You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ko...@apache.org on 2024/07/24 12:33:50 UTC
(ignite-3) branch main updated: IGNITE-22655 Sql. Improve error message for incorrect SQL string (#4108)
This is an automated email from the ASF dual-hosted git repository.
korlov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new cd3c790b03 IGNITE-22655 Sql. Improve error message for incorrect SQL string (#4108)
cd3c790b03 is described below
commit cd3c790b0328b208b3262107c78595a41aef5c12
Author: Max Zhuravkov <sh...@gmail.com>
AuthorDate: Wed Jul 24 15:33:43 2024 +0300
IGNITE-22655 Sql. Improve error message for incorrect SQL string (#4108)
---
.../internal/sql/engine/ItDataTypesTest.java | 3 +-
.../sql/identifiers/test_long_identifiers.test | 57 ++++++++++++++------
.../sql/engine/sql/IgniteSqlCreateTableOption.java | 15 ------
.../internal/sql/engine/sql/IgniteSqlParser.java | 63 ++++++++++++++++++++++
.../internal/sql/engine/sql/IgniteSqlUpdate.java | 3 +-
.../sql/engine/sql/IgniteSqlZoneOption.java | 15 ------
6 files changed, 108 insertions(+), 48 deletions(-)
diff --git a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
index 98b5004017..d64f2d9599 100644
--- a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
+++ b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
@@ -240,7 +240,8 @@ public class ItDataTypesTest extends BaseSqlIntegrationTest {
assertQuery(format("SELECT * FROM tbl WHERE v NOT IN ('{}' - '1', '0')", strUpper)).returns(checkReturn).check();
assertQuery("SELECT * FROM tbl WHERE v NOT IN (? - '1', '0')").withParam(checkReturn).returns(checkReturn).check();
- // TODO: https://issues.apache.org/jira/browse/IGNITE-22519 Comparison on BIGINT cast brings overflow
+ // TODO: https://issues.apache.org/jira/browse/IGNITE-20889
+ // Sql. Change type derivation for literals and expressions for overflowed BIGINT
// BigDecimal moreThanUpperBoundExact = new BigDecimal(strUpper).add(new BigDecimal(1));
// assertQuery(format("SELECT * FROM tbl WHERE v < {}::DECIMAL(19, 0)", moreThanUpperBoundExact)).returns(checkReturn).check();
diff --git a/modules/sql-engine/src/integrationTest/sql/identifiers/test_long_identifiers.test b/modules/sql-engine/src/integrationTest/sql/identifiers/test_long_identifiers.test
index 84ea70023c..e39c6af3d8 100644
--- a/modules/sql-engine/src/integrationTest/sql/identifiers/test_long_identifiers.test
+++ b/modules/sql-engine/src/integrationTest/sql/identifiers/test_long_identifiers.test
@@ -7,6 +7,12 @@
statement ok
PRAGMA enable_verification
+statement error: Non-query expression encountered in illegal context.
+tableName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters
+
+statement error: Non-query expression encountered in illegal context.
+SELECT 1; tableName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters
+
# Create table with short identifiers for test simplicity purpose
statement ok
CREATE TABLE t (id INTEGER, val INTEGER, PRIMARY KEY (id))
@@ -15,14 +21,25 @@ CREATE TABLE t (id INTEGER, val INTEGER, PRIMARY KEY (id))
statement ok
CREATE TABLE tableName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf128Characters (keyColumnName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf128Characters INTEGER, valueColumnName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf128Characters INTEGER, PRIMARY KEY (keyColumnName_veryLooooooooooooooooooooooooooooooooooooooooo [...]
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
CREATE TABLE tableName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters (key INTEGER, val INTEGER, PRIMARY KEY (key));
+statement error: Length of identifier
+SELECT * from t as tableName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters;
+
+statement error: Length of identifier
+SELECT * FROM t where 1 = (SELECT 1 from t as tableName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters LIMIT 1);
+
+statement error: Length of identifier
+CREATE TABLE ttt (key type0Name_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters, val INTEGER, PRIMARY KEY (key));
+
+statement error: Length of identifier
+CREATE TABLE ttt (key type0Name_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters ARRAY, val INTEGER, PRIMARY KEY (key));
# Rename table with long identifiers
skipif ignite3
# Ignored: https://issues.apache.org/jira/browse/IGNITE-19484
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
ALTER TABLE t RENAME TO tableName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters;
skipif ignite3
@@ -40,7 +57,7 @@ ALTER TABLE tableName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooo
statement ok
ALTER TABLE t ADD COLUMN (columnName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf128Characters INTEGER);
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
ALTER TABLE t ADD COLUMN (columnName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters INTEGER);
statement ok
@@ -50,7 +67,7 @@ ALTER TABLE t DROP COLUMN (columnName_veryLooooooooooooooooooooooooooooooooooooo
# Alter table rename column with long identifier
skipif ignite3
# Ignored: https://issues.apache.org/jira/browse/IGNITE-19485
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
ALTER TABLE t RENAME COLUMN val TO columnName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters;
skipif ignite3
@@ -86,10 +103,10 @@ SELECT columnAlias_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooo
1
2
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
SELECT columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters FROM (VALUES (1), (2)) t(columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters);
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
SELECT col FROM (VALUES (1), (2)) tableAlias_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters(col);
query I
@@ -102,10 +119,16 @@ SELECT 1 columnAlias_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooo
----
1
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
SELECT 1 as columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
+SELECT * FROM (VALUES (1)) t(columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters);
+
+statement error: Length of identifier
+SELECT * FROM (VALUES (1)) tableAlias_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters(c);
+
+statement error: Length of identifier
SELECT 1 columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters
# Long column aliases with subquery
@@ -119,10 +142,10 @@ SELECT columnAlias_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooo
----
1
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
SELECT columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters FROM (SELECT 1 as columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters);
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
SELECT columnAlias_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters FROM (SELECT 1 columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters);
query I
@@ -137,7 +160,7 @@ SELECT * FROM (SELECT 1) as tableAlias_veryLoooooooooooooooooooooooooooooooooooo
----
1
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
SELECT * FROM (SELECT 1) as tableAlias_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters;
query I
@@ -159,7 +182,7 @@ SELECT id as columnAlias_veryLoooooooooooooooooooooooooooooooooooooooooooooooooo
2
1
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
SELECT id as columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters FROM t ORDER BY columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters DESC;
@@ -174,9 +197,11 @@ SELECT val as columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooo
----
1 3
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
SELECT id as columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters FROM t GROUP BY columnAlias_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters;
+statement error: Length of identifier
+SELECT functionName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters(1, 2, 3)
# Long identifier in WHERE clause
query I
@@ -192,7 +217,7 @@ CREATE INDEX indexName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooo
statement ok
DROP INDEX indexName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf128Characters;
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
CREATE INDEX indexName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters on t (val);
@@ -208,7 +233,7 @@ DROP TABLE tableName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooo
statement ok
CREATE ZONE zoneName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf128Characters WITH STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3;
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
CREATE ZONE zoneName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters WITH STORAGE_PROFILES='default', PARTITIONS=1, REPLICAS=3;
statement ok
@@ -217,7 +242,7 @@ ALTER ZONE zoneName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooo
statement ok
ALTER ZONE zoneName_veryLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf128Characters RENAME TO zoneName;
-statement error: Failed to parse query: Length of identifier
+statement error: Length of identifier
ALTER ZONE zoneName RENAME TO zoneName_veryLoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongIdentifierOf129Characters;
statement ok
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateTableOption.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateTableOption.java
index a9e92afbbb..27c59da3fd 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateTableOption.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlCreateTableOption.java
@@ -26,9 +26,6 @@ import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlWriter;
import org.apache.calcite.sql.parser.SqlParserPos;
-import org.apache.calcite.sql.util.SqlVisitor;
-import org.apache.calcite.sql.validate.SqlValidator;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.apache.calcite.util.Litmus;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -92,18 +89,6 @@ public class IgniteSqlCreateTableOption extends SqlCall {
value.unparse(writer, leftPrec, rightPrec);
}
- /** {@inheritDoc} */
- @Override
- public void validate(SqlValidator validator, SqlValidatorScope scope) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override
- public <R> R accept(SqlVisitor<R> visitor) {
- throw new UnsupportedOperationException();
- }
-
/** {@inheritDoc} */
@Override
public boolean equalsDeep(SqlNode node, Litmus litmus) {
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlParser.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlParser.java
index e19ab9e812..2fe97d27c1 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlParser.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlParser.java
@@ -17,22 +17,31 @@
package org.apache.ignite.internal.sql.engine.sql;
+import static org.apache.calcite.util.Static.RESOURCE;
import static org.apache.ignite.internal.lang.IgniteStringFormatter.format;
import static org.apache.ignite.lang.ErrorGroups.Sql.STMT_PARSE_ERR;
import java.io.Reader;
import java.util.List;
import org.apache.calcite.config.Lex;
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlCollectionTypeNameSpec;
+import org.apache.calcite.sql.SqlDataTypeSpec;
import org.apache.calcite.sql.SqlDelete;
+import org.apache.calcite.sql.SqlIdentifier;
import org.apache.calcite.sql.SqlKind;
import org.apache.calcite.sql.SqlMerge;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
+import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlUpdate;
+import org.apache.calcite.sql.SqlUtil;
import org.apache.calcite.sql.parser.SqlAbstractParserImpl;
import org.apache.calcite.sql.parser.SqlParseException;
import org.apache.calcite.sql.parser.SqlParser;
import org.apache.calcite.sql.parser.SqlParserImplFactory;
+import org.apache.calcite.sql.parser.SqlParserPos;
+import org.apache.calcite.sql.util.SqlShuttle;
import org.apache.calcite.util.SourceStringReader;
import org.apache.ignite.internal.generated.query.calcite.sql.IgniteSqlParserImpl;
import org.apache.ignite.internal.generated.query.calcite.sql.IgniteSqlParserImplConstants;
@@ -41,6 +50,7 @@ import org.apache.ignite.internal.generated.query.calcite.sql.Token;
import org.apache.ignite.internal.generated.query.calcite.sql.TokenMgrError;
import org.apache.ignite.internal.util.StringUtils;
import org.apache.ignite.sql.SqlException;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Provides method for parsing SQL statements in SQL dialect of Apache Ignite 3.
@@ -55,6 +65,10 @@ public final class IgniteSqlParser {
public static final SqlParser.Config PARSER_CONFIG = SqlParser.config()
.withParserFactory(InternalIgniteSqlParser.FACTORY)
.withLex(Lex.ORACLE)
+ // Do not validate the length of SQL identifiers by the parser because a validation error is throw after creating a token,
+ // which is rather confusing. E.g. A string 12...(129 chars) is going to produce "identifier is too long" error,
+ // instead of reporting that expected a query but got something else.
+ .withIdentifierMaxLength(Integer.MAX_VALUE)
.withConformance(IgniteSqlConformance.INSTANCE);
private IgniteSqlParser() {
@@ -107,6 +121,9 @@ public final class IgniteSqlParser {
list.set(i, node);
}
+ ValidateSqlIdentifiers visitor = new ValidateSqlIdentifiers();
+ nodeList.accept(visitor);
+
return mode.createResult(list, dynamicParamsCount);
} catch (SqlParseException e) {
throw convertException(e);
@@ -273,4 +290,50 @@ public final class IgniteSqlParser {
return node;
}
}
+
+ private static class ValidateSqlIdentifiers extends SqlShuttle {
+ @Override
+ public @Nullable SqlNode visit(SqlIdentifier id) {
+ for (String segment : id.names) {
+ validateId(id.getParserPosition(), segment);
+ }
+
+ return super.visit(id);
+ }
+
+ @Override
+ public @Nullable SqlNode visit(SqlCall call) {
+ SqlOperator operator = call.getOperator();
+
+ // If something when wrong during the parsing, fail at the validation stage
+ if (operator != null) {
+ validateId(call.getParserPosition(), operator.getName());
+ }
+
+ return super.visit(call);
+ }
+
+ @Override
+ public @Nullable SqlNode visit(SqlDataTypeSpec type) {
+ this.visit(type.getTypeName());
+
+ // getComponentTypeSpec throws AssertionError if typeNameSpec is not an instance of CollectionTypeNameSpec.
+ if (type.getTypeNameSpec() instanceof SqlCollectionTypeNameSpec) {
+ SqlDataTypeSpec componentTypeSpec = type.getComponentTypeSpec();
+ if (componentTypeSpec != null) {
+ this.visit(componentTypeSpec);
+ }
+ }
+
+ return super.visit(type);
+ }
+
+ private static void validateId(SqlParserPos pos, String segment) {
+ int maxLength = SqlParser.DEFAULT_IDENTIFIER_MAX_LENGTH;
+
+ if (segment.length() > maxLength) {
+ throw SqlUtil.newContextException(pos, RESOURCE.identifierTooLong(segment, maxLength));
+ }
+ }
+ }
}
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlUpdate.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlUpdate.java
index 92967de3b9..3f2638ef1b 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlUpdate.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlUpdate.java
@@ -26,6 +26,7 @@ import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlNodeList;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlSelect;
+import org.apache.calcite.sql.SqlSpecialOperator;
import org.apache.calcite.sql.SqlUpdate;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.util.ImmutableNullableList;
@@ -37,7 +38,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
public class IgniteSqlUpdate extends SqlUpdate {
/** UPDATE operator. */
- protected static final class Operator extends IgniteSqlSpecialOperator {
+ protected static final class Operator extends SqlSpecialOperator {
/** Constructor. */
protected Operator() {
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlZoneOption.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlZoneOption.java
index 1a523acac9..8ba9f225df 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlZoneOption.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/sql/IgniteSqlZoneOption.java
@@ -26,9 +26,6 @@ import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.sql.SqlOperator;
import org.apache.calcite.sql.SqlWriter;
import org.apache.calcite.sql.parser.SqlParserPos;
-import org.apache.calcite.sql.util.SqlVisitor;
-import org.apache.calcite.sql.validate.SqlValidator;
-import org.apache.calcite.sql.validate.SqlValidatorScope;
import org.apache.calcite.util.Litmus;
import org.checkerframework.checker.nullness.qual.Nullable;
@@ -94,18 +91,6 @@ public class IgniteSqlZoneOption extends SqlCall {
value.unparse(writer, leftPrec, rightPrec);
}
- /** {@inheritDoc} */
- @Override
- public void validate(SqlValidator validator, SqlValidatorScope scope) {
- throw new UnsupportedOperationException();
- }
-
- /** {@inheritDoc} */
- @Override
- public <R> R accept(SqlVisitor<R> visitor) {
- throw new UnsupportedOperationException();
- }
-
/** {@inheritDoc} */
@Override
public boolean equalsDeep(SqlNode node, Litmus litmus) {