bug修改

This commit is contained in:
wubeidou
2023-11-30 11:29:43 +08:00
parent 20658c79ca
commit 214a52a2f8
18 changed files with 237 additions and 50 deletions

View File

@ -143,6 +143,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 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
Logger level of the driver. Allowed values: <code>OFF</code>, <code>DEBUG</code> or <code>TRACE</code>.

View File

@ -61,6 +61,17 @@ public enum PGProperty {
"Force use of a particular protocol version when connecting, currently only version 3 is supported.",
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>
*

View File

@ -7,6 +7,8 @@ package org.postgresql.core;
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
* 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 isACompatibilityFunction;
private int executeCount;
// record queries after rewrite
private final ArrayList<Query> rewriteQueries = new ArrayList<>();
public CachedQuery(Object key, Query query, boolean isFunction, boolean isACompatibilityFunction) {
assert key instanceof String || key instanceof 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 */;
}
/**
* 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
public String toString() {
return "CachedQuery{"

View File

@ -65,7 +65,8 @@ class CachedQueryCreateAction implements LruCache.CreateAction<Object, CachedQue
List<NativeQuery> queries = Parser.parseJdbcSql(parsedSql,
queryExecutor.getStandardConformingStrings(), isParameterized, splitStatements,
queryExecutor.isReWriteBatchedInsertsEnabled(), returningColumns);
queryExecutor.isReWriteBatchedInsertsEnabled(), queryExecutor.getQuoteReturningIdentifiers(),
returningColumns);
Query query = queryExecutor.wrap(queries);
return new CachedQuery(key, query, isFunction, isACompatibilityFunction);

View File

@ -51,6 +51,7 @@ public class Parser {
* @param withParameters whether to replace ?, ? with $1, $2, etc
* @param splitStatements whether to split statements by semicolon
* @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
* @return list of native queries
* @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,
boolean withParameters, boolean splitStatements,
boolean isBatchedReWriteConfigured,
boolean isQuotedReturningIdentifiers,
String... returningColumnNames) throws SQLException {
int numOfOverSymble = 0;
if(startWithComment(query)) {
@ -151,8 +153,8 @@ public class Parser {
}
fragmentStart = i + 1;
if (nativeSql.length() > 0) {
if (addReturning(
nativeSql, currentCommandType, returningColumnNames, isReturningPresent)) {
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent,
isQuotedReturningIdentifiers)) {
isReturningPresent = true;
}
@ -256,7 +258,8 @@ public class Parser {
}
fragmentStart = i + 1;
if (nativeSql.length() > 0) {
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent)) {
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent,
isQuotedReturningIdentifiers)) {
isReturningPresent = true;
}
@ -416,7 +419,8 @@ public class Parser {
return nativeQueries != null ? nativeQueries : Collections.<NativeQuery>emptyList();
}
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent)) {
if (addReturning(nativeSql, currentCommandType, returningColumnNames, isReturningPresent,
isQuotedReturningIdentifiers)) {
isReturningPresent = true;
}
@ -526,7 +530,8 @@ public class Parser {
}
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) {
return false;
}
@ -547,7 +552,11 @@ public class Parser {
if (col > 0) {
nativeSql.append(", ");
}
if (isQuotedReturningIdentifiers) {
Utils.escapeIdentifier(nativeSql, columnName);
} else {
nativeSql.append(columnName);
}
}
return true;
}
@ -670,6 +679,7 @@ public class Parser {
case "PROCEDURE":
case "FUNCTION":
case "DECLARE":
case "TRIGGER":
return true;
case "CREATE":
if (i == 0) {
@ -897,6 +907,7 @@ public class Parser {
&& (query[offset + 8] | 32) == 'g';
}
/**
* Parse string to check presence of SELECT keyword regardless of case.
*

View File

@ -444,6 +444,12 @@ public interface QueryExecutor extends TypeTransferModeRegistry {
*/
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.
* @return backend timezone in java format.

View File

@ -41,6 +41,7 @@ public abstract class QueryExecutorBase implements QueryExecutor {
private TransactionState transactionState;
private final boolean reWriteBatchedInserts;
private final boolean columnSanitiserDisabled;
private final boolean isQuotedReturningIdentifiers;
private final PreferQueryMode preferQueryMode;
private AutoSave autoSave;
private boolean flushCacheOnDeallocate = true;
@ -64,6 +65,7 @@ public abstract class QueryExecutorBase implements QueryExecutor {
this.cancelSignalTimeout = cancelSignalTimeout;
this.reWriteBatchedInserts = PGProperty.REWRITE_BATCHED_INSERTS.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);
this.preferQueryMode = PreferQueryMode.of(preferMode);
this.autoSave = AutoSave.of(PGProperty.AUTOSAVE.get(info));
@ -78,6 +80,12 @@ public abstract class QueryExecutorBase implements QueryExecutor {
@Override
public void evict(CachedQuery cachedQuery) throws SQLException {
cachedQuery.query.close();
if (!cachedQuery.isRewriteQueriesEmpty()) {
for (Query query : cachedQuery.getRewriteQueries()) {
query.close();
}
cachedQuery.clearRewriteQueries();
}
}
});
}
@ -261,6 +269,11 @@ public abstract class QueryExecutorBase implements QueryExecutor {
return standardConformingStrings;
}
@Override
public boolean getQuoteReturningIdentifiers() {
return isQuotedReturningIdentifiers;
}
@Override
public synchronized TransactionState getTransactionState() {
return transactionState;

View File

@ -5,10 +5,10 @@
package org.postgresql.core.v3;
import org.postgresql.core.CachedQuery;
import org.postgresql.core.NativeQuery;
import org.postgresql.core.ParameterList;
/**
* 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
@ -27,6 +27,8 @@ public class BatchedQuery extends SimpleQuery {
private final int batchSize;
private BatchedQuery[] blocks;
// record the origin query of the rewrite query
private CachedQuery originalPrepareQuery;
public BatchedQuery(NativeQuery query, TypeTransferModeRegistry transferModeRegistry,
int valuesBraceOpenPosition,
int valuesBraceClosePosition, boolean sanitiserDisabled) {
@ -85,6 +87,24 @@ public class BatchedQuery extends SimpleQuery {
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) {
String buildSql = null;
// dynamically build sql with parameters for batches

View File

@ -10,6 +10,7 @@ import org.postgresql.PGProperty;
import org.postgresql.copy.CopyIn;
import org.postgresql.copy.CopyOperation;
import org.postgresql.copy.CopyOut;
import org.postgresql.core.CachedQuery;
import org.postgresql.core.CommandCompleteParser;
import org.postgresql.core.Encoding;
import org.postgresql.core.EncodingPredictor;
@ -283,7 +284,7 @@ public class QueryExecutorImpl extends QueryExecutorBase {
public Query createSimpleQuery(String sql) throws SQLException {
List<NativeQuery> queries = Parser.parseJdbcSql(sql,
getStandardConformingStrings(), false, true,
isReWriteBatchedInsertsEnabled());
isReWriteBatchedInsertsEnabled(), getQuoteReturningIdentifiers());
return wrap(queries);
}
@ -1553,6 +1554,17 @@ public class QueryExecutorImpl extends QueryExecutorBase {
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)
throws IOException {
// 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.setPrepareTypes(typeOIDs);
registerParsedQuery(query, statementName);
checkAndUpdateRewriteQueries(query);
}
byte[] encodedStatementName = query.getEncodedStatementName();

View File

@ -321,6 +321,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
* @see PGProperty#RECEIVE_BUFFER_SIZE

View File

@ -243,7 +243,7 @@ public class ClientLogic {
//Replace the query syntax from jdbc syntax with ? for bind parameters to $1 $2 ... $n
List<NativeQuery> queries;
try {
queries = Parser.parseJdbcSql(query, true, true, true, true);
queries = Parser.parseJdbcSql(query, true, true, true, true, true);
} catch (SQLException e) {
throw new ClientLogicException(ERROR_PARSER_FAILURE, ERROR_TEXT_PARSER_FAILURE, true);
}

View File

@ -1725,6 +1725,7 @@ class PgPreparedStatement extends PgStatement implements PreparedStatement {
}
// Find appropriate batch for block count.
BatchedQuery bq = originalQuery.deriveForMultiBatch(valueBlock);
bq.setOriginalPrepareQuery(preparedQuery);
ParameterList newPl = bq.createParameterList();
for (int j = 0; j < valueBlock; j++) {
ParameterList pl = batchParameters.get(offset++);

View File

@ -155,7 +155,7 @@ public class ParserTest {
"insert test(id, name) select 1, 'value' as RETURNING from test2";
List<NativeQuery> qry =
Parser.parseJdbcSql(
query, true, true, true, true);
query, true, true, true, true, true);
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
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";
List<NativeQuery> qry =
Parser.parseJdbcSql(
query, true, true, true, true);
query, true, true, true, true, true);
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
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";
List<NativeQuery> qry =
Parser.parseJdbcSql(
query, true, true, true, true);
query, true, true, true, true, true);
boolean returningKeywordPresent = qry.get(0).command.isReturningKeywordPresent();
Assert.assertFalse("There's no top-level <<returning>> clause " + query, returningKeywordPresent);
}
@ -185,7 +185,7 @@ public class ParserTest {
@Test
public void insertBatchedReWriteOnConflict() throws SQLException {
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();
Assert.assertEquals(34, command.getBatchRewriteValuesBraceOpenPosition());
Assert.assertEquals(44, command.getBatchRewriteValuesBraceClosePosition());
@ -194,7 +194,7 @@ public class ParserTest {
@Test
public void insertBatchedReWriteOnConflictUpdateBind() throws SQLException {
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();
Assert.assertFalse("update set name=? is NOT compatible with insert rewrite", command.isBatchedReWriteCompatible());
}
@ -202,7 +202,7 @@ public class ParserTest {
@Test
public void insertBatchedReWriteOnConflictUpdateConstant() throws SQLException {
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();
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 {
String query =
"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();
Assert.assertEquals(34, command.getBatchRewriteValuesBraceOpenPosition());
Assert.assertEquals(56, command.getBatchRewriteValuesBraceClosePosition());
@ -241,7 +241,7 @@ public class ParserTest {
for (String mySql: sqlTests) {
List<NativeQuery> queries = Parser.parseJdbcSql(mySql,
false,false,
true, false, new String[0]);
true, false, true, new String[0]);
assertEquals(1, queries.size());
}
}

View File

@ -53,7 +53,7 @@ public class ReturningParserTest {
String query =
"insert into\"prep\"(a, " + prefix + columnName + suffix + ")values(1,2)" + prefix
+ 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 expectedReturning = this.returning.equalsIgnoreCase("returning")

View File

@ -387,6 +387,7 @@ public class TestUtil {
props.put(PGProperty.PREFER_QUERY_MODE.getName(), value);
}
}
PGProperty.QUOTE_RETURNING_IDENTIFIERS.set(props, false);
// Enable Base4 tests to override host,port,database
String hostport = props.getProperty(SERVER_HOST_PORT_PROP, getServer() + ":" + getPort());
String database = props.getProperty(DATABASE_PROP, getDatabase());

View File

@ -95,16 +95,16 @@ public class CompositeQueryParseTest {
@Test
public void testHasReturning() throws SQLException {
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);
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);
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,
true);
true, true);
query = queries.get(0);
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
public void testSelect() throws SQLException {
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);
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());
@ -121,7 +121,7 @@ public class CompositeQueryParseTest {
@Test
public void testDelete() throws SQLException {
List<NativeQuery> queries = Parser.parseJdbcSql("DeLeTe from foo where a=1", true, true, false,
true);
true, true);
NativeQuery query = queries.get(0);
assertEquals("This is a delete command", SqlCommandType.DELETE, query.command.getType());
}
@ -130,7 +130,7 @@ public class CompositeQueryParseTest {
public void testMultiQueryWithBind() throws SQLException {
// braces around (42) are required to puzzle the parser
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);
assertEquals("query(0) of " + sql,
"INSERT: INSERT INTO inttable(a) VALUES ($1)",
@ -143,7 +143,7 @@ public class CompositeQueryParseTest {
@Test
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);
assertEquals("This is a move command", SqlCommandType.MOVE, query.command.getType());
}
@ -152,7 +152,7 @@ public class CompositeQueryParseTest {
public void testUpdate() throws SQLException {
List<NativeQuery> queries;
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);
assertEquals("This is an UPDATE command", SqlCommandType.UPDATE, query.command.getType());
}
@ -160,11 +160,11 @@ public class CompositeQueryParseTest {
@Test
public void testInsert() throws SQLException {
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);
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);
assertEquals("This is a SELECT command", SqlCommandType.SELECT, query.command.getType());
}
@ -172,7 +172,7 @@ public class CompositeQueryParseTest {
@Test
public void testWithSelect() throws SQLException {
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);
assertEquals("with ... () select", SqlCommandType.SELECT, query.command.getType());
}
@ -180,7 +180,7 @@ public class CompositeQueryParseTest {
@Test
public void testWithInsert() throws SQLException {
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);
assertEquals("with ... () insert", SqlCommandType.INSERT, query.command.getType());
}
@ -201,7 +201,7 @@ public class CompositeQueryParseTest {
boolean splitStatements) {
try {
return toString(
Parser.parseJdbcSql(query, standardConformingStrings, withParameters, splitStatements, false));
Parser.parseJdbcSql(query, standardConformingStrings, withParameters, splitStatements, false, true));
} catch (SQLException e) {
throw new IllegalStateException("Parser.parseJdbcSql: " + e.getMessage(), e);
}

View File

@ -47,7 +47,7 @@ public class SqlCommandParseTest {
@Test
public void run() throws SQLException {
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);
assertEquals(sql, type, query.command.getType());
}

View File

@ -11,10 +11,7 @@ import org.postgresql.util.ExecuteUtil;
import org.postgresql.util.RsParser;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.sql.PreparedStatement;
import java.util.List;
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 {
return TestUtil.openDB();
}