/*
* Copyright (c) 2007, PostgreSQL Global Development Group
* See the LICENSE file in the project root for more information.
*/
package org.postgresql.test.jdbc3;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.postgresql.core.NativeQuery;
import org.postgresql.core.Parser;
import org.postgresql.core.SqlCommandType;
import org.junit.Test;
import java.sql.SQLException;
import java.util.List;
public class CompositeQueryParseTest {
@Test
public void testEmptyQuery() {
assertEquals("", reparse("", true, false, true));
}
@Test
public void testWhitespaceQuery() {
assertEquals("", reparse(" ", true, false, true));
}
@Test
public void testOnlyEmptyQueries() {
assertEquals("", reparse(";;;; ; \n;\n", true, false, true));
}
@Test
public void testSimpleQuery() {
assertEquals("select 1", reparse("select 1", true, false, true));
}
@Test
public void testSimpleBind() {
assertEquals("select $1", reparse("select ?", true, true, true));
}
@Test
public void testUnquotedQuestionmark() {
assertEquals("select '{\"key\": \"val\"}'::jsonb ? 'key'",
reparse("select '{\"key\": \"val\"}'::jsonb ? 'key'", true, false, true));
}
@Test
public void testRepeatedQuestionmark() {
assertEquals("select '{\"key\": \"val\"}'::jsonb ? 'key'",
reparse("select '{\"key\": \"val\"}'::jsonb ?? 'key'", true, false, true));
}
@Test
public void testQuotedQuestionmark() {
assertEquals("select '?'", reparse("select '?'", true, false, true));
}
@Test
public void testDoubleQuestionmark() {
assertEquals("select '?', $1 ?=> $2", reparse("select '?', ? ??=> ?", true, true, true));
}
@Test
public void testCompositeBasic() {
assertEquals("select 1;/*cut*/\n select 2", reparse("select 1; select 2", true, false, true));
}
@Test
public void testCompositeWithBinds() {
assertEquals("select $1;/*cut*/\n select $1", reparse("select ?; select ?", true, true, true));
}
@Test
public void testTrailingSemicolon() {
assertEquals("select 1", reparse("select 1;", true, false, true));
}
@Test
public void testTrailingSemicolonAndSpace() {
assertEquals("select 1", reparse("select 1; ", true, false, true));
}
@Test
public void testMultipleTrailingSemicolons() {
assertEquals("select 1", reparse("select 1;;;", true, false, true));
}
@Test
public void testHasReturning() throws SQLException {
List<NativeQuery> queries = Parser.parseJdbcSql("insert into foo (a,b,c) values (?,?,?) RetuRning a", true, true, false,
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);
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);
query = queries.get(0);
assertFalse("The parser should not find the word returning as it is in quotes ", query.command.isReturningKeywordPresent());
}
@Test
public void testSelect() throws SQLException {
List<NativeQuery> queries;
queries = Parser.parseJdbcSql("select 1 as returning from (update table)", true, true, false, 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());
}
@Test
public void testDelete() throws SQLException {
List<NativeQuery> queries = Parser.parseJdbcSql("DeLeTe from foo where a=1", true, true, false,
true);
NativeQuery query = queries.get(0);
assertEquals("This is a delete command", SqlCommandType.DELETE, query.command.getType());
}
@Test
public void testMove() throws SQLException {
List<NativeQuery> queries = Parser.parseJdbcSql("MoVe NEXT FROM FOO", true, true, false, true);
NativeQuery query = queries.get(0);
assertEquals("This is a move command", SqlCommandType.MOVE, query.command.getType());
}
@Test
public void testUpdate() throws SQLException {
List<NativeQuery> queries;
NativeQuery query;
queries = Parser.parseJdbcSql("update foo set (a=?,b=?,c=?)", true, true, false, true);
query = queries.get(0);
assertEquals("This is an UPDATE command", SqlCommandType.UPDATE, query.command.getType());
}
@Test
public void testInsert() throws SQLException {
List<NativeQuery> queries = Parser.parseJdbcSql("InSeRt into foo (a,b,c) values (?,?,?) returning a", true, true, false,
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);
query = queries.get(0);
assertEquals("This is a SELECT command", SqlCommandType.SELECT, query.command.getType());
}
@Test
public void testWith() throws SQLException {
List<NativeQuery> queries;
queries = Parser.parseJdbcSql("with update as insert (update foo set (a=?,b=?,c=?)) select * from update", true, true, false, true);
NativeQuery query = queries.get(0);
assertEquals("This is a WITH command", SqlCommandType.WITH, query.command.getType());
}
@Test
public void testMultipleEmptyQueries() {
assertEquals("select 1;/*cut*/\n" + "select 2",
reparse("select 1; ;\t;select 2", true, false, true));
}
@Test
public void testCompositeWithComments() {
assertEquals("select 1;/*cut*/\n" + "/* noop */;/*cut*/\n" + "select 2",
reparse("select 1;/* noop */;select 2", true, false, true));
}
private String reparse(String query, boolean standardConformingStrings, boolean withParameters,
boolean splitStatements) {
try {
return toString(
Parser.parseJdbcSql(query, standardConformingStrings, withParameters, splitStatements, false));
} catch (SQLException e) {
throw new IllegalStateException("Parser.parseJdbcSql: " + e.getMessage(), e);
}
}
private String toString(List<NativeQuery> queries) {
StringBuilder sb = new StringBuilder();
for (NativeQuery query : queries) {
if (sb.length() != 0) {
sb.append(";/*cut*/\n");
}
sb.append(query.nativeSql);
}
return sb.toString();
}
}