Does PostgreSQL supports "SELECT... FOR UPDATE OF..." SQL? - postgresql

I am currently using "PostgreSQL 9.0.4" database with JDBC driver: "postgresql-9.0-801.jdbc4.jar".
I have the following JDBC SQL using "SELECT... FOR UPDATE OF..." clause which retrieves a column value (long) and updates the value by incrementing in same transaction.
I need to return the long value, thus I need to use SELECT Sql.
final PreparedStatement preparedStatement = _connection.prepareStatement(
"select value from sequence where table_name='JOB' for update of value",
ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
long ret;
try {
final ResultSet resultSet = preparedStatement.executeQuery();
resultSet.next();
ret = resultSet.getLong(1);
resultSet.updateLong(1, ret + 1);
resultSet.updateRow();
} catch (SQLException ex) {
ex.printStackTrace();
}
finally {
resultSet.close();
preparedStatement.close();
}
return ret;
All other databases e.g. MySQL, Oracle, MS-SQL, Derby work fine with such SQL - but PostgreSQL always throws following exception.
org.postgresql.util.PSQLException: ERROR: relation "value" in FOR UPDATE/SHARE clause not found in FROM clause
Position: 68
I do have the table "sequence" with the "value" column properly created - so this may not be the infamous case-sensitivity issue.
Does this mean Postgres does not support "SELECT ...FOR UPDATE OF.." SQL syntax?
In that case what will be the best way to achieve the same effect (i.e. select and update with the same transaction)?
Many thanks in advance,

Yes. It is supported. BUT the syntax is
FOR UPDATE [ OF table_name [, ...] ] [ NOWAIT ]
You can see more here:
http://www.postgresql.org/docs/8.2/static/sql-select.html#SQL-FOR-UPDATE-SHARE

Related

Remove "SELECT version();" query in Typeorm

I am using TypeORM in a AWS Lambda function and I am trying to optimise the performance of the Lambda function.
After enabling logging in TypeORM, I always see this query in the log:
INFO query: SELECT version();
...that seems to be done by TypeORM to check if the version of PostgreSQL supports generated columns:
const results = (await this.executeQuery(
connection,
"SELECT version();",
)) as {
rows: {
version: string
}[]
}
const versionString = results.rows[0].version.replace(
/^PostgreSQL ([\d\.]+) .*$/,
"$1",
)
this.version = versionString
this.isGeneratedColumnsSupported = VersionUtils.isGreaterOrEqual(
versionString,
"12.0",
)
https://github.com/typeorm/typeorm/blob/2473ff0a8eca2fafffdabd6fa4cc46b76347f0c2/src/driver/postgres/PostgresDriver.ts#L370
Now my question is: Is it possible to disable this check or cache the result or hardcode the value once for all to avoid this query every time we do run a DB query?
Thanks a lot.

How to use a list as a parameter source for SQL queries with Vertx JDBC Client?

I have a Vert.x web application that needs to query an AWS RDS instance running Postgres 10.7. The Vert.x JDBC client is io.vertx:vertx-jdbc-client:3.8.4. I want to query a table with the constraint that a certain column's value is included in a set of values:
select from table where column in/any (?)
I followed the Vertx documentation, which says to create a JsonArray and populate it with the values to inject into the query. The column is of type text and the list that I want to match on is a Java ArrayList<String>. My query code looks like:
String sql = "SELECT a FROM table WHERE col IN (?)";
List<String> values = someObject.someField();
sqlClient.getConnection(connectionResult -> {
if (connectionResult.failed()) {
// handle
} else {
SQLConnection connection = connectionResult.result();
JsonArray params = new JsonArray()
.add(values);
connection.queryWithParams(sql, params, queryResult -> {
if (queryResult.failed()) {
// handle
} else {
// parse
}
});
}
});
The query fails with the error: org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of io.vertx.core.json.JsonArray. Use setObject() with an explicit Types value to specify the type to use.
I know that in the worst case, I can create a literal SQL string where col in (?, ?, ?, ..., ?) and add each String from the list to a JsonArray, but there must be a way to just add the ArrayList<String> as a parameter and keep the query simple. How can I specify a list of values to match against in my query?
The Vert.x JDBC Client does not support array parameters in queries.
However it is possible with the Vert.x Pg Client, which does not depend on JDBC. You need to modify your query first:
SELECT a FROM table WHERE col = ANY(?)
Then:
pgClient.preparedQuery(query, Tuple.of(possibleValues), collector, handler);

Hibernate executeUpdate() throws exception for PostgreSQL native query with returning *

Hibernate executeUpdate() for insert or update native query with returning * gives and exception and also does not update the tables.
SQLQuery query = session.createSQLQuery(
"INSERT INTO public.account (username) VALUES ('xx'), ('yy'), ('zz') RETURNING user_id");
Transaction tx = session.beginTransaction();
query.executeUpdate();
tx.commit();
Exception:
org.postgresql.util.PSQLException: A result was returned when none was expected.
executeUpdate() is only appropriate if the SQL statement does not return result rows.
Use iterate(), list() or scroll() instead.

I can't get the getGeneratedKeys with the PostgreSQL JDBC driver

I'm blocked on a stupid problem in one of my functions.
I want to get the generatedKey of one of my Sql query. I can't and i don't understand why. The problem is that resultSet.next() it return false even if the line have been inserted when I check the data in the table.
Here is my code :
Statement statement = connection.createStatement();
statement.executeUpdate("INSERT INTO calamar.calamar.application (nom,criticite,autorise) VALUES ('"+nom+"','"+criticite+"','"+false+"');");
ResultSet resultSet = statement.getGeneratedKeys();
resultSet.next();
Solution : Add Statement.RETURN_GENERATED_KEYS
Statement statement = connection.createStatement();
statement.executeUpdate("INSERT INTO calamar.calamar.application (nom,criticite,autorise) VALUES ('"+nom+"','"+criticite+"','"+false+"');", Statement.RETURN_GENERATED_KEYS);
ResultSet resultSet = statement.getGeneratedKeys();
resultSet.next();

querying MS Access column properties with OleDb

I'm using OLE and C#.NET to query the schema of a MS Access database. Specifically, I need to find out whether a particular column is an "identity" column or not. For SQL Server, I can use:
select COLUMNPROPERTY(object_id('dbo.tablename'),'columnname','IsIdentity')
... but when I invoke this SQL against Access, I get an OleDbException with the following message:
Undefined function 'COLUMNPROPERTY' in expression.
Searching the archives, it appears there are ways to do this with DAO, but I need to use OLE. Anyone happen to know how I can do this with OLE?
You can get the schema from the connection, for example:
cn.GetOleDbSchemaTable(OleDbSchemaGuid.Indexes,
new Object[] { null, null, null, null, "Table1" });
Is the indexes for Table1. One of the fields returned is PRIMARY_KEY
See http://msdn.microsoft.com/en-us/library/system.data.oledb.oledbschemaguid.columns(v=vs.71)
The same using the GetSchema method.
using(OleDbConnection con = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;" +
"Data Source=C:\temp\db.mdb;" +
"Persist Security Info=False;"))
{
con.Open();
var schema = con.GetSchema("Indexes");
var col = schema.Select("TABLE_NAME = 'YourTableName' AND PRIMARY_KEY = True");
Console.WriteLine(col[0]["COLUMN_NAME"].ToString());
}