bug修改
This commit is contained in:
@ -142,6 +142,10 @@ Connection conn = DriverManager.getConnection(url);
|
|||||||
|
|
||||||
The driver supports the V3 frontend/backend protocols. The V3 protocol was introduced in 7.4 and
|
The driver supports the V3 frontend/backend protocols. The V3 protocol was introduced in 7.4 and
|
||||||
the driver will by default try to connect using the V3 protocol.
|
the driver will by default try to connect using the V3 protocol.
|
||||||
|
|
||||||
|
* **quoteReturningIdentifiers** = boolean
|
||||||
|
|
||||||
|
By default we double quote returning identifiers. Some ORM's alraedy allows quote them. Switch allows them to turn this off.
|
||||||
|
|
||||||
* **loggerLevel** = String
|
* **loggerLevel** = String
|
||||||
|
|
||||||
|
@ -61,6 +61,17 @@ public enum PGProperty {
|
|||||||
"Force use of a particular protocol version when connecting, currently only version 3 is supported.",
|
"Force use of a particular protocol version when connecting, currently only version 3 is supported.",
|
||||||
false, "3"),
|
false, "3"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quote returning columns.
|
||||||
|
* There are some ORM's that quote everything, including returning columns
|
||||||
|
* If we quote them, then we end up sending ""colname"" to the backend
|
||||||
|
* which will not be found
|
||||||
|
*/
|
||||||
|
QUOTE_RETURNING_IDENTIFIERS("quoteReturningIdentifiers",
|
||||||
|
"true",
|
||||||
|
"Quote identifiers provided in returning array",
|
||||||
|
false),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Logger level of the driver. Allowed values: {@code OFF}, {@code DEBUG} or {@code TRACE}.</p>
|
* <p>Logger level of the driver. Allowed values: {@code OFF}, {@code DEBUG} or {@code TRACE}.</p>
|
||||||
*
|
*
|
||||||
|
@ -7,6 +7,8 @@ package org.postgresql.core;
|
|||||||
|
|
||||||
import org.postgresql.util.CanEstimateSize;
|
import org.postgresql.util.CanEstimateSize;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores information on the parsed JDBC query. It is used to cut parsing overhead when executing
|
* Stores information on the parsed JDBC query. It is used to cut parsing overhead when executing
|
||||||
* the same query through {@link java.sql.Connection#prepareStatement(String)}.
|
* the same query through {@link java.sql.Connection#prepareStatement(String)}.
|
||||||
@ -20,7 +22,8 @@ public class CachedQuery implements CanEstimateSize {
|
|||||||
public final boolean isFunction;
|
public final boolean isFunction;
|
||||||
public final boolean isACompatibilityFunction;
|
public final boolean isACompatibilityFunction;
|
||||||
private int executeCount;
|
private int executeCount;
|
||||||
|
// record queries after rewrite
|
||||||
|
private final ArrayList<Query> rewriteQueries = new ArrayList<>();
|
||||||
public CachedQuery(Object key, Query query, boolean isFunction, boolean isACompatibilityFunction) {
|
public CachedQuery(Object key, Query query, boolean isFunction, boolean isACompatibilityFunction) {
|
||||||
assert key instanceof String || key instanceof CanEstimateSize
|
assert key instanceof String || key instanceof CanEstimateSize
|
||||||
: "CachedQuery.key should either be String or implement CanEstimateSize."
|
: "CachedQuery.key should either be String or implement CanEstimateSize."
|
||||||
@ -66,6 +69,42 @@ public class CachedQuery implements CanEstimateSize {
|
|||||||
+ 100L /* entry in hash map, CachedQuery wrapper, etc */;
|
+ 100L /* entry in hash map, CachedQuery wrapper, etc */;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* add rewrite query to list
|
||||||
|
*
|
||||||
|
* @param query the query to add
|
||||||
|
*/
|
||||||
|
public void addRewriteQueries(Query query) {
|
||||||
|
rewriteQueries.add(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get rewrite queries list
|
||||||
|
*
|
||||||
|
* @return rewrite queries list
|
||||||
|
*/
|
||||||
|
public ArrayList<Query> getRewriteQueries() {
|
||||||
|
return rewriteQueries;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if rewrite queries list empty
|
||||||
|
*
|
||||||
|
* @return check result
|
||||||
|
*/
|
||||||
|
public boolean isRewriteQueriesEmpty() {
|
||||||
|
return rewriteQueries.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clear rewrite queries
|
||||||
|
*/
|
||||||
|
public void clearRewriteQueries() {
|
||||||
|
if (rewriteQueries.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
rewriteQueries.clear();
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "CachedQuery{"
|
return "CachedQuery{"
|
||||||
|
@ -65,7 +65,8 @@ class CachedQueryCreateAction implements LruCache.CreateAction<Object, CachedQue
|
|||||||
|
|
||||||
List<NativeQuery> queries = Parser.parseJdbcSql(parsedSql,
|
List<NativeQuery> queries = Parser.parseJdbcSql(parsedSql,
|
||||||
queryExecutor.getStandardConformingStrings(), isParameterized, splitStatements,
|
queryExecutor.getStandardConformingStrings(), isParameterized, splitStatements,
|
||||||
queryExecutor.isReWriteBatchedInsertsEnabled(), returningColumns);
|
queryExecutor.isReWriteBatchedInsertsEnabled(), queryExecutor.getQuoteReturningIdentifiers(),
|
||||||
|
returningColumns);
|
||||||
|
|
||||||
Query query = queryExecutor.wrap(queries);
|
Query query = queryExecutor.wrap(queries);
|
||||||
return new CachedQuery(key, query, isFunction, isACompatibilityFunction);
|
return new CachedQuery(key, query, isFunction, isACompatibilityFunction);
|
||||||
|
@ -51,6 +51,7 @@ public class Parser {
|
|||||||
* @param withParameters whether to replace ?, ? with $1, $2, etc
|
* @param withParameters whether to replace ?, ? with $1, $2, etc
|
||||||
* @param splitStatements whether to split statements by semicolon
|
* @param splitStatements whether to split statements by semicolon
|
||||||
* @param isBatchedReWriteConfigured whether re-write optimization is enabled
|
* @param isBatchedReWriteConfigured whether re-write optimization is enabled
|
||||||
|
* @param isQuotedReturningIdentifiers whether to quote identifiers returned using returning clause
|
||||||
* @param returningColumnNames for simple insert, update, delete add returning with given column names
|
* @param returningColumnNames for simple insert, update, delete add returning with given column names
|
||||||
* @return list of native queries
|
* @return list of native queries
|
||||||
* @throws SQLException if unable to add returning clause (invalid column names)
|
* @throws SQLException if unable to add returning clause (invalid column names)
|
||||||
@ -58,6 +59,7 @@ public class Parser {
|
|||||||
public static List<NativeQuery> parseJdbcSql(String query, boolean standardConformingStrings,
|
public static List<NativeQuery> parseJdbcSql(String query, boolean standardConformingStrings,
|
||||||
boolean withParameters, boolean splitStatements,
|
boolean withParameters, boolean splitStatements,
|
||||||
boolean isBatchedReWriteConfigured,
|
boolean isBatchedReWriteConfigured,
|
||||||
|
boolean isQuotedReturningIdentifiers,
|
||||||
String... returningColumnNames) throws SQLException {
|
String... returningColumnNames) throws SQLException {
|
||||||
int numOfOverSymble = 0;
|
int numOfOverSymble = 0;
|
||||||
if(startWithComment(query)) {
|
if(startWithComment(query)) {
|
||||||
@ -151,8 +153,8 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
fragmentStart = i + 1;
|
fragmentStart = i + 1;
|
||||||
if (nativeSql.length() > 0) {
|
if (nativeSql.length() > 0) {
|
||||||
if (addReturning(
|
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent,
|
||||||
nativeSql, currentCommandType, returningColumnNames, isReturningPresent)) {
|
isQuotedReturningIdentifiers)) {
|
||||||
isReturningPresent = true;
|
isReturningPresent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +258,8 @@ public class Parser {
|
|||||||
}
|
}
|
||||||
fragmentStart = i + 1;
|
fragmentStart = i + 1;
|
||||||
if (nativeSql.length() > 0) {
|
if (nativeSql.length() > 0) {
|
||||||
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent)) {
|
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent,
|
||||||
|
isQuotedReturningIdentifiers)) {
|
||||||
isReturningPresent = true;
|
isReturningPresent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +381,7 @@ public class Parser {
|
|||||||
if (inParen != 0 || aChar == ')') {
|
if (inParen != 0 || aChar == ')') {
|
||||||
// RETURNING and VALUES cannot be present in braces
|
// RETURNING and VALUES cannot be present in braces
|
||||||
} else if (wordLength == 9 && parseReturningKeyword(aChars, keywordStart)) {
|
} else if (wordLength == 9 && parseReturningKeyword(aChars, keywordStart)) {
|
||||||
isReturningPresent = true;
|
isReturningPresent = true;
|
||||||
} else if (wordLength == 6 && parseValuesKeyword(aChars, keywordStart)) {
|
} else if (wordLength == 6 && parseValuesKeyword(aChars, keywordStart)) {
|
||||||
isValuesFound = true;
|
isValuesFound = true;
|
||||||
}
|
}
|
||||||
@ -416,7 +419,8 @@ public class Parser {
|
|||||||
return nativeQueries != null ? nativeQueries : Collections.<NativeQuery>emptyList();
|
return nativeQueries != null ? nativeQueries : Collections.<NativeQuery>emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent)) {
|
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent,
|
||||||
|
isQuotedReturningIdentifiers)) {
|
||||||
isReturningPresent = true;
|
isReturningPresent = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -525,8 +529,9 @@ public class Parser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean addReturning(StringBuilder nativeSql, SqlCommandType currentCommandType,
|
private static boolean addReturning(StringBuilder nativeSql, SqlCommandType currentCommandType,
|
||||||
String[] returningColumnNames, boolean isReturningPresent) throws SQLException {
|
String[] returningColumnNames, boolean isReturningPresent, boolean isQuotedReturningIdentifiers)
|
||||||
|
throws SQLException {
|
||||||
if (isReturningPresent || returningColumnNames.length == 0) {
|
if (isReturningPresent || returningColumnNames.length == 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -547,7 +552,11 @@ public class Parser {
|
|||||||
if (col > 0) {
|
if (col > 0) {
|
||||||
nativeSql.append(", ");
|
nativeSql.append(", ");
|
||||||
}
|
}
|
||||||
Utils.escapeIdentifier(nativeSql, columnName);
|
if (isQuotedReturningIdentifiers) {
|
||||||
|
Utils.escapeIdentifier(nativeSql, columnName);
|
||||||
|
} else {
|
||||||
|
nativeSql.append(columnName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -670,6 +679,7 @@ public class Parser {
|
|||||||
case "PROCEDURE":
|
case "PROCEDURE":
|
||||||
case "FUNCTION":
|
case "FUNCTION":
|
||||||
case "DECLARE":
|
case "DECLARE":
|
||||||
|
case "TRIGGER":
|
||||||
return true;
|
return true;
|
||||||
case "CREATE":
|
case "CREATE":
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
@ -897,6 +907,7 @@ public class Parser {
|
|||||||
&& (query[offset + 8] | 32) == 'g';
|
&& (query[offset + 8] | 32) == 'g';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse string to check presence of SELECT keyword regardless of case.
|
* Parse string to check presence of SELECT keyword regardless of case.
|
||||||
*
|
*
|
||||||
|
@ -445,6 +445,12 @@ public interface QueryExecutor extends TypeTransferModeRegistry {
|
|||||||
boolean getStandardConformingStrings();
|
boolean getStandardConformingStrings();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* get quote identifier
|
||||||
|
*
|
||||||
|
* @return true if we are going to quote identifier provided in the returning array default is true
|
||||||
|
*/
|
||||||
|
boolean getQuoteReturningIdentifiers();
|
||||||
|
/**
|
||||||
* Returns backend timezone in java format.
|
* Returns backend timezone in java format.
|
||||||
* @return backend timezone in java format.
|
* @return backend timezone in java format.
|
||||||
*/
|
*/
|
||||||
|
@ -41,6 +41,7 @@ public abstract class QueryExecutorBase implements QueryExecutor {
|
|||||||
private TransactionState transactionState;
|
private TransactionState transactionState;
|
||||||
private final boolean reWriteBatchedInserts;
|
private final boolean reWriteBatchedInserts;
|
||||||
private final boolean columnSanitiserDisabled;
|
private final boolean columnSanitiserDisabled;
|
||||||
|
private final boolean isQuotedReturningIdentifiers;
|
||||||
private final PreferQueryMode preferQueryMode;
|
private final PreferQueryMode preferQueryMode;
|
||||||
private AutoSave autoSave;
|
private AutoSave autoSave;
|
||||||
private boolean flushCacheOnDeallocate = true;
|
private boolean flushCacheOnDeallocate = true;
|
||||||
@ -64,22 +65,29 @@ public abstract class QueryExecutorBase implements QueryExecutor {
|
|||||||
this.cancelSignalTimeout = cancelSignalTimeout;
|
this.cancelSignalTimeout = cancelSignalTimeout;
|
||||||
this.reWriteBatchedInserts = PGProperty.REWRITE_BATCHED_INSERTS.getBoolean(info);
|
this.reWriteBatchedInserts = PGProperty.REWRITE_BATCHED_INSERTS.getBoolean(info);
|
||||||
this.columnSanitiserDisabled = PGProperty.DISABLE_COLUMN_SANITISER.getBoolean(info);
|
this.columnSanitiserDisabled = PGProperty.DISABLE_COLUMN_SANITISER.getBoolean(info);
|
||||||
|
this.isQuotedReturningIdentifiers = PGProperty.QUOTE_RETURNING_IDENTIFIERS.getBoolean(info);
|
||||||
String preferMode = PGProperty.PREFER_QUERY_MODE.get(info);
|
String preferMode = PGProperty.PREFER_QUERY_MODE.get(info);
|
||||||
this.preferQueryMode = PreferQueryMode.of(preferMode);
|
this.preferQueryMode = PreferQueryMode.of(preferMode);
|
||||||
this.autoSave = AutoSave.of(PGProperty.AUTOSAVE.get(info));
|
this.autoSave = AutoSave.of(PGProperty.AUTOSAVE.get(info));
|
||||||
this.cachedQueryCreateAction = new CachedQueryCreateAction(this);
|
this.cachedQueryCreateAction = new CachedQueryCreateAction(this);
|
||||||
this.props = info;
|
this.props = info;
|
||||||
statementCache = new LruCache<Object, CachedQuery>(
|
statementCache = new LruCache<Object, CachedQuery>(
|
||||||
Math.max(0, PGProperty.PREPARED_STATEMENT_CACHE_QUERIES.getInt(info)),
|
Math.max(0, PGProperty.PREPARED_STATEMENT_CACHE_QUERIES.getInt(info)),
|
||||||
Math.max(0, PGProperty.PREPARED_STATEMENT_CACHE_SIZE_MIB.getInt(info) * 1024 * 1024),
|
Math.max(0, PGProperty.PREPARED_STATEMENT_CACHE_SIZE_MIB.getInt(info) * 1024 * 1024),
|
||||||
false,
|
false,
|
||||||
cachedQueryCreateAction,
|
cachedQueryCreateAction,
|
||||||
new LruCache.EvictAction<CachedQuery>() {
|
new LruCache.EvictAction<CachedQuery>() {
|
||||||
@Override
|
@Override
|
||||||
public void evict(CachedQuery cachedQuery) throws SQLException {
|
public void evict(CachedQuery cachedQuery) throws SQLException {
|
||||||
cachedQuery.query.close();
|
cachedQuery.query.close();
|
||||||
}
|
if (!cachedQuery.isRewriteQueriesEmpty()) {
|
||||||
});
|
for (Query query : cachedQuery.getRewriteQueries()) {
|
||||||
|
query.close();
|
||||||
|
}
|
||||||
|
cachedQuery.clearRewriteQueries();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void sendCloseMessage() throws IOException;
|
protected abstract void sendCloseMessage() throws IOException;
|
||||||
@ -261,6 +269,11 @@ public abstract class QueryExecutorBase implements QueryExecutor {
|
|||||||
return standardConformingStrings;
|
return standardConformingStrings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getQuoteReturningIdentifiers() {
|
||||||
|
return isQuotedReturningIdentifiers;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized TransactionState getTransactionState() {
|
public synchronized TransactionState getTransactionState() {
|
||||||
return transactionState;
|
return transactionState;
|
||||||
|
@ -5,10 +5,10 @@
|
|||||||
|
|
||||||
package org.postgresql.core.v3;
|
package org.postgresql.core.v3;
|
||||||
|
|
||||||
|
import org.postgresql.core.CachedQuery;
|
||||||
import org.postgresql.core.NativeQuery;
|
import org.postgresql.core.NativeQuery;
|
||||||
import org.postgresql.core.ParameterList;
|
import org.postgresql.core.ParameterList;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Purpose of this object is to support batched query re write behaviour. Responsibility for
|
* Purpose of this object is to support batched query re write behaviour. Responsibility for
|
||||||
* tracking the batch size and implement the clean up of the query fragments after the batch execute
|
* tracking the batch size and implement the clean up of the query fragments after the batch execute
|
||||||
@ -27,6 +27,8 @@ public class BatchedQuery extends SimpleQuery {
|
|||||||
private final int batchSize;
|
private final int batchSize;
|
||||||
private BatchedQuery[] blocks;
|
private BatchedQuery[] blocks;
|
||||||
|
|
||||||
|
// record the origin query of the rewrite query
|
||||||
|
private CachedQuery originalPrepareQuery;
|
||||||
public BatchedQuery(NativeQuery query, TypeTransferModeRegistry transferModeRegistry,
|
public BatchedQuery(NativeQuery query, TypeTransferModeRegistry transferModeRegistry,
|
||||||
int valuesBraceOpenPosition,
|
int valuesBraceOpenPosition,
|
||||||
int valuesBraceClosePosition, boolean sanitiserDisabled) {
|
int valuesBraceClosePosition, boolean sanitiserDisabled) {
|
||||||
@ -85,6 +87,24 @@ public class BatchedQuery extends SimpleQuery {
|
|||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get original prepareQuery
|
||||||
|
*
|
||||||
|
* @return the originalPrepareQuery
|
||||||
|
*/
|
||||||
|
public CachedQuery getOriginalPrepareQuery() {
|
||||||
|
return originalPrepareQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set original prepareQuery
|
||||||
|
*
|
||||||
|
* @param originalPrepareQuery the originalPrepareQuery to be set
|
||||||
|
*/
|
||||||
|
public void setOriginalPrepareQuery(CachedQuery originalPrepareQuery) {
|
||||||
|
this.originalPrepareQuery = originalPrepareQuery;
|
||||||
|
}
|
||||||
|
|
||||||
private String buildNativeSql(ParameterList params) {
|
private String buildNativeSql(ParameterList params) {
|
||||||
String buildSql = null;
|
String buildSql = null;
|
||||||
// dynamically build sql with parameters for batches
|
// dynamically build sql with parameters for batches
|
||||||
|
@ -10,6 +10,7 @@ import org.postgresql.PGProperty;
|
|||||||
import org.postgresql.copy.CopyIn;
|
import org.postgresql.copy.CopyIn;
|
||||||
import org.postgresql.copy.CopyOperation;
|
import org.postgresql.copy.CopyOperation;
|
||||||
import org.postgresql.copy.CopyOut;
|
import org.postgresql.copy.CopyOut;
|
||||||
|
import org.postgresql.core.CachedQuery;
|
||||||
import org.postgresql.core.CommandCompleteParser;
|
import org.postgresql.core.CommandCompleteParser;
|
||||||
import org.postgresql.core.Encoding;
|
import org.postgresql.core.Encoding;
|
||||||
import org.postgresql.core.EncodingPredictor;
|
import org.postgresql.core.EncodingPredictor;
|
||||||
@ -283,7 +284,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
public Query createSimpleQuery(String sql) throws SQLException {
|
public Query createSimpleQuery(String sql) throws SQLException {
|
||||||
List<NativeQuery> queries = Parser.parseJdbcSql(sql,
|
List<NativeQuery> queries = Parser.parseJdbcSql(sql,
|
||||||
getStandardConformingStrings(), false, true,
|
getStandardConformingStrings(), false, true,
|
||||||
isReWriteBatchedInsertsEnabled());
|
isReWriteBatchedInsertsEnabled(), getQuoteReturningIdentifiers());
|
||||||
return wrap(queries);
|
return wrap(queries);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1553,6 +1554,17 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
pendingDescribePortalQueue.add(sync);
|
pendingDescribePortalQueue.add(sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkAndUpdateRewriteQueries(SimpleQuery query) {
|
||||||
|
if (!(query instanceof BatchedQuery)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
BatchedQuery batchedQuery = (BatchedQuery) query;
|
||||||
|
CachedQuery originalPrepareQuery = batchedQuery.getOriginalPrepareQuery();
|
||||||
|
if (originalPrepareQuery == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
originalPrepareQuery.addRewriteQueries(batchedQuery);
|
||||||
|
}
|
||||||
private void sendParse(SimpleQuery query, SimpleParameterList params, boolean oneShot)
|
private void sendParse(SimpleQuery query, SimpleParameterList params, boolean oneShot)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
// Already parsed, or we have a Parse pending and the types are right?
|
// Already parsed, or we have a Parse pending and the types are right?
|
||||||
@ -1582,6 +1594,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
|
|||||||
query.setStatementName(statementName, deallocateEpoch, getClientEncoding());
|
query.setStatementName(statementName, deallocateEpoch, getClientEncoding());
|
||||||
query.setPrepareTypes(typeOIDs);
|
query.setPrepareTypes(typeOIDs);
|
||||||
registerParsedQuery(query, statementName);
|
registerParsedQuery(query, statementName);
|
||||||
|
checkAndUpdateRewriteQueries(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] encodedStatementName = query.getEncodedStatementName();
|
byte[] encodedStatementName = query.getEncodedStatementName();
|
||||||
|
@ -322,6 +322,22 @@ public abstract class BaseDataSource implements CommonDataSource, Referenceable
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @return quoteReturningIdentifiers
|
||||||
|
* @see PGProperty#QUOTE_RETURNING_IDENTIFIERS
|
||||||
|
*/
|
||||||
|
public boolean getQuoteReturningIdentifiers() {
|
||||||
|
return PGProperty.QUOTE_RETURNING_IDENTIFIERS.getBoolean(properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param isQuotedIdentifiers indicate whether to quote identifiers
|
||||||
|
* @see PGProperty#QUOTE_RETURNING_IDENTIFIERS
|
||||||
|
*/
|
||||||
|
public void setQuoteReturningIdentifiers(boolean isQuotedIdentifiers) {
|
||||||
|
PGProperty.QUOTE_RETURNING_IDENTIFIERS.set(properties, isQuotedIdentifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* @return receive buffer size
|
* @return receive buffer size
|
||||||
* @see PGProperty#RECEIVE_BUFFER_SIZE
|
* @see PGProperty#RECEIVE_BUFFER_SIZE
|
||||||
*/
|
*/
|
||||||
|
@ -243,7 +243,7 @@ public class ClientLogic {
|
|||||||
//Replace the query syntax from jdbc syntax with ? for bind parameters to $1 $2 ... $n
|
//Replace the query syntax from jdbc syntax with ? for bind parameters to $1 $2 ... $n
|
||||||
List<NativeQuery> queries;
|
List<NativeQuery> queries;
|
||||||
try {
|
try {
|
||||||
queries = Parser.parseJdbcSql(query, true, true, true, true);
|
queries = Parser.parseJdbcSql(query, true, true, true, true, true);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new ClientLogicException(ERROR_PARSER_FAILURE, ERROR_TEXT_PARSER_FAILURE, true);
|
throw new ClientLogicException(ERROR_PARSER_FAILURE, ERROR_TEXT_PARSER_FAILURE, true);
|
||||||
}
|
}
|
||||||
|
@ -1725,6 +1725,7 @@ class PgPreparedStatement extends PgStatement implements PreparedStatement {
|
|||||||
}
|
}
|
||||||
// Find appropriate batch for block count.
|
// Find appropriate batch for block count.
|
||||||
BatchedQuery bq = originalQuery.deriveForMultiBatch(valueBlock);
|
BatchedQuery bq = originalQuery.deriveForMultiBatch(valueBlock);
|
||||||
|
bq.setOriginalPrepareQuery(preparedQuery);
|
||||||
ParameterList newPl = bq.createParameterList();
|
ParameterList newPl = bq.createParameterList();
|
||||||
for (int j = 0; j < valueBlock; j++) {
|
for (int j = 0; j < valueBlock; j++) {
|
||||||
ParameterList pl = batchParameters.get(offset++);
|
ParameterList pl = batchParameters.get(offset++);
|
||||||
|
@ -155,7 +155,7 @@ public class ParserTest {
|
|||||||
"insert test(id, name) select 1, 'value' as RETURNING from test2";
|
"insert test(id, name) select 1, 'value' as RETURNING from test2";
|
||||||
List<NativeQuery> qry =
|
List<NativeQuery> qry =
|
||||||
Parser.parseJdbcSql(
|
Parser.parseJdbcSql(
|
||||||
query, true, true, true, true);
|
query, true, true, true, true, true);
|
||||||
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
|
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
|
||||||
Assert.assertFalse("Query does not have returning clause " + query, returningKeywordPresent);
|
Assert.assertFalse("Query does not have returning clause " + query, returningKeywordPresent);
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ public class ParserTest {
|
|||||||
"insert test(id, name) select 1, 'value' from test2 RETURNING id";
|
"insert test(id, name) select 1, 'value' from test2 RETURNING id";
|
||||||
List<NativeQuery> qry =
|
List<NativeQuery> qry =
|
||||||
Parser.parseJdbcSql(
|
Parser.parseJdbcSql(
|
||||||
query, true, true, true, true);
|
query, true, true, true, true, true);
|
||||||
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
|
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
|
||||||
Assert.assertTrue("Query has a returning clause " + query, returningKeywordPresent);
|
Assert.assertTrue("Query has a returning clause " + query, returningKeywordPresent);
|
||||||
}
|
}
|
||||||
@ -177,7 +177,7 @@ public class ParserTest {
|
|||||||
"with x as (insert into mytab(x) values(1) returning x) insert test(id, name) select 1, 'value' from test2";
|
"with x as (insert into mytab(x) values(1) returning x) insert test(id, name) select 1, 'value' from test2";
|
||||||
List<NativeQuery> qry =
|
List<NativeQuery> qry =
|
||||||
Parser.parseJdbcSql(
|
Parser.parseJdbcSql(
|
||||||
query, true, true, true, true);
|
query, true, true, true, true, true);
|
||||||
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
|
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
|
||||||
Assert.assertFalse("There's no top-level <<returning>> clause " + query, returningKeywordPresent);
|
Assert.assertFalse("There's no top-level <<returning>> clause " + query, returningKeywordPresent);
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ public class ParserTest {
|
|||||||
@Test
|
@Test
|
||||||
public void insertBatchedReWriteOnConflict() throws SQLException {
|
public void insertBatchedReWriteOnConflict() throws SQLException {
|
||||||
String query = "insert into test(id, name) values (:id,:name) ON CONFLICT (id) DO NOTHING";
|
String query = "insert into test(id, name) values (:id,:name) ON CONFLICT (id) DO NOTHING";
|
||||||
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true);
|
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true, true);
|
||||||
SqlCommand command = qry.get(0).getCommand();
|
SqlCommand command = qry.get(0).getCommand();
|
||||||
Assert.assertEquals(34, command.getBatchRewriteValuesBraceOpenPosition());
|
Assert.assertEquals(34, command.getBatchRewriteValuesBraceOpenPosition());
|
||||||
Assert.assertEquals(44, command.getBatchRewriteValuesBraceClosePosition());
|
Assert.assertEquals(44, command.getBatchRewriteValuesBraceClosePosition());
|
||||||
@ -194,7 +194,7 @@ public class ParserTest {
|
|||||||
@Test
|
@Test
|
||||||
public void insertBatchedReWriteOnConflictUpdateBind() throws SQLException {
|
public void insertBatchedReWriteOnConflictUpdateBind() throws SQLException {
|
||||||
String query = "insert into test(id, name) values (?,?) ON CONFLICT (id) UPDATE SET name=?";
|
String query = "insert into test(id, name) values (?,?) ON CONFLICT (id) UPDATE SET name=?";
|
||||||
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true);
|
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true, true);
|
||||||
SqlCommand command = qry.get(0).getCommand();
|
SqlCommand command = qry.get(0).getCommand();
|
||||||
Assert.assertFalse("update set name=? is NOT compatible with insert rewrite", command.isBatchedReWriteCompatible());
|
Assert.assertFalse("update set name=? is NOT compatible with insert rewrite", command.isBatchedReWriteCompatible());
|
||||||
}
|
}
|
||||||
@ -202,7 +202,7 @@ public class ParserTest {
|
|||||||
@Test
|
@Test
|
||||||
public void insertBatchedReWriteOnConflictUpdateConstant() throws SQLException {
|
public void insertBatchedReWriteOnConflictUpdateConstant() throws SQLException {
|
||||||
String query = "insert into test(id, name) values (?,?) ON CONFLICT (id) UPDATE SET name='default'";
|
String query = "insert into test(id, name) values (?,?) ON CONFLICT (id) UPDATE SET name='default'";
|
||||||
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true);
|
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true, true);
|
||||||
SqlCommand command = qry.get(0).getCommand();
|
SqlCommand command = qry.get(0).getCommand();
|
||||||
Assert.assertTrue("update set name='default' is compatible with insert rewrite", command.isBatchedReWriteCompatible());
|
Assert.assertTrue("update set name='default' is compatible with insert rewrite", command.isBatchedReWriteCompatible());
|
||||||
}
|
}
|
||||||
@ -211,7 +211,7 @@ public class ParserTest {
|
|||||||
public void insertMultiInsert() throws SQLException {
|
public void insertMultiInsert() throws SQLException {
|
||||||
String query =
|
String query =
|
||||||
"insert into test(id, name) values (:id,:name),(:id,:name) ON CONFLICT (id) DO NOTHING";
|
"insert into test(id, name) values (:id,:name),(:id,:name) ON CONFLICT (id) DO NOTHING";
|
||||||
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true);
|
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true, true);
|
||||||
SqlCommand command = qry.get(0).getCommand();
|
SqlCommand command = qry.get(0).getCommand();
|
||||||
Assert.assertEquals(34, command.getBatchRewriteValuesBraceOpenPosition());
|
Assert.assertEquals(34, command.getBatchRewriteValuesBraceOpenPosition());
|
||||||
Assert.assertEquals(56, command.getBatchRewriteValuesBraceClosePosition());
|
Assert.assertEquals(56, command.getBatchRewriteValuesBraceClosePosition());
|
||||||
@ -241,7 +241,7 @@ public class ParserTest {
|
|||||||
for (String mySql: sqlTests) {
|
for (String mySql: sqlTests) {
|
||||||
List<NativeQuery> queries = Parser.parseJdbcSql(mySql,
|
List<NativeQuery> queries = Parser.parseJdbcSql(mySql,
|
||||||
false,false,
|
false,false,
|
||||||
true, false, new String[0]);
|
true, false, true, new String[0]);
|
||||||
assertEquals(1, queries.size());
|
assertEquals(1, queries.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public class ReturningParserTest {
|
|||||||
String query =
|
String query =
|
||||||
"insert into\"prep\"(a, " + prefix + columnName + suffix + ")values(1,2)" + prefix
|
"insert into\"prep\"(a, " + prefix + columnName + suffix + ")values(1,2)" + prefix
|
||||||
+ returning + suffix;
|
+ returning + suffix;
|
||||||
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true);
|
List<NativeQuery> qry = Parser.parseJdbcSql(query, true, true, true, true, true);
|
||||||
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
|
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
|
||||||
|
|
||||||
boolean expectedReturning = this.returning.equalsIgnoreCase("returning")
|
boolean expectedReturning = this.returning.equalsIgnoreCase("returning")
|
||||||
|
@ -387,6 +387,7 @@ public class TestUtil {
|
|||||||
props.put(PGProperty.PREFER_QUERY_MODE.getName(), value);
|
props.put(PGProperty.PREFER_QUERY_MODE.getName(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
PGProperty.QUOTE_RETURNING_IDENTIFIERS.set(props, false);
|
||||||
// Enable Base4 tests to override host,port,database
|
// Enable Base4 tests to override host,port,database
|
||||||
String hostport = props.getProperty(SERVER_HOST_PORT_PROP, getServer() + ":" + getPort());
|
String hostport = props.getProperty(SERVER_HOST_PORT_PROP, getServer() + ":" + getPort());
|
||||||
String database = props.getProperty(DATABASE_PROP, getDatabase());
|
String database = props.getProperty(DATABASE_PROP, getDatabase());
|
||||||
|
@ -95,16 +95,16 @@ public class CompositeQueryParseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testHasReturning() throws SQLException {
|
public void testHasReturning() throws SQLException {
|
||||||
List<NativeQuery> queries = Parser.parseJdbcSql("insert into foo (a,b,c) values (?,?,?) RetuRning a", true, true, false,
|
List<NativeQuery> queries = Parser.parseJdbcSql("insert into foo (a,b,c) values (?,?,?) RetuRning a", true, true, false,
|
||||||
true);
|
true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertTrue("The parser should find the word returning", query.command.isReturningKeywordPresent());
|
assertTrue("The parser should find the word returning", query.command.isReturningKeywordPresent());
|
||||||
|
|
||||||
queries = Parser.parseJdbcSql("insert into foo (a,b,c) values (?,?,?)", true, true, false, true);
|
queries = Parser.parseJdbcSql("insert into foo (a,b,c) values (?,?,?)", true, true, false, true, true);
|
||||||
query = queries.get(0);
|
query = queries.get(0);
|
||||||
assertFalse("The parser should not find the word returning", query.command.isReturningKeywordPresent());
|
assertFalse("The parser should not find the word returning", query.command.isReturningKeywordPresent());
|
||||||
|
|
||||||
queries = Parser.parseJdbcSql("insert into foo (a,b,c) values ('returning',?,?)", true, true, false,
|
queries = Parser.parseJdbcSql("insert into foo (a,b,c) values ('returning',?,?)", true, true, false,
|
||||||
true);
|
true, true);
|
||||||
query = queries.get(0);
|
query = queries.get(0);
|
||||||
assertFalse("The parser should not find the word returning as it is in quotes ", query.command.isReturningKeywordPresent());
|
assertFalse("The parser should not find the word returning as it is in quotes ", query.command.isReturningKeywordPresent());
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ public class CompositeQueryParseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testSelect() throws SQLException {
|
public void testSelect() throws SQLException {
|
||||||
List<NativeQuery> queries;
|
List<NativeQuery> queries;
|
||||||
queries = Parser.parseJdbcSql("select 1 as returning from (update table)", true, true, false, true);
|
queries = Parser.parseJdbcSql("select 1 as returning from (update table)", true, true, false, true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertEquals("This is a select ", SqlCommandType.SELECT, query.command.getType());
|
assertEquals("This is a select ", SqlCommandType.SELECT, query.command.getType());
|
||||||
assertTrue("Returning is OK here as it is not an insert command ", query.command.isReturningKeywordPresent());
|
assertTrue("Returning is OK here as it is not an insert command ", query.command.isReturningKeywordPresent());
|
||||||
@ -121,7 +121,7 @@ public class CompositeQueryParseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testDelete() throws SQLException {
|
public void testDelete() throws SQLException {
|
||||||
List<NativeQuery> queries = Parser.parseJdbcSql("DeLeTe from foo where a=1", true, true, false,
|
List<NativeQuery> queries = Parser.parseJdbcSql("DeLeTe from foo where a=1", true, true, false,
|
||||||
true);
|
true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertEquals("This is a delete command", SqlCommandType.DELETE, query.command.getType());
|
assertEquals("This is a delete command", SqlCommandType.DELETE, query.command.getType());
|
||||||
}
|
}
|
||||||
@ -130,7 +130,7 @@ public class CompositeQueryParseTest {
|
|||||||
public void testMultiQueryWithBind() throws SQLException {
|
public void testMultiQueryWithBind() throws SQLException {
|
||||||
// braces around (42) are required to puzzle the parser
|
// braces around (42) are required to puzzle the parser
|
||||||
String sql = "INSERT INTO inttable(a) VALUES (?);SELECT (42)";
|
String sql = "INSERT INTO inttable(a) VALUES (?);SELECT (42)";
|
||||||
List<NativeQuery> queries = Parser.parseJdbcSql(sql, true, true, true,true);
|
List<NativeQuery> queries = Parser.parseJdbcSql(sql, true, true, true,true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertEquals("query(0) of " + sql,
|
assertEquals("query(0) of " + sql,
|
||||||
"INSERT: INSERT INTO inttable(a) VALUES ($1)",
|
"INSERT: INSERT INTO inttable(a) VALUES ($1)",
|
||||||
@ -143,7 +143,7 @@ public class CompositeQueryParseTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMove() throws SQLException {
|
public void testMove() throws SQLException {
|
||||||
List<NativeQuery> queries = Parser.parseJdbcSql("MoVe NEXT FROM FOO", true, true, false, true);
|
List<NativeQuery> queries = Parser.parseJdbcSql("MoVe NEXT FROM FOO", true, true, false, true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertEquals("This is a move command", SqlCommandType.MOVE, query.command.getType());
|
assertEquals("This is a move command", SqlCommandType.MOVE, query.command.getType());
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ public class CompositeQueryParseTest {
|
|||||||
public void testUpdate() throws SQLException {
|
public void testUpdate() throws SQLException {
|
||||||
List<NativeQuery> queries;
|
List<NativeQuery> queries;
|
||||||
NativeQuery query;
|
NativeQuery query;
|
||||||
queries = Parser.parseJdbcSql("update foo set (a=?,b=?,c=?)", true, true, false, true);
|
queries = Parser.parseJdbcSql("update foo set (a=?,b=?,c=?)", true, true, false, true, true);
|
||||||
query = queries.get(0);
|
query = queries.get(0);
|
||||||
assertEquals("This is an UPDATE command", SqlCommandType.UPDATE, query.command.getType());
|
assertEquals("This is an UPDATE command", SqlCommandType.UPDATE, query.command.getType());
|
||||||
}
|
}
|
||||||
@ -160,11 +160,11 @@ public class CompositeQueryParseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testInsert() throws SQLException {
|
public void testInsert() throws SQLException {
|
||||||
List<NativeQuery> queries = Parser.parseJdbcSql("InSeRt into foo (a,b,c) values (?,?,?) returning a", true, true, false,
|
List<NativeQuery> queries = Parser.parseJdbcSql("InSeRt into foo (a,b,c) values (?,?,?) returning a", true, true, false,
|
||||||
true);
|
true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertEquals("This is an INSERT command", SqlCommandType.INSERT, query.command.getType());
|
assertEquals("This is an INSERT command", SqlCommandType.INSERT, query.command.getType());
|
||||||
|
|
||||||
queries = Parser.parseJdbcSql("select 1 as insert", true, true, false, true);
|
queries = Parser.parseJdbcSql("select 1 as insert", true, true, false, true, true);
|
||||||
query = queries.get(0);
|
query = queries.get(0);
|
||||||
assertEquals("This is a SELECT command", SqlCommandType.SELECT, query.command.getType());
|
assertEquals("This is a SELECT command", SqlCommandType.SELECT, query.command.getType());
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ public class CompositeQueryParseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testWithSelect() throws SQLException {
|
public void testWithSelect() throws SQLException {
|
||||||
List<NativeQuery> queries;
|
List<NativeQuery> queries;
|
||||||
queries = Parser.parseJdbcSql("with update as (update foo set (a=?,b=?,c=?)) select * from update", true, true, false, true);
|
queries = Parser.parseJdbcSql("with update as (update foo set (a=?,b=?,c=?)) select * from update", true, true, false, true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertEquals("with ... () select", SqlCommandType.SELECT, query.command.getType());
|
assertEquals("with ... () select", SqlCommandType.SELECT, query.command.getType());
|
||||||
}
|
}
|
||||||
@ -180,7 +180,7 @@ public class CompositeQueryParseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void testWithInsert() throws SQLException {
|
public void testWithInsert() throws SQLException {
|
||||||
List<NativeQuery> queries;
|
List<NativeQuery> queries;
|
||||||
queries = Parser.parseJdbcSql("with update as (update foo set (a=?,b=?,c=?)) insert into table(select) values(1)", true, true, false, true);
|
queries = Parser.parseJdbcSql("with update as (update foo set (a=?,b=?,c=?)) insert into table(select) values(1)", true, true, false, true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertEquals("with ... () insert", SqlCommandType.INSERT, query.command.getType());
|
assertEquals("with ... () insert", SqlCommandType.INSERT, query.command.getType());
|
||||||
}
|
}
|
||||||
@ -201,7 +201,7 @@ public class CompositeQueryParseTest {
|
|||||||
boolean splitStatements) {
|
boolean splitStatements) {
|
||||||
try {
|
try {
|
||||||
return toString(
|
return toString(
|
||||||
Parser.parseJdbcSql(query, standardConformingStrings, withParameters, splitStatements, false));
|
Parser.parseJdbcSql(query, standardConformingStrings, withParameters, splitStatements, false, true));
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new IllegalStateException("Parser.parseJdbcSql: " + e.getMessage(), e);
|
throw new IllegalStateException("Parser.parseJdbcSql: " + e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ public class SqlCommandParseTest {
|
|||||||
@Test
|
@Test
|
||||||
public void run() throws SQLException {
|
public void run() throws SQLException {
|
||||||
List<NativeQuery> queries;
|
List<NativeQuery> queries;
|
||||||
queries = Parser.parseJdbcSql(sql, true, true, false, true);
|
queries = Parser.parseJdbcSql(sql, true, true, false, true, true);
|
||||||
NativeQuery query = queries.get(0);
|
NativeQuery query = queries.get(0);
|
||||||
assertEquals(sql, type, query.command.getType());
|
assertEquals(sql, type, query.command.getType());
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,7 @@ import org.postgresql.util.ExecuteUtil;
|
|||||||
import org.postgresql.util.RsParser;
|
import org.postgresql.util.RsParser;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.ResultSet;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.sql.Statement;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
@ -63,6 +60,60 @@ public class SelectFunctionTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTriggerQuery() throws Exception {
|
||||||
|
String sqlTable = "create table t_tinyint0006 (" + "id int primary key auto_increment,"
|
||||||
|
+ "my_data tinyint" + ");";
|
||||||
|
String sqlTrigger = "create trigger trigger_tinyint0006 before insert on t_tinyint0006" + " for each row "
|
||||||
|
+ "begin" + " update t_tinyint0006 set my_data=1;" + "end;";
|
||||||
|
try (Connection conn = createConnection()) {
|
||||||
|
ExecuteUtil.execute(conn, sqlTable);
|
||||||
|
ExecuteUtil.execute(conn, sqlTrigger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReturningQuery() throws Exception {
|
||||||
|
String returnString = "INSERT INTO CIMMIT (DATA_ENABLE) VALUES (1)";
|
||||||
|
try (Connection conn = createConnection()) {
|
||||||
|
PreparedStatement st = conn.prepareStatement(returnString, new String[] {"ID"});
|
||||||
|
st.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBatchInsert() throws Exception {
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.put("preparedStatementCacheQueries", "2");
|
||||||
|
props.put("prepareThreshold", "2");
|
||||||
|
props.put("fetchSize", "5");
|
||||||
|
props.put("batchMode", "OFF");
|
||||||
|
props.put("reWriteBatchedInserts", "true");
|
||||||
|
try (Connection conn = TestUtil.openDB(props)) {
|
||||||
|
for (int j = 1; j <= 1000; j++) {
|
||||||
|
ExecuteUtil.execute(conn, "set session_timeout = 0;");
|
||||||
|
ExecuteUtil.execute(conn, "drop table if exists t" + j);
|
||||||
|
ExecuteUtil.execute(conn, "create table t" + j
|
||||||
|
+ "(id int, id1 int, id2 int, id3 int, id4 int, id5 int, data varchar(2048));");
|
||||||
|
String batchInsert = "insert into t" + j + " values (?,?,?,?,?,?,?)";
|
||||||
|
PreparedStatement preparedStatement = conn.prepareStatement(batchInsert);
|
||||||
|
for (int i = 1; i <= 1000; i++) {
|
||||||
|
preparedStatement.setInt(1, 1);
|
||||||
|
preparedStatement.setInt(2, i);
|
||||||
|
preparedStatement.setInt(3, i);
|
||||||
|
preparedStatement.setInt(4, i);
|
||||||
|
preparedStatement.setInt(5, i);
|
||||||
|
preparedStatement.setInt(6, i);
|
||||||
|
preparedStatement.setString(7, "Huawei");
|
||||||
|
preparedStatement.addBatch();
|
||||||
|
}
|
||||||
|
preparedStatement.executeBatch();
|
||||||
|
preparedStatement.close();
|
||||||
|
}
|
||||||
|
// block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Connection createConnection() throws Exception {
|
private static Connection createConnection() throws Exception {
|
||||||
return TestUtil.openDB();
|
return TestUtil.openDB();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user