Discard table hints in MSSQLServer mode

Ignore table hints (e.g. "SELECT * FROM table WITH (NOLOCK)"), that form a
valid expression in SQL Server.

Reference:
https://docs.microsoft.com/en-us/sql/t-sql/queries/hints-transact-sql-table?view=sql-server-2017
上级 ca4658b7
......@@ -1802,6 +1802,11 @@ public class Parser {
}
}
}
if (database.getMode().discardWithTableHints) {
discardWithTableHints();
}
// inherit alias for CTE as views from table name
if (table.isView() && table.isTableExpression() && alias == null) {
alias = table.getName();
......@@ -1855,6 +1860,34 @@ public class Parser {
return null;
}
private void discardWithTableHints() {
if (readIf("WITH")) {
read(OPEN_PAREN);
if (!readIf(CLOSE_PAREN)) {
do {
discardTableHint();
} while (readIfMore(true));
}
}
}
private void discardTableHint() {
if (readIf("INDEX")) {
if (readIf(OPEN_PAREN)) {
do {
readExpression();
} while (readIf(COMMA));
read(CLOSE_PAREN);
} else if (readIf(EQUAL)){
readExpression();
} else {
throw getSyntaxError();
}
} else {
readExpression();
}
}
private Prepared parseTruncate() {
read("TABLE");
Table table = readTableOrView();
......
......@@ -187,6 +187,11 @@ public class Mode {
*/
public boolean allowDB2TimestampFormat;
/**
* Discard SQLServer table hints (e.g. "SELECT * FROM table WITH (NOLOCK)")
*/
public boolean discardWithTableHints;
/**
* Convert (VAR)CHAR to VAR(BINARY) and vice versa with UTF-8 encoding instead of HEX.
*/
......@@ -256,6 +261,7 @@ public class Mode {
mode.allowPlusForStringConcat = true;
mode.swapConvertFunctionParameters = true;
mode.supportPoundSymbolForColumnNames = true;
mode.discardWithTableHints = true;
// MS SQL Server does not support client info properties. See
// https://msdn.microsoft.com/en-Us/library/dd571296%28v=sql.110%29.aspx
mode.supportedClientInfoPropertiesRegEx = null;
......
......@@ -30,6 +30,7 @@ import org.h2.test.db.TestCheckpoint;
import org.h2.test.db.TestCluster;
import org.h2.test.db.TestCompatibility;
import org.h2.test.db.TestCompatibilityOracle;
import org.h2.test.db.TestCompatibilitySQLServer;
import org.h2.test.db.TestCsv;
import org.h2.test.db.TestDateStorage;
import org.h2.test.db.TestDeadlock;
......@@ -745,6 +746,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
addTest(new TestCheckpoint());
addTest(new TestCompatibility());
addTest(new TestCompatibilityOracle());
addTest(new TestCompatibilitySQLServer());
addTest(new TestCsv());
addTest(new TestDeadlock());
if (vmlens) {
......
package org.h2.test.db;
import org.h2.test.TestBase;
import org.h2.test.TestDb;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Test MSSQLServer compatibility mode.
*/
public class TestCompatibilitySQLServer extends TestDb {
/**
* Run just this test.
*
* @param s ignored
*/
public static void main(String... s) throws Exception {
TestBase test = TestBase.createCaller().init();
test.test();
}
@Override
public void test() throws Exception {
testDiscardTableHints();
}
private void testDiscardTableHints() throws SQLException {
deleteDb("sqlserver");
Connection conn = getConnection("sqlserver;MODE=MSSQLServer");
Statement stat = conn.createStatement();
stat.execute("create table parent(id int primary key, name varchar(255))");
stat.execute("create table child(id int primary key, parent_id int, name varchar(255), foreign key (parent_id) references public.parent(id))");
assertSupportedSyntax(stat, "select * from parent");
assertSupportedSyntax(stat, "select * from parent with(nolock)");
assertSupportedSyntax(stat, "select * from parent with(nolock, index = id)");
assertSupportedSyntax(stat, "select * from parent with(nolock, index(id, name))");
assertSupportedSyntax(stat, "select * from parent p join child ch on ch.parent_id = p.id");
assertSupportedSyntax(stat, "select * from parent p with(nolock) join child ch with(nolock) on ch.parent_id = p.id");
assertSupportedSyntax(stat, "select * from parent p with(nolock) join child ch with(nolock, index = id) on ch.parent_id = p.id");
assertSupportedSyntax(stat, "select * from parent p with(nolock) join child ch with(nolock, index(id, name)) on ch.parent_id = p.id");
}
private void assertSupportedSyntax(Statement stat, String sql) {
try {
stat.execute(sql);
} catch (SQLException ex) {
fail("Failed to execute SQL statement: " + sql);
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论