diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/pom.xml b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/pom.xml
new file mode 100644
index 00000000000..5d7d7fcad75
--- /dev/null
+++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/pom.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+ org.finos.legend.engine
+ legend-engine-xt-relationalStore-h2
+ 4.63.1-SNAPSHOT
+
+ 4.0.0
+
+
+ legend-engine-xt-relationalStore-h2-execution-2.1.214
+ jar
+ Legend Engine - XT - Relational Store - H2 - Execution - 2.1.214
+
+
+
+ 11
+ 11
+ UTF-8
+
+
+
+
+
+ com.h2database
+ h2
+ 2.1.214
+
+
+
+
+ junit
+ junit
+ test
+
+
+
+
\ No newline at end of file
diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/main/java/org/h2/engine/Mode.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/main/java/org/h2/engine/Mode.java
new file mode 100644
index 00000000000..b104d03277a
--- /dev/null
+++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/main/java/org/h2/engine/Mode.java
@@ -0,0 +1,742 @@
+/*
+ * Copyright 2004-2022 H2 Group. Multiple-Licensed under the MPL 2.0,
+ * and the EPL 1.0 (https://h2database.com/html/license.html).
+ * Initial Developer: H2 Group
+ */
+package org.h2.engine;
+
+import java.sql.Types;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import org.h2.util.StringUtils;
+import org.h2.value.DataType;
+import org.h2.value.Value;
+
+/**
+ * The compatibility modes. There is a fixed set of modes (for example
+ * PostgreSQL, MySQL). Each mode has different settings.
+ */
+public class Mode {
+
+ public enum ModeEnum {
+ REGULAR, STRICT, LEGACY, DB2, Derby, MariaDB, MSSQLServer, HSQLDB, MySQL, Oracle, PostgreSQL
+ }
+
+ /**
+ * Determines how rows with {@code NULL} values in indexed columns are handled
+ * in unique indexes.
+ */
+ public enum UniqueIndexNullsHandling {
+ /**
+ * Multiple rows with identical values in indexed columns with at least one
+ * indexed {@code NULL} value are allowed in unique index.
+ */
+ ALLOW_DUPLICATES_WITH_ANY_NULL,
+
+ /**
+ * Multiple rows with identical values in indexed columns with all indexed
+ * {@code NULL} values are allowed in unique index.
+ */
+ ALLOW_DUPLICATES_WITH_ALL_NULLS,
+
+ /**
+ * Multiple rows with identical values in indexed columns are not allowed in
+ * unique index.
+ */
+ FORBID_ANY_DUPLICATES
+ }
+
+ /**
+ * Generation of column names for expressions.
+ */
+ public enum ExpressionNames {
+ /**
+ * Use optimized SQL representation of expression.
+ */
+ OPTIMIZED_SQL,
+
+ /**
+ * Use original SQL representation of expression.
+ */
+ ORIGINAL_SQL,
+
+ /**
+ * Generate empty name.
+ */
+ EMPTY,
+
+ /**
+ * Use ordinal number of a column.
+ */
+ NUMBER,
+
+ /**
+ * Use ordinal number of a column with C prefix.
+ */
+ C_NUMBER,
+
+ /**
+ * Use function name for functions and ?column? for other expressions
+ */
+ POSTGRESQL_STYLE,
+ }
+
+ /**
+ * Generation of column names for expressions to be used in a view.
+ */
+ public enum ViewExpressionNames {
+ /**
+ * Use both specified and generated names as is.
+ */
+ AS_IS,
+
+ /**
+ * Throw exception for unspecified names.
+ */
+ EXCEPTION,
+
+ /**
+ * Use both specified and generated names as is, but replace too long
+ * generated names with {@code Name_exp_###}.
+ */
+ MYSQL_STYLE,
+ }
+
+ /**
+ * When CHAR values are right-padded with spaces.
+ */
+ public enum CharPadding {
+ /**
+ * CHAR values are always right-padded with spaces.
+ */
+ ALWAYS,
+
+ /**
+ * Spaces are trimmed from the right side of CHAR values, but CHAR
+ * values in result sets are right-padded with spaces to the declared
+ * length
+ */
+ IN_RESULT_SETS,
+
+ /**
+ * Spaces are trimmed from the right side of CHAR values.
+ */
+ NEVER
+ }
+
+ private static final HashMap MODES = new HashMap<>();
+
+ // Modes are also documented in the features section
+
+ /**
+ * When enabled, aliased columns (as in SELECT ID AS I FROM TEST) return the
+ * alias (I in this case) in ResultSetMetaData.getColumnName() and 'null' in
+ * getTableName(). If disabled, the real column name (ID in this case) and
+ * table name is returned.
+ */
+ public boolean aliasColumnName;
+
+ /**
+ * When converting the scale of decimal data, the number is only converted
+ * if the new scale is smaller than the current scale. Usually, the scale is
+ * converted and 0s are added if required.
+ */
+ public boolean convertOnlyToSmallerScale;
+
+ /**
+ * Creating indexes in the CREATE TABLE statement is allowed using
+ * INDEX(..)
or KEY(..)
.
+ * Example: create table test(id int primary key, name varchar(255),
+ * key idx_name(name));
+ */
+ public boolean indexDefinitionInCreateTable;
+
+ /**
+ * Identifiers may be quoted using square brackets as in [Test].
+ */
+ public boolean squareBracketQuotedNames;
+
+ /**
+ * The system columns 'ctid' and 'oid' are supported.
+ */
+ public boolean systemColumns;
+
+ /**
+ * Determines how rows with {@code NULL} values in indexed columns are handled
+ * in unique indexes.
+ */
+ public UniqueIndexNullsHandling uniqueIndexNullsHandling = UniqueIndexNullsHandling.ALLOW_DUPLICATES_WITH_ANY_NULL;
+
+ /**
+ * Empty strings are treated like NULL values. Useful for Oracle emulation.
+ */
+ public boolean treatEmptyStringsAsNull;
+
+ /**
+ * Support the pseudo-table SYSIBM.SYSDUMMY1.
+ */
+ public boolean sysDummy1;
+
+ /**
+ * Text can be concatenated using '+'.
+ */
+ public boolean allowPlusForStringConcat;
+
+ /**
+ * The single-argument function LOG() uses base 10 instead of E.
+ */
+ public boolean logIsLogBase10;
+
+ /**
+ * Swap the parameters of LOG() function.
+ */
+ public boolean swapLogFunctionParameters;
+
+ /**
+ * The function REGEXP_REPLACE() uses \ for back-references.
+ */
+ public boolean regexpReplaceBackslashReferences;
+
+ /**
+ * Swap the parameters of the CONVERT function.
+ */
+ public boolean swapConvertFunctionParameters;
+
+ /**
+ * can set the isolation level using WITH {RR|RS|CS|UR}
+ */
+ public boolean isolationLevelInSelectOrInsertStatement;
+
+ /**
+ * MySQL style INSERT ... ON DUPLICATE KEY UPDATE ... and INSERT IGNORE.
+ */
+ public boolean onDuplicateKeyUpdate;
+
+ /**
+ * MySQL style REPLACE INTO.
+ */
+ public boolean replaceInto;
+
+ /**
+ * PostgreSQL style INSERT ... ON CONFLICT DO NOTHING.
+ */
+ public boolean insertOnConflict;
+
+ /**
+ * Pattern describing the keys the java.sql.Connection.setClientInfo()
+ * method accepts.
+ */
+ public Pattern supportedClientInfoPropertiesRegEx;
+
+ /**
+ * Support the # for column names
+ */
+ public boolean supportPoundSymbolForColumnNames;
+
+ /**
+ * Whether IN predicate may have an empty value list.
+ */
+ public boolean allowEmptyInPredicate;
+
+ /**
+ * How to pad or trim CHAR values.
+ */
+ public CharPadding charPadding = CharPadding.ALWAYS;
+
+ /**
+ * Whether DB2 TIMESTAMP formats are allowed.
+ */
+ public boolean allowDB2TimestampFormat;
+
+ /**
+ * Discard SQLServer table hints (e.g. "SELECT * FROM table WITH (NOLOCK)")
+ */
+ public boolean discardWithTableHints;
+
+ /**
+ * If {@code true}, datetime value function return the same value within a
+ * transaction, if {@code false} datetime value functions return the same
+ * value within a command.
+ */
+ public boolean dateTimeValueWithinTransaction;
+
+ /**
+ * If {@code true} {@code 0x}-prefixed numbers are parsed as binary string
+ * literals, if {@code false} they are parsed as hexadecimal numeric values.
+ */
+ public boolean zeroExLiteralsAreBinaryStrings;
+
+ /**
+ * If {@code true} unrelated ORDER BY expression are allowed in DISTINCT
+ * queries, if {@code false} they are disallowed.
+ */
+ public boolean allowUnrelatedOrderByExpressionsInDistinctQueries;
+
+ /**
+ * If {@code true} some additional non-standard ALTER TABLE commands are allowed.
+ */
+ public boolean alterTableExtensionsMySQL;
+
+ /**
+ * If {@code true} non-standard ALTER TABLE MODIFY COLUMN is allowed.
+ */
+ public boolean alterTableModifyColumn;
+
+ /**
+ * If {@code true} TRUNCATE TABLE uses RESTART IDENTITY by default.
+ */
+ public boolean truncateTableRestartIdentity;
+
+ /**
+ * If {@code true} NEXT VALUE FOR SEQUENCE, CURRENT VALUE FOR SEQUENCE,
+ * SEQUENCE.NEXTVAL, and SEQUENCE.CURRVAL return values with DECIMAL/NUMERIC
+ * data type instead of BIGINT.
+ */
+ public boolean decimalSequences;
+
+ /**
+ * If {@code true} constructs like 'CREATE TABLE CATALOG..TABLE_NAME' are allowed,
+ * the default schema is used.
+ */
+ public boolean allowEmptySchemaValuesAsDefaultSchema;
+
+ /**
+ * If {@code true} all numeric data types may have precision and 'UNSIGNED'
+ * clause.
+ */
+ public boolean allNumericTypesHavePrecision;
+
+ /**
+ * If {@code true} 'FOR BIT DATA' clauses are allowed for character string
+ * data types.
+ */
+ public boolean forBitData;
+
+ /**
+ * If {@code true} 'CHAR' and 'BYTE' length units are allowed.
+ */
+ public boolean charAndByteLengthUnits;
+
+ /**
+ * If {@code true}, sequence.NEXTVAL and sequence.CURRVAL pseudo columns are
+ * supported.
+ */
+ public boolean nextvalAndCurrvalPseudoColumns;
+
+ /**
+ * If {@code true}, the next value expression returns different values when
+ * invoked multiple times within a row. This setting does not affect
+ * NEXTVAL() function.
+ */
+ public boolean nextValueReturnsDifferentValues;
+
+ /**
+ * If {@code true}, sequences of generated by default identity columns are
+ * updated when value is provided by user.
+ */
+ public boolean updateSequenceOnManualIdentityInsertion;
+
+ /**
+ * If {@code true}, last identity of the session is updated on insertion of
+ * a new value into identity column.
+ */
+ public boolean takeInsertedIdentity;
+
+ /**
+ * If {@code true}, last identity of the session is updated on generation of
+ * a new sequence value.
+ */
+ public boolean takeGeneratedSequenceValue;
+
+ /**
+ * If {@code true}, identity columns have DEFAULT ON NULL clause.
+ */
+ public boolean identityColumnsHaveDefaultOnNull;
+
+ /**
+ * If {@code true}, merge when matched clause may have WHERE clause.
+ */
+ public boolean mergeWhere;
+
+ /**
+ * If {@code true}, allow using from clause in update statement.
+ */
+ public boolean allowUsingFromClauseInUpdateStatement;
+
+ /**
+ * If {@code true}, referential constraints will create a unique constraint
+ * on referenced columns if it doesn't exist instead of throwing an
+ * exception.
+ */
+ public boolean createUniqueConstraintForReferencedColumns;
+
+ /**
+ * How column names are generated for expressions.
+ */
+ public ExpressionNames expressionNames = ExpressionNames.OPTIMIZED_SQL;
+
+ /**
+ * How column names are generated for views.
+ */
+ public ViewExpressionNames viewExpressionNames = ViewExpressionNames.AS_IS;
+
+ /**
+ * Whether TOP clause in SELECT queries is supported.
+ */
+ public boolean topInSelect;
+
+ /**
+ * Whether TOP clause in DML commands is supported.
+ */
+ public boolean topInDML;
+
+ /**
+ * Whether LIMIT / OFFSET clauses are supported.
+ */
+ public boolean limit;
+
+ /**
+ * Whether MINUS can be used as EXCEPT.
+ */
+ public boolean minusIsExcept;
+
+ /**
+ * Whether IDENTITY pseudo data type is supported.
+ */
+ public boolean identityDataType;
+
+ /**
+ * Whether SERIAL and BIGSERIAL pseudo data types are supported.
+ */
+ public boolean serialDataTypes;
+
+ /**
+ * Whether SQL Server-style IDENTITY clause is supported.
+ */
+ public boolean identityClause;
+
+ /**
+ * Whether MySQL-style AUTO_INCREMENT clause is supported.
+ */
+ public boolean autoIncrementClause;
+
+ /**
+ * Whether DATE data type is parsed as TIMESTAMP(0).
+ */
+ public boolean dateIsTimestamp0;
+
+ /**
+ * Whether NUMERIC and DECIMAL/DEC without parameters are parsed as DECFLOAT.
+ */
+ public boolean numericIsDecfloat;
+
+ /**
+ * An optional Set of hidden/disallowed column types.
+ * Certain DBMSs don't support all column types provided by H2, such as
+ * "NUMBER" when using PostgreSQL mode.
+ */
+ public Set disallowedTypes = Collections.emptySet();
+
+ /**
+ * Custom mappings from type names to data types.
+ */
+ public HashMap typeByNameMap = new HashMap<>();
+
+ /**
+ * Allow to use GROUP BY n, where n is column index in the SELECT list, similar to ORDER BY
+ */
+ public boolean groupByColumnIndex;
+
+ /**
+ * Allow to compare numeric with BOOLEAN.
+ */
+ public boolean numericWithBooleanComparison;
+
+ private final String name;
+
+ private final ModeEnum modeEnum;
+
+ static {
+ Mode mode = new Mode(ModeEnum.REGULAR);
+ mode.allowEmptyInPredicate = true;
+ mode.dateTimeValueWithinTransaction = true;
+ mode.topInSelect = true;
+ mode.limit = true;
+ mode.minusIsExcept = true;
+ mode.identityDataType = true;
+ mode.serialDataTypes = true;
+ mode.autoIncrementClause = true;
+ add(mode);
+
+ mode = new Mode(ModeEnum.STRICT);
+ mode.dateTimeValueWithinTransaction = true;
+ add(mode);
+
+ mode = new Mode(ModeEnum.LEGACY);
+ // Features of REGULAR mode
+ mode.allowEmptyInPredicate = true;
+ mode.dateTimeValueWithinTransaction = true;
+ mode.topInSelect = true;
+ mode.limit = true;
+ mode.minusIsExcept = true;
+ mode.identityDataType = true;
+ mode.serialDataTypes = true;
+ mode.autoIncrementClause = true;
+ // Legacy identity and sequence features
+ mode.identityClause = true;
+ mode.updateSequenceOnManualIdentityInsertion = true;
+ mode.takeInsertedIdentity = true;
+ mode.identityColumnsHaveDefaultOnNull = true;
+ mode.nextvalAndCurrvalPseudoColumns = true;
+ // Legacy DML features
+ mode.topInDML = true;
+ mode.mergeWhere = true;
+ // Legacy DDL features
+ mode.createUniqueConstraintForReferencedColumns = true;
+ // Legacy numeric with boolean comparison
+ mode.numericWithBooleanComparison = true;
+ // @legend-fix : dont do padding for char columns in legacy mode
+ mode.charPadding = CharPadding.NEVER;
+ add(mode);
+
+ mode = new Mode(ModeEnum.DB2);
+ mode.aliasColumnName = true;
+ mode.sysDummy1 = true;
+ mode.isolationLevelInSelectOrInsertStatement = true;
+ // See
+ // https://www.ibm.com/support/knowledgecenter/SSEPEK_11.0.0/
+ // com.ibm.db2z11.doc.java/src/tpc/imjcc_r0052001.dita
+ mode.supportedClientInfoPropertiesRegEx =
+ Pattern.compile("ApplicationName|ClientAccountingInformation|" +
+ "ClientUser|ClientCorrelationToken");
+ mode.allowDB2TimestampFormat = true;
+ mode.forBitData = true;
+ mode.takeInsertedIdentity = true;
+ mode.nextvalAndCurrvalPseudoColumns = true;
+ mode.expressionNames = ExpressionNames.NUMBER;
+ mode.viewExpressionNames = ViewExpressionNames.EXCEPTION;
+ mode.limit = true;
+ mode.minusIsExcept = true;
+ mode.numericWithBooleanComparison = true;
+ add(mode);
+
+ mode = new Mode(ModeEnum.Derby);
+ mode.aliasColumnName = true;
+ mode.uniqueIndexNullsHandling = UniqueIndexNullsHandling.FORBID_ANY_DUPLICATES;
+ mode.sysDummy1 = true;
+ mode.isolationLevelInSelectOrInsertStatement = true;
+ // Derby does not support client info properties as of version 10.12.1.1
+ mode.supportedClientInfoPropertiesRegEx = null;
+ mode.forBitData = true;
+ mode.takeInsertedIdentity = true;
+ mode.expressionNames = ExpressionNames.NUMBER;
+ mode.viewExpressionNames = ViewExpressionNames.EXCEPTION;
+ add(mode);
+
+ mode = new Mode(ModeEnum.HSQLDB);
+ mode.allowPlusForStringConcat = true;
+ mode.identityColumnsHaveDefaultOnNull = true;
+ // HSQLDB does not support client info properties. See
+ // http://hsqldb.org/doc/apidocs/org/hsqldb/jdbc/JDBCConnection.html#setClientInfo-java.lang.String-java.lang.String-
+ mode.supportedClientInfoPropertiesRegEx = null;
+ mode.expressionNames = ExpressionNames.C_NUMBER;
+ mode.topInSelect = true;
+ mode.limit = true;
+ mode.minusIsExcept = true;
+ mode.numericWithBooleanComparison = true;
+ add(mode);
+
+ mode = new Mode(ModeEnum.MSSQLServer);
+ mode.aliasColumnName = true;
+ mode.squareBracketQuotedNames = true;
+ mode.uniqueIndexNullsHandling = UniqueIndexNullsHandling.FORBID_ANY_DUPLICATES;
+ mode.allowPlusForStringConcat = true;
+ mode.swapLogFunctionParameters = 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;
+ mode.zeroExLiteralsAreBinaryStrings = true;
+ mode.truncateTableRestartIdentity = true;
+ mode.takeInsertedIdentity = true;
+ DataType dt = DataType.createNumeric(19, 4);
+ dt.type = Value.NUMERIC;
+ dt.sqlType = Types.NUMERIC;
+ dt.specialPrecisionScale = true;
+ mode.typeByNameMap.put("MONEY", dt);
+ dt = DataType.createNumeric(10, 4);
+ dt.type = Value.NUMERIC;
+ dt.sqlType = Types.NUMERIC;
+ dt.specialPrecisionScale = true;
+ mode.typeByNameMap.put("SMALLMONEY", dt);
+ mode.typeByNameMap.put("UNIQUEIDENTIFIER", DataType.getDataType(Value.UUID));
+ mode.allowEmptySchemaValuesAsDefaultSchema = true;
+ mode.expressionNames = ExpressionNames.EMPTY;
+ mode.viewExpressionNames = ViewExpressionNames.EXCEPTION;
+ mode.topInSelect = true;
+ mode.topInDML = true;
+ mode.identityClause = true;
+ mode.numericWithBooleanComparison = true;
+ add(mode);
+
+ mode = new Mode(ModeEnum.MariaDB);
+ mode.indexDefinitionInCreateTable = true;
+ mode.regexpReplaceBackslashReferences = true;
+ mode.onDuplicateKeyUpdate = true;
+ mode.replaceInto = true;
+ mode.charPadding = CharPadding.NEVER;
+ mode.supportedClientInfoPropertiesRegEx = Pattern.compile(".*");
+ mode.zeroExLiteralsAreBinaryStrings = true;
+ mode.allowUnrelatedOrderByExpressionsInDistinctQueries = true;
+ mode.alterTableExtensionsMySQL = true;
+ mode.alterTableModifyColumn = true;
+ mode.truncateTableRestartIdentity = true;
+ mode.allNumericTypesHavePrecision = true;
+ mode.nextValueReturnsDifferentValues = true;
+ mode.updateSequenceOnManualIdentityInsertion = true;
+ mode.takeInsertedIdentity = true;
+ mode.identityColumnsHaveDefaultOnNull = true;
+ mode.expressionNames = ExpressionNames.ORIGINAL_SQL;
+ mode.viewExpressionNames = ViewExpressionNames.MYSQL_STYLE;
+ mode.limit = true;
+ mode.autoIncrementClause = true;
+ mode.typeByNameMap.put("YEAR", DataType.getDataType(Value.SMALLINT));
+ mode.groupByColumnIndex = true;
+ mode.numericWithBooleanComparison = true;
+ add(mode);
+
+ mode = new Mode(ModeEnum.MySQL);
+ mode.indexDefinitionInCreateTable = true;
+ mode.regexpReplaceBackslashReferences = true;
+ mode.onDuplicateKeyUpdate = true;
+ mode.replaceInto = true;
+ mode.charPadding = CharPadding.NEVER;
+ // MySQL allows to use any key for client info entries. See
+ // https://github.com/mysql/mysql-connector-j/blob/5.1.47/src/com/mysql/jdbc/JDBC4CommentClientInfoProvider.java
+ mode.supportedClientInfoPropertiesRegEx =
+ Pattern.compile(".*");
+ mode.zeroExLiteralsAreBinaryStrings = true;
+ mode.allowUnrelatedOrderByExpressionsInDistinctQueries = true;
+ mode.alterTableExtensionsMySQL = true;
+ mode.alterTableModifyColumn = true;
+ mode.truncateTableRestartIdentity = true;
+ mode.allNumericTypesHavePrecision = true;
+ mode.updateSequenceOnManualIdentityInsertion = true;
+ mode.takeInsertedIdentity = true;
+ mode.identityColumnsHaveDefaultOnNull = true;
+ mode.createUniqueConstraintForReferencedColumns = true;
+ mode.expressionNames = ExpressionNames.ORIGINAL_SQL;
+ mode.viewExpressionNames = ViewExpressionNames.MYSQL_STYLE;
+ mode.limit = true;
+ mode.autoIncrementClause = true;
+ mode.typeByNameMap.put("YEAR", DataType.getDataType(Value.SMALLINT));
+ mode.groupByColumnIndex = true;
+ mode.numericWithBooleanComparison = true;
+ add(mode);
+
+ mode = new Mode(ModeEnum.Oracle);
+ mode.aliasColumnName = true;
+ mode.convertOnlyToSmallerScale = true;
+ mode.uniqueIndexNullsHandling = UniqueIndexNullsHandling.ALLOW_DUPLICATES_WITH_ALL_NULLS;
+ mode.treatEmptyStringsAsNull = true;
+ mode.regexpReplaceBackslashReferences = true;
+ mode.supportPoundSymbolForColumnNames = true;
+ // Oracle accepts keys of the form .*. See
+ // https://docs.oracle.com/database/121/JJDBC/jdbcvers.htm#JJDBC29006
+ mode.supportedClientInfoPropertiesRegEx =
+ Pattern.compile(".*\\..*");
+ mode.alterTableModifyColumn = true;
+ mode.decimalSequences = true;
+ mode.charAndByteLengthUnits = true;
+ mode.nextvalAndCurrvalPseudoColumns = true;
+ mode.mergeWhere = true;
+ mode.minusIsExcept = true;
+ mode.expressionNames = ExpressionNames.ORIGINAL_SQL;
+ mode.viewExpressionNames = ViewExpressionNames.EXCEPTION;
+ mode.dateIsTimestamp0 = true;
+ mode.typeByNameMap.put("BINARY_FLOAT", DataType.getDataType(Value.REAL));
+ mode.typeByNameMap.put("BINARY_DOUBLE", DataType.getDataType(Value.DOUBLE));
+ add(mode);
+
+ mode = new Mode(ModeEnum.PostgreSQL);
+ mode.aliasColumnName = true;
+ mode.systemColumns = true;
+ mode.logIsLogBase10 = true;
+ mode.regexpReplaceBackslashReferences = true;
+ mode.insertOnConflict = true;
+ // PostgreSQL only supports the ApplicationName property. See
+ // https://github.com/hhru/postgres-jdbc/blob/master/postgresql-jdbc-9.2-1002.src/
+ // org/postgresql/jdbc4/AbstractJdbc4Connection.java
+ mode.supportedClientInfoPropertiesRegEx =
+ Pattern.compile("ApplicationName");
+ mode.charPadding = CharPadding.IN_RESULT_SETS;
+ mode.nextValueReturnsDifferentValues = true;
+ mode.takeGeneratedSequenceValue = true;
+ mode.expressionNames = ExpressionNames.POSTGRESQL_STYLE;
+ mode.allowUsingFromClauseInUpdateStatement = true;
+ mode.limit = true;
+ mode.serialDataTypes = true;
+ mode.numericIsDecfloat = true;
+ // Enumerate all H2 types NOT supported by PostgreSQL:
+ Set disallowedTypes = new java.util.HashSet<>();
+ disallowedTypes.add("NUMBER");
+ disallowedTypes.add("TINYINT");
+ disallowedTypes.add("BLOB");
+ disallowedTypes.add("VARCHAR_IGNORECASE");
+ mode.disallowedTypes = disallowedTypes;
+ dt = DataType.getDataType(Value.JSON);
+ mode.typeByNameMap.put("JSONB", dt);
+ dt = DataType.createNumeric(19, 2);
+ dt.type = Value.NUMERIC;
+ dt.sqlType = Types.NUMERIC;
+ dt.specialPrecisionScale = true;
+ mode.typeByNameMap.put("MONEY", dt);
+ dt = DataType.getDataType(Value.INTEGER);
+ mode.typeByNameMap.put("OID", dt);
+ mode.dateTimeValueWithinTransaction = true;
+ mode.groupByColumnIndex = true;
+ add(mode);
+ }
+
+ private Mode(ModeEnum modeEnum) {
+ this.name = modeEnum.name();
+ this.modeEnum = modeEnum;
+ }
+
+ private static void add(Mode mode) {
+ MODES.put(StringUtils.toUpperEnglish(mode.name), mode);
+ }
+
+ /**
+ * Get the mode with the given name.
+ *
+ * @param name the name of the mode
+ * @return the mode object
+ */
+ public static Mode getInstance(String name) {
+ return MODES.get(StringUtils.toUpperEnglish(name));
+ }
+
+ public static Mode getRegular() {
+ return getInstance(ModeEnum.REGULAR.name());
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public ModeEnum getEnum() {
+ return this.modeEnum;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+}
diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/main/java/org/h2/value/TypeInfo.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/main/java/org/h2/value/TypeInfo.java
new file mode 100644
index 00000000000..be143d609b6
--- /dev/null
+++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/main/java/org/h2/value/TypeInfo.java
@@ -0,0 +1,1546 @@
+/*
+ * Copyright 2004-2022 H2 Group. Multiple-Licensed under the MPL 2.0,
+ * and the EPL 1.0 (https://h2database.com/html/license.html).
+ * Initial Developer: H2 Group
+ */
+package org.h2.value;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+
+import org.h2.api.ErrorCode;
+import org.h2.api.IntervalQualifier;
+import org.h2.engine.Constants;
+import org.h2.message.DbException;
+
+/**
+ * Data type with parameters.
+ */
+public class TypeInfo extends ExtTypeInfo implements Typed {
+
+ /**
+ * UNKNOWN type with parameters.
+ */
+ public static final TypeInfo TYPE_UNKNOWN;
+
+ /**
+ * NULL type with parameters.
+ */
+ public static final TypeInfo TYPE_NULL;
+
+ /**
+ * CHAR type with default parameters.
+ */
+ public static final TypeInfo TYPE_CHAR;
+
+ /**
+ * CHARACTER VARYING type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_VARCHAR;
+
+ /**
+ * VARCHAR_IGNORECASE type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_VARCHAR_IGNORECASE;
+
+ /**
+ * CHARACTER LARGE OBJECT type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_CLOB;
+
+ /**
+ * BINARY type with default parameters.
+ */
+ public static final TypeInfo TYPE_BINARY;
+
+ /**
+ * BINARY VARYING type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_VARBINARY;
+
+ /**
+ * BINARY LARGE OBJECT type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_BLOB;
+
+ /**
+ * BOOLEAN type with parameters.
+ */
+ public static final TypeInfo TYPE_BOOLEAN;
+
+ /**
+ * TINYINT type with parameters.
+ */
+ public static final TypeInfo TYPE_TINYINT;
+
+ /**
+ * SMALLINT type with parameters.
+ */
+ public static final TypeInfo TYPE_SMALLINT;
+
+ /**
+ * INTEGER type with parameters.
+ */
+ public static final TypeInfo TYPE_INTEGER;
+
+ /**
+ * BIGINT type with parameters.
+ */
+ public static final TypeInfo TYPE_BIGINT;
+
+ /**
+ * NUMERIC type with maximum precision and scale 0.
+ */
+ public static final TypeInfo TYPE_NUMERIC_SCALE_0;
+
+ /**
+ * NUMERIC type with parameters enough to hold a BIGINT value.
+ */
+ public static final TypeInfo TYPE_NUMERIC_BIGINT;
+
+ /**
+ * NUMERIC type that can hold values with floating point.
+ */
+ public static final TypeInfo TYPE_NUMERIC_FLOATING_POINT;
+
+ /**
+ * REAL type with parameters.
+ */
+ public static final TypeInfo TYPE_REAL;
+
+ /**
+ * DOUBLE PRECISION type with parameters.
+ */
+ public static final TypeInfo TYPE_DOUBLE;
+
+ /**
+ * DECFLOAT type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_DECFLOAT;
+
+ /**
+ * DECFLOAT type with parameters enough to hold a BIGINT value.
+ */
+ public static final TypeInfo TYPE_DECFLOAT_BIGINT;
+
+ /**
+ * DATE type with parameters.
+ */
+ public static final TypeInfo TYPE_DATE;
+
+ /**
+ * TIME type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_TIME;
+
+ /**
+ * TIME WITH TIME ZONE type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_TIME_TZ;
+
+ /**
+ * TIMESTAMP type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_TIMESTAMP;
+
+ /**
+ * TIMESTAMP WITH TIME ZONE type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_TIMESTAMP_TZ;
+
+ /**
+ * INTERVAL DAY type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_INTERVAL_DAY;
+
+ /**
+ * INTERVAL YEAR TO MONTH type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_INTERVAL_YEAR_TO_MONTH;
+
+ /**
+ * INTERVAL DAY TO SECOND type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_INTERVAL_DAY_TO_SECOND;
+
+ /**
+ * INTERVAL HOUR TO SECOND type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_INTERVAL_HOUR_TO_SECOND;
+
+ /**
+ * JAVA_OBJECT type with maximum parameters.
+ */
+ public static final TypeInfo TYPE_JAVA_OBJECT;
+
+ /**
+ * ENUM type with undefined parameters.
+ */
+ public static final TypeInfo TYPE_ENUM_UNDEFINED;
+
+ /**
+ * GEOMETRY type with default parameters.
+ */
+ public static final TypeInfo TYPE_GEOMETRY;
+
+ /**
+ * JSON type.
+ */
+ public static final TypeInfo TYPE_JSON;
+
+ /**
+ * UUID type with parameters.
+ */
+ public static final TypeInfo TYPE_UUID;
+
+ /**
+ * ARRAY type with unknown parameters.
+ */
+ public static final TypeInfo TYPE_ARRAY_UNKNOWN;
+
+ /**
+ * ROW (row value) type without fields.
+ */
+ public static final TypeInfo TYPE_ROW_EMPTY;
+
+ private static final TypeInfo[] TYPE_INFOS_BY_VALUE_TYPE;
+
+ private final int valueType;
+
+ private final long precision;
+
+ private final int scale;
+
+ private final ExtTypeInfo extTypeInfo;
+
+ static {
+ TypeInfo[] infos = new TypeInfo[Value.TYPE_COUNT];
+ TYPE_UNKNOWN = new TypeInfo(Value.UNKNOWN);
+ // NULL
+ infos[Value.NULL] = TYPE_NULL = new TypeInfo(Value.NULL);
+ // CHARACTER
+ infos[Value.CHAR] = TYPE_CHAR = new TypeInfo(Value.CHAR, -1L);
+ infos[Value.VARCHAR] = TYPE_VARCHAR = new TypeInfo(Value.VARCHAR);
+ infos[Value.CLOB] = TYPE_CLOB = new TypeInfo(Value.CLOB);
+ infos[Value.VARCHAR_IGNORECASE] = TYPE_VARCHAR_IGNORECASE = new TypeInfo(Value.VARCHAR_IGNORECASE);
+ // BINARY
+ infos[Value.BINARY] = TYPE_BINARY = new TypeInfo(Value.BINARY, -1L);
+ infos[Value.VARBINARY] = TYPE_VARBINARY = new TypeInfo(Value.VARBINARY);
+ infos[Value.BLOB] = TYPE_BLOB = new TypeInfo(Value.BLOB);
+ // BOOLEAN
+ infos[Value.BOOLEAN] = TYPE_BOOLEAN = new TypeInfo(Value.BOOLEAN);
+ // NUMERIC
+ infos[Value.TINYINT] = TYPE_TINYINT = new TypeInfo(Value.TINYINT);
+ infos[Value.SMALLINT] = TYPE_SMALLINT = new TypeInfo(Value.SMALLINT);
+ infos[Value.INTEGER] = TYPE_INTEGER = new TypeInfo(Value.INTEGER);
+ infos[Value.BIGINT] = TYPE_BIGINT = new TypeInfo(Value.BIGINT);
+ TYPE_NUMERIC_SCALE_0 = new TypeInfo(Value.NUMERIC, Constants.MAX_NUMERIC_PRECISION, 0, null);
+ TYPE_NUMERIC_BIGINT = new TypeInfo(Value.NUMERIC, ValueBigint.DECIMAL_PRECISION, 0, null);
+ infos[Value.NUMERIC] = TYPE_NUMERIC_FLOATING_POINT = new TypeInfo(Value.NUMERIC,
+ Constants.MAX_NUMERIC_PRECISION, Constants.MAX_NUMERIC_PRECISION / 2, null);
+ infos[Value.REAL] = TYPE_REAL = new TypeInfo(Value.REAL);
+ infos[Value.DOUBLE] = TYPE_DOUBLE = new TypeInfo(Value.DOUBLE);
+ infos[Value.DECFLOAT] = TYPE_DECFLOAT = new TypeInfo(Value.DECFLOAT);
+ TYPE_DECFLOAT_BIGINT = new TypeInfo(Value.DECFLOAT, (long) ValueBigint.DECIMAL_PRECISION);
+ // DATETIME
+ infos[Value.DATE] = TYPE_DATE = new TypeInfo(Value.DATE);
+ infos[Value.TIME] = TYPE_TIME = new TypeInfo(Value.TIME, ValueTime.MAXIMUM_SCALE);
+ infos[Value.TIME_TZ] = TYPE_TIME_TZ = new TypeInfo(Value.TIME_TZ, ValueTime.MAXIMUM_SCALE);
+ infos[Value.TIMESTAMP] = TYPE_TIMESTAMP = new TypeInfo(Value.TIMESTAMP, ValueTimestamp.MAXIMUM_SCALE);
+ infos[Value.TIMESTAMP_TZ] = TYPE_TIMESTAMP_TZ = new TypeInfo(Value.TIMESTAMP_TZ, ValueTimestamp.MAXIMUM_SCALE);
+ // INTERVAL
+ for (int i = Value.INTERVAL_YEAR; i <= Value.INTERVAL_MINUTE_TO_SECOND; i++) {
+ infos[i] = new TypeInfo(i, ValueInterval.MAXIMUM_PRECISION,
+ IntervalQualifier.valueOf(i - Value.INTERVAL_YEAR).hasSeconds() ? ValueInterval.MAXIMUM_SCALE : -1,
+ null);
+ }
+ TYPE_INTERVAL_DAY = infos[Value.INTERVAL_DAY];
+ TYPE_INTERVAL_YEAR_TO_MONTH = infos[Value.INTERVAL_YEAR_TO_MONTH];
+ TYPE_INTERVAL_DAY_TO_SECOND = infos[Value.INTERVAL_DAY_TO_SECOND];
+ TYPE_INTERVAL_HOUR_TO_SECOND = infos[Value.INTERVAL_HOUR_TO_SECOND];
+ // OTHER
+ infos[Value.JAVA_OBJECT] = TYPE_JAVA_OBJECT = new TypeInfo(Value.JAVA_OBJECT);
+ infos[Value.ENUM] = TYPE_ENUM_UNDEFINED = new TypeInfo(Value.ENUM);
+ infos[Value.GEOMETRY] = TYPE_GEOMETRY = new TypeInfo(Value.GEOMETRY);
+ infos[Value.JSON] = TYPE_JSON = new TypeInfo(Value.JSON);
+ infos[Value.UUID] = TYPE_UUID = new TypeInfo(Value.UUID);
+ // COLLECTION
+ infos[Value.ARRAY] = TYPE_ARRAY_UNKNOWN = new TypeInfo(Value.ARRAY);
+ infos[Value.ROW] = TYPE_ROW_EMPTY = new TypeInfo(Value.ROW, -1L, -1, //
+ new ExtTypeInfoRow(new LinkedHashMap<>()));
+ TYPE_INFOS_BY_VALUE_TYPE = infos;
+ }
+
+ /**
+ * Get the data type with parameters object for the given value type and
+ * maximum parameters.
+ *
+ * @param type
+ * the value type
+ * @return the data type with parameters object
+ */
+ public static TypeInfo getTypeInfo(int type) {
+ if (type == Value.UNKNOWN) {
+ throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "?");
+ }
+ if (type >= Value.NULL && type < Value.TYPE_COUNT) {
+ TypeInfo t = TYPE_INFOS_BY_VALUE_TYPE[type];
+ if (t != null) {
+ return t;
+ }
+ }
+ return TYPE_NULL;
+ }
+
+ /**
+ * Get the data type with parameters object for the given value type and the
+ * specified parameters.
+ *
+ * @param type
+ * the value type
+ * @param precision
+ * the precision or {@code -1L} for default
+ * @param scale
+ * the scale or {@code -1} for default
+ * @param extTypeInfo
+ * the extended type information or null
+ * @return the data type with parameters object
+ */
+ public static TypeInfo getTypeInfo(int type, long precision, int scale, ExtTypeInfo extTypeInfo) {
+ switch (type) {
+ case Value.NULL:
+ case Value.BOOLEAN:
+ case Value.TINYINT:
+ case Value.SMALLINT:
+ case Value.INTEGER:
+ case Value.BIGINT:
+ case Value.DATE:
+ case Value.UUID:
+ return TYPE_INFOS_BY_VALUE_TYPE[type];
+ case Value.UNKNOWN:
+ return TYPE_UNKNOWN;
+ case Value.CHAR:
+ if (precision < 1) {
+ return TYPE_CHAR;
+ }
+ if (precision > Constants.MAX_STRING_LENGTH) {
+ precision = Constants.MAX_STRING_LENGTH;
+ }
+ return new TypeInfo(Value.CHAR, precision);
+ case Value.VARCHAR:
+ if (precision < 1 || precision >= Constants.MAX_STRING_LENGTH) {
+ if (precision != 0) {
+ return TYPE_VARCHAR;
+ }
+ precision = 1;
+ }
+ return new TypeInfo(Value.VARCHAR, precision);
+ case Value.CLOB:
+ if (precision < 1) {
+ return TYPE_CLOB;
+ }
+ return new TypeInfo(Value.CLOB, precision);
+ case Value.VARCHAR_IGNORECASE:
+ if (precision < 1 || precision >= Constants.MAX_STRING_LENGTH) {
+ if (precision != 0) {
+ return TYPE_VARCHAR_IGNORECASE;
+ }
+ precision = 1;
+ }
+ return new TypeInfo(Value.VARCHAR_IGNORECASE, precision);
+ case Value.BINARY:
+ if (precision < 1) {
+ return TYPE_BINARY;
+ }
+ if (precision > Constants.MAX_STRING_LENGTH) {
+ precision = Constants.MAX_STRING_LENGTH;
+ }
+ return new TypeInfo(Value.BINARY, precision);
+ case Value.VARBINARY:
+ if (precision < 1 || precision >= Constants.MAX_STRING_LENGTH) {
+ if (precision != 0) {
+ return TYPE_VARBINARY;
+ }
+ precision = 1;
+ }
+ return new TypeInfo(Value.VARBINARY, precision);
+ case Value.BLOB:
+ if (precision < 1) {
+ return TYPE_BLOB;
+ }
+ return new TypeInfo(Value.BLOB, precision);
+ case Value.NUMERIC:
+ if (precision < 1) {
+ precision = -1L;
+ } else if (precision > Constants.MAX_NUMERIC_PRECISION) {
+ precision = Constants.MAX_NUMERIC_PRECISION;
+ }
+ if (scale < 0) {
+ scale = -1;
+ } else if (scale > ValueNumeric.MAXIMUM_SCALE) {
+ scale = ValueNumeric.MAXIMUM_SCALE;
+ }
+ return new TypeInfo(Value.NUMERIC, precision, scale,
+ extTypeInfo instanceof ExtTypeInfoNumeric ? extTypeInfo : null);
+ case Value.REAL:
+ if (precision >= 1 && precision <= 24) {
+ return new TypeInfo(Value.REAL, precision, -1, extTypeInfo);
+ }
+ return TYPE_REAL;
+ case Value.DOUBLE:
+ if (precision == 0 || precision >= 25 && precision <= 53) {
+ return new TypeInfo(Value.DOUBLE, precision, -1, extTypeInfo);
+ }
+ return TYPE_DOUBLE;
+ case Value.DECFLOAT:
+ if (precision < 1) {
+ precision = -1L;
+ } else if (precision >= Constants.MAX_NUMERIC_PRECISION) {
+ return TYPE_DECFLOAT;
+ }
+ return new TypeInfo(Value.DECFLOAT, precision, -1, null);
+ case Value.TIME:
+ if (scale < 0) {
+ scale = -1;
+ } else if (scale >= ValueTime.MAXIMUM_SCALE) {
+ return TYPE_TIME;
+ }
+ return new TypeInfo(Value.TIME, scale);
+ case Value.TIME_TZ:
+ if (scale < 0) {
+ scale = -1;
+ } else if (scale >= ValueTime.MAXIMUM_SCALE) {
+ return TYPE_TIME_TZ;
+ }
+ return new TypeInfo(Value.TIME_TZ, scale);
+ case Value.TIMESTAMP:
+ if (scale < 0) {
+ scale = -1;
+ } else if (scale >= ValueTimestamp.MAXIMUM_SCALE) {
+ return TYPE_TIMESTAMP;
+ }
+ return new TypeInfo(Value.TIMESTAMP, scale);
+ case Value.TIMESTAMP_TZ:
+ if (scale < 0) {
+ scale = -1;
+ } else if (scale >= ValueTimestamp.MAXIMUM_SCALE) {
+ return TYPE_TIMESTAMP_TZ;
+ }
+ return new TypeInfo(Value.TIMESTAMP_TZ, scale);
+ case Value.INTERVAL_YEAR:
+ case Value.INTERVAL_MONTH:
+ case Value.INTERVAL_DAY:
+ case Value.INTERVAL_HOUR:
+ case Value.INTERVAL_MINUTE:
+ case Value.INTERVAL_YEAR_TO_MONTH:
+ case Value.INTERVAL_DAY_TO_HOUR:
+ case Value.INTERVAL_DAY_TO_MINUTE:
+ case Value.INTERVAL_HOUR_TO_MINUTE:
+ if (precision < 1) {
+ precision = -1L;
+ } else if (precision > ValueInterval.MAXIMUM_PRECISION) {
+ precision = ValueInterval.MAXIMUM_PRECISION;
+ }
+ return new TypeInfo(type, precision);
+ case Value.INTERVAL_SECOND:
+ case Value.INTERVAL_DAY_TO_SECOND:
+ case Value.INTERVAL_HOUR_TO_SECOND:
+ case Value.INTERVAL_MINUTE_TO_SECOND:
+ if (precision < 1) {
+ precision = -1L;
+ } else if (precision > ValueInterval.MAXIMUM_PRECISION) {
+ precision = ValueInterval.MAXIMUM_PRECISION;
+ }
+ if (scale < 0) {
+ scale = -1;
+ } else if (scale > ValueInterval.MAXIMUM_SCALE) {
+ scale = ValueInterval.MAXIMUM_SCALE;
+ }
+ return new TypeInfo(type, precision, scale, null);
+ case Value.JAVA_OBJECT:
+ if (precision < 1) {
+ return TYPE_JAVA_OBJECT;
+ } else if (precision > Constants.MAX_STRING_LENGTH) {
+ precision = Constants.MAX_STRING_LENGTH;
+ }
+ return new TypeInfo(Value.JAVA_OBJECT, precision);
+ case Value.ENUM:
+ if (extTypeInfo instanceof ExtTypeInfoEnum) {
+ return ((ExtTypeInfoEnum) extTypeInfo).getType();
+ } else {
+ return TYPE_ENUM_UNDEFINED;
+ }
+ case Value.GEOMETRY:
+ if (extTypeInfo instanceof ExtTypeInfoGeometry) {
+ return new TypeInfo(Value.GEOMETRY, -1L, -1, extTypeInfo);
+ } else {
+ return TYPE_GEOMETRY;
+ }
+ case Value.JSON:
+ if (precision < 1) {
+ return TYPE_JSON;
+ } else if (precision > Constants.MAX_STRING_LENGTH) {
+ precision = Constants.MAX_STRING_LENGTH;
+ }
+ return new TypeInfo(Value.JSON, precision);
+ case Value.ARRAY:
+ if (!(extTypeInfo instanceof TypeInfo)) {
+ throw new IllegalArgumentException();
+ }
+ if (precision < 0 || precision >= Constants.MAX_ARRAY_CARDINALITY) {
+ precision = -1L;
+ }
+ return new TypeInfo(Value.ARRAY, precision, -1, extTypeInfo);
+ case Value.ROW:
+ if (!(extTypeInfo instanceof ExtTypeInfoRow)) {
+ throw new IllegalArgumentException();
+ }
+ return new TypeInfo(Value.ROW, -1L, -1, extTypeInfo);
+ }
+ return TYPE_NULL;
+ }
+
+ /**
+ * Get the higher data type of all values.
+ *
+ * @param values
+ * the values
+ * @return the higher data type
+ */
+ public static TypeInfo getHigherType(Typed[] values) {
+ int cardinality = values.length;
+ TypeInfo type;
+ if (cardinality == 0) {
+ type = TypeInfo.TYPE_NULL;
+ } else {
+ type = values[0].getType();
+ boolean hasUnknown = false, hasNull = false;
+ switch (type.getValueType()) {
+ case Value.UNKNOWN:
+ hasUnknown = true;
+ break;
+ case Value.NULL:
+ hasNull = true;
+ }
+ for (int i = 1; i < cardinality; i++) {
+ TypeInfo t = values[i].getType();
+ switch (t.getValueType()) {
+ case Value.UNKNOWN:
+ hasUnknown = true;
+ break;
+ case Value.NULL:
+ hasNull = true;
+ break;
+ default:
+ type = getHigherType(type, t);
+ }
+ }
+ if (type.getValueType() <= Value.NULL && hasUnknown) {
+ throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, hasNull ? "NULL, ?" : "?");
+ }
+ }
+ return type;
+ }
+
+ /**
+ * Get the higher data type of two data types. If values need to be
+ * converted to match the other operands data type, the value with the lower
+ * order is converted to the value with the higher order.
+ *
+ * @param type1
+ * the first data type
+ * @param type2
+ * the second data type
+ * @return the higher data type of the two
+ */
+ public static TypeInfo getHigherType(TypeInfo type1, TypeInfo type2) {
+ int t1 = type1.getValueType(), t2 = type2.getValueType(), dataType;
+ if (t1 == t2) {
+ if (t1 == Value.UNKNOWN) {
+ throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "?, ?");
+ }
+ dataType = t1;
+ } else {
+ if (t1 < t2) {
+ int t = t1;
+ t1 = t2;
+ t2 = t;
+ TypeInfo type = type1;
+ type1 = type2;
+ type2 = type;
+ }
+ if (t1 == Value.UNKNOWN) {
+ if (t2 == Value.NULL) {
+ throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "?, NULL");
+ }
+ return type2;
+ } else if (t2 == Value.UNKNOWN) {
+ if (t1 == Value.NULL) {
+ throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, "NULL, ?");
+ }
+ return type1;
+ }
+ if (t2 == Value.NULL) {
+ return type1;
+ }
+ dataType = Value.getHigherOrderKnown(t1, t2);
+ }
+ long precision;
+ switch (dataType) {
+ case Value.NUMERIC: {
+ type1 = type1.toNumericType();
+ type2 = type2.toNumericType();
+ long precision1 = type1.getPrecision(), precision2 = type2.getPrecision();
+ int scale1 = type1.getScale(), scale2 = type2.getScale(), scale;
+ if (scale1 < scale2) {
+ precision1 += scale2 - scale1;
+ scale = scale2;
+ } else {
+ precision2 += scale1 - scale2;
+ scale = scale1;
+ }
+ return TypeInfo.getTypeInfo(Value.NUMERIC, Math.max(precision1, precision2), scale, null);
+ }
+ case Value.REAL:
+ case Value.DOUBLE:
+ precision = -1L;
+ break;
+ case Value.GEOMETRY:
+ return getHigherGeometry(type1, type2);
+ case Value.ARRAY:
+ return getHigherArray(type1, type2, dimensions(type1), dimensions(type2));
+ case Value.ROW:
+ return getHigherRow(type1, type2);
+ default:
+ precision = Math.max(type1.getPrecision(), type2.getPrecision());
+ }
+ ExtTypeInfo ext1 = type1.extTypeInfo;
+ return TypeInfo.getTypeInfo(dataType, //
+ precision, //
+ Math.max(type1.getScale(), type2.getScale()), //
+ dataType == t1 && ext1 != null ? ext1 : dataType == t2 ? type2.extTypeInfo : null);
+ }
+
+ private static TypeInfo getHigherGeometry(TypeInfo type1, TypeInfo type2) {
+ int t;
+ Integer srid;
+ ExtTypeInfo ext1 = type1.getExtTypeInfo(), ext2 = type2.getExtTypeInfo();
+ if (ext1 instanceof ExtTypeInfoGeometry) {
+ if (ext2 instanceof ExtTypeInfoGeometry) {
+ ExtTypeInfoGeometry g1 = (ExtTypeInfoGeometry) ext1, g2 = (ExtTypeInfoGeometry) ext2;
+ t = g1.getType();
+ srid = g1.getSrid();
+ int t2 = g2.getType();
+ Integer srid2 = g2.getSrid();
+ if (Objects.equals(srid, srid2)) {
+ if (t == t2) {
+ return type1;
+ } else if (srid == null) {
+ return TYPE_GEOMETRY;
+ } else {
+ t = 0;
+ }
+ } else if (srid == null || srid2 == null) {
+ if (t == 0 || t != t2) {
+ return TYPE_GEOMETRY;
+ } else {
+ srid = null;
+ }
+ } else {
+ throw DbException.get(ErrorCode.TYPES_ARE_NOT_COMPARABLE_2, type1.getTraceSQL(),
+ type2.getTraceSQL());
+ }
+ } else {
+ return type2.getValueType() == Value.GEOMETRY ? TypeInfo.TYPE_GEOMETRY : type1;
+ }
+ } else if (ext2 instanceof ExtTypeInfoGeometry) {
+ return type1.getValueType() == Value.GEOMETRY ? TypeInfo.TYPE_GEOMETRY : type2;
+ } else {
+ return TYPE_GEOMETRY;
+ }
+ return new TypeInfo(Value.GEOMETRY, -1L, -1, new ExtTypeInfoGeometry(t, srid));
+ }
+
+ private static int dimensions(TypeInfo type) {
+ int result;
+ for (result = 0; type.getValueType() == Value.ARRAY; result++) {
+ type = (TypeInfo) type.extTypeInfo;
+ }
+ return result;
+ }
+
+ private static TypeInfo getHigherArray(TypeInfo type1, TypeInfo type2, int d1, int d2) {
+ long precision;
+ if (d1 > d2) {
+ d1--;
+ precision = Math.max(type1.getPrecision(), 1L);
+ type1 = (TypeInfo) type1.extTypeInfo;
+ } else if (d1 < d2) {
+ d2--;
+ precision = Math.max(1L, type2.getPrecision());
+ type2 = (TypeInfo) type2.extTypeInfo;
+ } else if (d1 > 0) {
+ d1--;
+ d2--;
+ precision = Math.max(type1.getPrecision(), type2.getPrecision());
+ type1 = (TypeInfo) type1.extTypeInfo;
+ type2 = (TypeInfo) type2.extTypeInfo;
+ } else {
+ return getHigherType(type1, type2);
+ }
+ return TypeInfo.getTypeInfo(Value.ARRAY, precision, 0, getHigherArray(type1, type2, d1, d2));
+ }
+
+ private static TypeInfo getHigherRow(TypeInfo type1, TypeInfo type2) {
+ if (type1.getValueType() != Value.ROW) {
+ type1 = typeToRow(type1);
+ }
+ if (type2.getValueType() != Value.ROW) {
+ type2 = typeToRow(type2);
+ }
+ ExtTypeInfoRow ext1 = (ExtTypeInfoRow) type1.getExtTypeInfo(), ext2 = (ExtTypeInfoRow) type2.getExtTypeInfo();
+ if (ext1.equals(ext2)) {
+ return type1;
+ }
+ Set> m1 = ext1.getFields(), m2 = ext2.getFields();
+ int degree = m1.size();
+ if (m2.size() != degree) {
+ throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH);
+ }
+ LinkedHashMap m = new LinkedHashMap<>((int) Math.ceil(degree / .75));
+ for (Iterator> i1 = m1.iterator(), i2 = m2.iterator(); i1.hasNext();) {
+ Map.Entry e1 = i1.next();
+ m.put(e1.getKey(), getHigherType(e1.getValue(), i2.next().getValue()));
+ }
+ return TypeInfo.getTypeInfo(Value.ROW, 0, 0, new ExtTypeInfoRow(m));
+ }
+
+ private static TypeInfo typeToRow(TypeInfo type) {
+ LinkedHashMap map = new LinkedHashMap<>(2);
+ map.put("C1", type);
+ return TypeInfo.getTypeInfo(Value.ROW, 0, 0, new ExtTypeInfoRow(map));
+ }
+
+ /**
+ * Determines whether two specified types are the same data types without
+ * taking precision or scale into account.
+ *
+ * @param t1
+ * first data type
+ * @param t2
+ * second data type
+ * @return whether types are the same
+ */
+ public static boolean areSameTypes(TypeInfo t1, TypeInfo t2) {
+ for (;;) {
+ int valueType = t1.getValueType();
+ if (valueType != t2.getValueType()) {
+ return false;
+ }
+ ExtTypeInfo ext1 = t1.getExtTypeInfo(), ext2 = t2.getExtTypeInfo();
+ if (valueType != Value.ARRAY) {
+ return Objects.equals(ext1, ext2);
+ }
+ t1 = (TypeInfo) ext1;
+ t2 = (TypeInfo) ext2;
+ }
+ }
+
+ /**
+ * Checks whether two specified types are comparable and throws an exception
+ * otherwise.
+ *
+ * @param t1
+ * first data type
+ * @param t2
+ * second data type
+ * @throws DbException
+ * if types aren't comparable
+ */
+ public static void checkComparable(TypeInfo t1, TypeInfo t2) {
+ if (!areComparable(t1, t2)) {
+ throw DbException.get(ErrorCode.TYPES_ARE_NOT_COMPARABLE_2, t1.getTraceSQL(), t2.getTraceSQL());
+ }
+ }
+
+ /**
+ * Determines whether two specified types are comparable.
+ *
+ * @param t1
+ * first data type
+ * @param t2
+ * second data type
+ * @return whether types are comparable
+ */
+ private static boolean areComparable(TypeInfo t1, TypeInfo t2) {
+ int vt1 = (t1 = t1.unwrapRow()).getValueType(), vt2 = (t2 = t2.unwrapRow()).getValueType();
+ if (vt1 > vt2) {
+ int vt = vt1;
+ vt1 = vt2;
+ vt2 = vt;
+ TypeInfo t = t1;
+ t1 = t2;
+ t2 = t;
+ }
+ if (vt1 <= Value.NULL) {
+ return true;
+ }
+ if (vt1 == vt2) {
+ switch (vt1) {
+ case Value.ARRAY:
+ return areComparable((TypeInfo) t1.getExtTypeInfo(), (TypeInfo) t2.getExtTypeInfo());
+ case Value.ROW: {
+ Set> f1 = ((ExtTypeInfoRow) t1.getExtTypeInfo()).getFields();
+ Set> f2 = ((ExtTypeInfoRow) t2.getExtTypeInfo()).getFields();
+ int degree = f1.size();
+ if (f2.size() != degree) {
+ return false;
+ }
+ Iterator> i1 = f1.iterator(), i2 = f2.iterator();
+ while (i1.hasNext()) {
+ if (!areComparable(i1.next().getValue(), i2.next().getValue())) {
+ return false;
+ }
+ }
+ }
+ //$FALL-THROUGH$
+ default:
+ return true;
+ }
+ }
+ byte g1 = Value.GROUPS[vt1], g2 = Value.GROUPS[vt2];
+ if (g1 == g2) {
+ switch (g1) {
+ default:
+ return true;
+ case Value.GROUP_DATETIME:
+ return vt1 != Value.DATE || vt2 != Value.TIME && vt2 != Value.TIME_TZ;
+ case Value.GROUP_OTHER:
+ case Value.GROUP_COLLECTION:
+ return false;
+ }
+ }
+ switch (g1) {
+ case Value.GROUP_BOOLEAN:
+ switch (g2) {
+ case Value.GROUP_NUMERIC:
+ return true; // @legend-fix : allow numeric to boolean comparisons
+ default:
+ return false;
+ }
+ case Value.GROUP_CHARACTER_STRING:
+ switch (g2) {
+ case Value.GROUP_NUMERIC:
+ case Value.GROUP_DATETIME:
+ case Value.GROUP_INTERVAL_YM:
+ case Value.GROUP_INTERVAL_DT:
+ case Value.GROUP_BOOLEAN: // @legend-fix : allow varchar to boolean comparisons
+ return true;
+ case Value.GROUP_OTHER:
+ switch (vt2) {
+ case Value.ENUM:
+ case Value.GEOMETRY:
+ case Value.JSON:
+ case Value.UUID:
+ return true;
+ default:
+ return false;
+ }
+ default:
+ return false;
+ }
+ case Value.GROUP_BINARY_STRING:
+ switch (vt2) {
+ case Value.JAVA_OBJECT:
+ case Value.GEOMETRY:
+ case Value.JSON:
+ case Value.UUID:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Determines whether two specified types have the same ordering rules.
+ *
+ * @param t1
+ * first data type
+ * @param t2
+ * second data type
+ * @return whether types are comparable
+ */
+ public static boolean haveSameOrdering(TypeInfo t1, TypeInfo t2) {
+ int vt1 = (t1 = t1.unwrapRow()).getValueType(), vt2 = (t2 = t2.unwrapRow()).getValueType();
+ if (vt1 > vt2) {
+ int vt = vt1;
+ vt1 = vt2;
+ vt2 = vt;
+ TypeInfo t = t1;
+ t1 = t2;
+ t2 = t;
+ }
+ if (vt1 <= Value.NULL) {
+ return true;
+ }
+ if (vt1 == vt2) {
+ switch (vt1) {
+ case Value.ARRAY:
+ return haveSameOrdering((TypeInfo) t1.getExtTypeInfo(), (TypeInfo) t2.getExtTypeInfo());
+ case Value.ROW: {
+ Set> f1 = ((ExtTypeInfoRow) t1.getExtTypeInfo()).getFields();
+ Set> f2 = ((ExtTypeInfoRow) t2.getExtTypeInfo()).getFields();
+ int degree = f1.size();
+ if (f2.size() != degree) {
+ return false;
+ }
+ Iterator> i1 = f1.iterator(), i2 = f2.iterator();
+ while (i1.hasNext()) {
+ if (!haveSameOrdering(i1.next().getValue(), i2.next().getValue())) {
+ return false;
+ }
+ }
+ }
+ //$FALL-THROUGH$
+ default:
+ return true;
+ }
+ }
+ byte g1 = Value.GROUPS[vt1], g2 = Value.GROUPS[vt2];
+ if (g1 == g2) {
+ switch (g1) {
+ default:
+ return true;
+ case Value.GROUP_CHARACTER_STRING:
+ return (vt1 == Value.VARCHAR_IGNORECASE) == (vt2 == Value.VARCHAR_IGNORECASE);
+ case Value.GROUP_DATETIME:
+ switch (vt1) {
+ case Value.DATE:
+ return vt2 == Value.TIMESTAMP || vt2 == Value.TIMESTAMP_TZ;
+ case Value.TIME:
+ case Value.TIME_TZ:
+ return vt2 == Value.TIME || vt2 == Value.TIME_TZ;
+ default: // TIMESTAMP TIMESTAMP_TZ
+ return true;
+ }
+ case Value.GROUP_OTHER:
+ case Value.GROUP_COLLECTION:
+ return false;
+ }
+ }
+ if (g1 == Value.GROUP_BINARY_STRING) {
+ switch (vt2) {
+ case Value.JAVA_OBJECT:
+ case Value.GEOMETRY:
+ case Value.JSON:
+ case Value.UUID:
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+ }
+
+ private TypeInfo(int valueType) {
+ this.valueType = valueType;
+ precision = -1L;
+ scale = -1;
+ extTypeInfo = null;
+ }
+
+ private TypeInfo(int valueType, long precision) {
+ this.valueType = valueType;
+ this.precision = precision;
+ scale = -1;
+ extTypeInfo = null;
+ }
+
+ private TypeInfo(int valueType, int scale) {
+ this.valueType = valueType;
+ precision = -1L;
+ this.scale = scale;
+ extTypeInfo = null;
+ }
+
+ /**
+ * Creates new instance of data type with parameters.
+ *
+ * @param valueType
+ * the value type
+ * @param precision
+ * the precision
+ * @param scale
+ * the scale
+ * @param extTypeInfo
+ * the extended type information, or null
+ */
+ public TypeInfo(int valueType, long precision, int scale, ExtTypeInfo extTypeInfo) {
+ this.valueType = valueType;
+ this.precision = precision;
+ this.scale = scale;
+ this.extTypeInfo = extTypeInfo;
+ }
+
+ /**
+ * Returns this type information.
+ *
+ * @return this
+ */
+ @Override
+ public TypeInfo getType() {
+ return this;
+ }
+
+ /**
+ * Returns the value type.
+ *
+ * @return the value type
+ */
+ public int getValueType() {
+ return valueType;
+ }
+
+ /**
+ * Returns the precision.
+ *
+ * @return the precision
+ */
+ public long getPrecision() {
+ switch (valueType) {
+ case Value.UNKNOWN:
+ return -1L;
+ case Value.NULL:
+ return ValueNull.PRECISION;
+ case Value.CHAR:
+ case Value.BINARY:
+ return precision >= 0L ? precision : 1L;
+ case Value.VARCHAR:
+ case Value.VARCHAR_IGNORECASE:
+ case Value.VARBINARY:
+ case Value.JAVA_OBJECT:
+ case Value.ENUM:
+ case Value.GEOMETRY:
+ case Value.JSON:
+ return precision >= 0L ? precision : Constants.MAX_STRING_LENGTH;
+ case Value.CLOB:
+ case Value.BLOB:
+ return precision >= 0L ? precision : Long.MAX_VALUE;
+ case Value.BOOLEAN:
+ return ValueBoolean.PRECISION;
+ case Value.TINYINT:
+ return ValueTinyint.PRECISION;
+ case Value.SMALLINT:
+ return ValueSmallint.PRECISION;
+ case Value.INTEGER:
+ return ValueInteger.PRECISION;
+ case Value.BIGINT:
+ return ValueBigint.PRECISION;
+ case Value.NUMERIC:
+ return precision >= 0L ? precision : Constants.MAX_NUMERIC_PRECISION;
+ case Value.REAL:
+ return ValueReal.PRECISION;
+ case Value.DOUBLE:
+ return ValueDouble.PRECISION;
+ case Value.DECFLOAT:
+ return precision >= 0L ? precision : Constants.MAX_NUMERIC_PRECISION;
+ case Value.DATE:
+ return ValueDate.PRECISION;
+ case Value.TIME: {
+ int s = scale >= 0 ? scale : ValueTime.DEFAULT_SCALE;
+ return s == 0 ? 8 : 9 + s;
+ }
+ case Value.TIME_TZ: {
+ int s = scale >= 0 ? scale : ValueTime.DEFAULT_SCALE;
+ return s == 0 ? 14 : 15 + s;
+ }
+ case Value.TIMESTAMP: {
+ int s = scale >= 0 ? scale : ValueTimestamp.DEFAULT_SCALE;
+ return s == 0 ? 19 : 20 + s;
+ }
+ case Value.TIMESTAMP_TZ: {
+ int s = scale >= 0 ? scale : ValueTimestamp.DEFAULT_SCALE;
+ return s == 0 ? 25 : 26 + s;
+ }
+ case Value.INTERVAL_YEAR:
+ case Value.INTERVAL_MONTH:
+ case Value.INTERVAL_DAY:
+ case Value.INTERVAL_HOUR:
+ case Value.INTERVAL_MINUTE:
+ case Value.INTERVAL_SECOND:
+ case Value.INTERVAL_YEAR_TO_MONTH:
+ case Value.INTERVAL_DAY_TO_HOUR:
+ case Value.INTERVAL_DAY_TO_MINUTE:
+ case Value.INTERVAL_DAY_TO_SECOND:
+ case Value.INTERVAL_HOUR_TO_MINUTE:
+ case Value.INTERVAL_HOUR_TO_SECOND:
+ case Value.INTERVAL_MINUTE_TO_SECOND:
+ return precision >= 0L ? precision : ValueInterval.DEFAULT_PRECISION;
+ case Value.ROW:
+ return Integer.MAX_VALUE;
+ case Value.UUID:
+ return ValueUuid.PRECISION;
+ case Value.ARRAY:
+ return precision >= 0L ? precision : Constants.MAX_ARRAY_CARDINALITY;
+ default:
+ return precision;
+ }
+ }
+
+ /**
+ * Returns the precision, or {@code -1L} if not specified in data type
+ * definition.
+ *
+ * @return the precision, or {@code -1L} if not specified in data type
+ * definition
+ */
+ public long getDeclaredPrecision() {
+ return precision;
+ }
+
+ /**
+ * Returns the scale.
+ *
+ * @return the scale
+ */
+ public int getScale() {
+ switch (valueType) {
+ case Value.UNKNOWN:
+ return -1;
+ case Value.NULL:
+ case Value.CHAR:
+ case Value.VARCHAR:
+ case Value.CLOB:
+ case Value.VARCHAR_IGNORECASE:
+ case Value.BINARY:
+ case Value.VARBINARY:
+ case Value.BLOB:
+ case Value.BOOLEAN:
+ case Value.TINYINT:
+ case Value.SMALLINT:
+ case Value.INTEGER:
+ case Value.BIGINT:
+ case Value.REAL:
+ case Value.DOUBLE:
+ case Value.DECFLOAT:
+ case Value.DATE:
+ case Value.INTERVAL_YEAR:
+ case Value.INTERVAL_MONTH:
+ case Value.INTERVAL_DAY:
+ case Value.INTERVAL_HOUR:
+ case Value.INTERVAL_MINUTE:
+ case Value.INTERVAL_YEAR_TO_MONTH:
+ case Value.INTERVAL_DAY_TO_HOUR:
+ case Value.INTERVAL_DAY_TO_MINUTE:
+ case Value.INTERVAL_HOUR_TO_MINUTE:
+ case Value.JAVA_OBJECT:
+ case Value.ENUM:
+ case Value.GEOMETRY:
+ case Value.JSON:
+ case Value.UUID:
+ case Value.ARRAY:
+ case Value.ROW:
+ return 0;
+ case Value.NUMERIC:
+ return scale >= 0 ? scale : 0;
+ case Value.TIME:
+ case Value.TIME_TZ:
+ return scale >= 0 ? scale : ValueTime.DEFAULT_SCALE;
+ case Value.TIMESTAMP:
+ case Value.TIMESTAMP_TZ:
+ return scale >= 0 ? scale : ValueTimestamp.DEFAULT_SCALE;
+ case Value.INTERVAL_SECOND:
+ case Value.INTERVAL_DAY_TO_SECOND:
+ case Value.INTERVAL_HOUR_TO_SECOND:
+ case Value.INTERVAL_MINUTE_TO_SECOND:
+ return scale >= 0 ? scale : ValueInterval.DEFAULT_SCALE;
+ default:
+ return scale;
+ }
+ }
+
+ /**
+ * Returns the scale, or {@code -1} if not specified in data type
+ * definition.
+ *
+ * @return the scale, or {@code -1} if not specified in data type definition
+ */
+ public int getDeclaredScale() {
+ return scale;
+ }
+
+ /**
+ * Returns the display size in characters.
+ *
+ * @return the display size
+ */
+ public int getDisplaySize() {
+ switch (valueType) {
+ case Value.UNKNOWN:
+ default:
+ return -1;
+ case Value.NULL:
+ return ValueNull.DISPLAY_SIZE;
+ case Value.CHAR:
+ return precision >= 0 ? (int) precision : 1;
+ case Value.VARCHAR:
+ case Value.VARCHAR_IGNORECASE:
+ case Value.JSON:
+ return precision >= 0 ? (int) precision : Constants.MAX_STRING_LENGTH;
+ case Value.CLOB:
+ return precision >= 0 && precision <= Integer.MAX_VALUE ? (int) precision : Integer.MAX_VALUE;
+ case Value.BINARY:
+ return precision >= 0 ? (int) precision * 2 : 2;
+ case Value.VARBINARY:
+ case Value.JAVA_OBJECT:
+ return precision >= 0 ? (int) precision * 2 : Constants.MAX_STRING_LENGTH * 2;
+ case Value.BLOB:
+ return precision >= 0 && precision <= Integer.MAX_VALUE / 2 ? (int) precision * 2 : Integer.MAX_VALUE;
+ case Value.BOOLEAN:
+ return ValueBoolean.DISPLAY_SIZE;
+ case Value.TINYINT:
+ return ValueTinyint.DISPLAY_SIZE;
+ case Value.SMALLINT:
+ return ValueSmallint.DISPLAY_SIZE;
+ case Value.INTEGER:
+ return ValueInteger.DISPLAY_SIZE;
+ case Value.BIGINT:
+ return ValueBigint.DISPLAY_SIZE;
+ case Value.NUMERIC:
+ return precision >= 0 ? (int) precision + 2 : Constants.MAX_NUMERIC_PRECISION + 2;
+ case Value.REAL:
+ return ValueReal.DISPLAY_SIZE;
+ case Value.DOUBLE:
+ return ValueDouble.DISPLAY_SIZE;
+ case Value.DECFLOAT:
+ return precision >= 0 ? (int) precision + 12 : Constants.MAX_NUMERIC_PRECISION + 12;
+ case Value.DATE:
+ return ValueDate.PRECISION;
+ case Value.TIME: {
+ int s = scale >= 0 ? scale : ValueTime.DEFAULT_SCALE;
+ return s == 0 ? 8 : 9 + s;
+ }
+ case Value.TIME_TZ: {
+ int s = scale >= 0 ? scale : ValueTime.DEFAULT_SCALE;
+ return s == 0 ? 14 : 15 + s;
+ }
+ case Value.TIMESTAMP: {
+ int s = scale >= 0 ? scale : ValueTimestamp.DEFAULT_SCALE;
+ return s == 0 ? 19 : 20 + s;
+ }
+ case Value.TIMESTAMP_TZ: {
+ int s = scale >= 0 ? scale : ValueTimestamp.DEFAULT_SCALE;
+ return s == 0 ? 25 : 26 + s;
+ }
+ case Value.INTERVAL_YEAR:
+ case Value.INTERVAL_MONTH:
+ case Value.INTERVAL_DAY:
+ case Value.INTERVAL_HOUR:
+ case Value.INTERVAL_MINUTE:
+ case Value.INTERVAL_SECOND:
+ case Value.INTERVAL_YEAR_TO_MONTH:
+ case Value.INTERVAL_DAY_TO_HOUR:
+ case Value.INTERVAL_DAY_TO_MINUTE:
+ case Value.INTERVAL_DAY_TO_SECOND:
+ case Value.INTERVAL_HOUR_TO_MINUTE:
+ case Value.INTERVAL_HOUR_TO_SECOND:
+ case Value.INTERVAL_MINUTE_TO_SECOND:
+ return ValueInterval.getDisplaySize(valueType,
+ precision >= 0 ? (int) precision : ValueInterval.DEFAULT_PRECISION,
+ scale >= 0 ? scale : ValueInterval.DEFAULT_SCALE);
+ case Value.GEOMETRY:
+ case Value.ARRAY:
+ case Value.ROW:
+ return Integer.MAX_VALUE;
+ case Value.ENUM:
+ return extTypeInfo != null ? (int) precision : Constants.MAX_STRING_LENGTH;
+ case Value.UUID:
+ return ValueUuid.DISPLAY_SIZE;
+ }
+ }
+
+ /**
+ * Returns the extended type information, or null.
+ *
+ * @return the extended type information, or null
+ */
+ public ExtTypeInfo getExtTypeInfo() {
+ return extTypeInfo;
+ }
+
+ @Override
+ public StringBuilder getSQL(StringBuilder builder, int sqlFlags) {
+ switch (valueType) {
+ case Value.CHAR:
+ case Value.VARCHAR:
+ case Value.CLOB:
+ case Value.VARCHAR_IGNORECASE:
+ case Value.BINARY:
+ case Value.VARBINARY:
+ case Value.BLOB:
+ case Value.JAVA_OBJECT:
+ case Value.JSON:
+ builder.append(Value.getTypeName(valueType));
+ if (precision >= 0L) {
+ builder.append('(').append(precision).append(')');
+ }
+ break;
+ case Value.NUMERIC: {
+ if (extTypeInfo != null) {
+ extTypeInfo.getSQL(builder, sqlFlags);
+ } else {
+ builder.append("NUMERIC");
+ }
+ boolean withPrecision = precision >= 0;
+ boolean withScale = scale >= 0;
+ if (withPrecision || withScale) {
+ builder.append('(').append(withPrecision ? precision : Constants.MAX_NUMERIC_PRECISION);
+ if (withScale) {
+ builder.append(", ").append(scale);
+ }
+ builder.append(')');
+ }
+ break;
+ }
+ case Value.REAL:
+ case Value.DOUBLE:
+ if (precision < 0) {
+ builder.append(Value.getTypeName(valueType));
+ } else {
+ builder.append("FLOAT");
+ if (precision > 0) {
+ builder.append('(').append(precision).append(')');
+ }
+ }
+ break;
+ case Value.DECFLOAT:
+ builder.append("DECFLOAT");
+ if (precision >= 0) {
+ builder.append('(').append(precision).append(')');
+ }
+ break;
+ case Value.TIME:
+ case Value.TIME_TZ:
+ builder.append("TIME");
+ if (scale >= 0) {
+ builder.append('(').append(scale).append(')');
+ }
+ if (valueType == Value.TIME_TZ) {
+ builder.append(" WITH TIME ZONE");
+ }
+ break;
+ case Value.TIMESTAMP:
+ case Value.TIMESTAMP_TZ:
+ builder.append("TIMESTAMP");
+ if (scale >= 0) {
+ builder.append('(').append(scale).append(')');
+ }
+ if (valueType == Value.TIMESTAMP_TZ) {
+ builder.append(" WITH TIME ZONE");
+ }
+ break;
+ case Value.INTERVAL_YEAR:
+ case Value.INTERVAL_MONTH:
+ case Value.INTERVAL_DAY:
+ case Value.INTERVAL_HOUR:
+ case Value.INTERVAL_MINUTE:
+ case Value.INTERVAL_SECOND:
+ case Value.INTERVAL_YEAR_TO_MONTH:
+ case Value.INTERVAL_DAY_TO_HOUR:
+ case Value.INTERVAL_DAY_TO_MINUTE:
+ case Value.INTERVAL_DAY_TO_SECOND:
+ case Value.INTERVAL_HOUR_TO_MINUTE:
+ case Value.INTERVAL_HOUR_TO_SECOND:
+ case Value.INTERVAL_MINUTE_TO_SECOND:
+ IntervalQualifier.valueOf(valueType - Value.INTERVAL_YEAR).getTypeName(builder, (int) precision, scale,
+ false);
+ break;
+ case Value.ENUM:
+ extTypeInfo.getSQL(builder.append("ENUM"), sqlFlags);
+ break;
+ case Value.GEOMETRY:
+ builder.append("GEOMETRY");
+ if (extTypeInfo != null) {
+ extTypeInfo.getSQL(builder, sqlFlags);
+ }
+ break;
+ case Value.ARRAY:
+ if (extTypeInfo != null) {
+ extTypeInfo.getSQL(builder, sqlFlags).append(' ');
+ }
+ builder.append("ARRAY");
+ if (precision >= 0L) {
+ builder.append('[').append(precision).append(']');
+ }
+ break;
+ case Value.ROW:
+ builder.append("ROW");
+ if (extTypeInfo != null) {
+ extTypeInfo.getSQL(builder, sqlFlags);
+ }
+ break;
+ default:
+ builder.append(Value.getTypeName(valueType));
+ }
+ return builder;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = 31 * result + valueType;
+ result = 31 * result + (int) (precision ^ (precision >>> 32));
+ result = 31 * result + scale;
+ result = 31 * result + ((extTypeInfo == null) ? 0 : extTypeInfo.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || obj.getClass() != TypeInfo.class) {
+ return false;
+ }
+ TypeInfo other = (TypeInfo) obj;
+ return valueType == other.valueType && precision == other.precision && scale == other.scale
+ && Objects.equals(extTypeInfo, other.extTypeInfo);
+ }
+
+ /**
+ * Convert this type information to compatible NUMERIC type information.
+ *
+ * @return NUMERIC type information
+ */
+ public TypeInfo toNumericType() {
+ switch (valueType) {
+ case Value.BOOLEAN:
+ case Value.TINYINT:
+ case Value.SMALLINT:
+ case Value.INTEGER:
+ return getTypeInfo(Value.NUMERIC, getDecimalPrecision(), 0, null);
+ case Value.BIGINT:
+ return TYPE_NUMERIC_BIGINT;
+ case Value.NUMERIC:
+ return this;
+ case Value.REAL:
+ // Smallest REAL value is 1.4E-45 with precision 2 and scale 46
+ // Largest REAL value is 3.4028235E+38 with precision 8 and scale
+ // -31
+ return getTypeInfo(Value.NUMERIC, 85, 46, null);
+ case Value.DOUBLE:
+ // Smallest DOUBLE value is 4.9E-324 with precision 2 and scale 325
+ // Largest DOUBLE value is 1.7976931348623157E+308 with precision 17
+ // and scale -292
+ return getTypeInfo(Value.NUMERIC, 634, 325, null);
+ default:
+ return TYPE_NUMERIC_FLOATING_POINT;
+ }
+ }
+
+ /**
+ * Convert this type information to compatible DECFLOAT type information.
+ *
+ * @return DECFLOAT type information
+ */
+ public TypeInfo toDecfloatType() {
+ switch (valueType) {
+ case Value.BOOLEAN:
+ case Value.TINYINT:
+ case Value.SMALLINT:
+ case Value.INTEGER:
+ return getTypeInfo(Value.DECFLOAT, getDecimalPrecision(), 0, null);
+ case Value.BIGINT:
+ return TYPE_DECFLOAT_BIGINT;
+ case Value.NUMERIC:
+ return getTypeInfo(Value.DECFLOAT, getPrecision(), 0, null);
+ case Value.REAL:
+ return getTypeInfo(Value.DECFLOAT, ValueReal.DECIMAL_PRECISION, 0, null);
+ case Value.DOUBLE:
+ return getTypeInfo(Value.DECFLOAT, ValueReal.DECIMAL_PRECISION, 0, null);
+ case Value.DECFLOAT:
+ return this;
+ default:
+ return TYPE_DECFLOAT;
+ }
+ }
+
+ /**
+ * Returns unwrapped data type if this data type is a row type with degree 1
+ * or this type otherwise.
+ *
+ * @return unwrapped data type if this data type is a row type with degree 1
+ * or this type otherwise
+ */
+ public TypeInfo unwrapRow() {
+ if (valueType == Value.ROW) {
+ Set> fields = ((ExtTypeInfoRow) extTypeInfo).getFields();
+ if (fields.size() == 1) {
+ return fields.iterator().next().getValue().unwrapRow();
+ }
+ }
+ return this;
+ }
+
+ /**
+ * Returns approximate precision in decimal digits for binary numeric data
+ * types and precision for all other types.
+ *
+ * @return precision in decimal digits
+ */
+ public long getDecimalPrecision() {
+ switch (valueType) {
+ case Value.TINYINT:
+ return ValueTinyint.DECIMAL_PRECISION;
+ case Value.SMALLINT:
+ return ValueSmallint.DECIMAL_PRECISION;
+ case Value.INTEGER:
+ return ValueInteger.DECIMAL_PRECISION;
+ case Value.BIGINT:
+ return ValueBigint.DECIMAL_PRECISION;
+ case Value.REAL:
+ return ValueReal.DECIMAL_PRECISION;
+ case Value.DOUBLE:
+ return ValueDouble.DECIMAL_PRECISION;
+ default:
+ return precision;
+ }
+ }
+
+ /**
+ * Returns the declared name of this data type with precision, scale,
+ * length, cardinality etc. parameters removed, excluding parameters of ENUM
+ * data type, GEOMETRY data type, ARRAY elements, and ROW fields.
+ *
+ * @return the declared name
+ */
+ public String getDeclaredTypeName() {
+ switch (valueType) {
+ case Value.NUMERIC:
+ return extTypeInfo != null ? "DECIMAL" : "NUMERIC";
+ case Value.REAL:
+ case Value.DOUBLE:
+ if (extTypeInfo != null) {
+ return "FLOAT";
+ }
+ break;
+ case Value.ENUM:
+ case Value.GEOMETRY:
+ case Value.ROW:
+ return getSQL(DEFAULT_SQL_FLAGS);
+ case Value.ARRAY:
+ TypeInfo typeInfo = (TypeInfo) extTypeInfo;
+ // Use full type names with parameters for elements
+ return typeInfo.getSQL(new StringBuilder(), DEFAULT_SQL_FLAGS).append(" ARRAY").toString();
+ }
+ return Value.getTypeName(valueType);
+ }
+
+}
diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestBooleanComparison.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestBooleanComparison.java
new file mode 100644
index 00000000000..c3690385532
--- /dev/null
+++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestBooleanComparison.java
@@ -0,0 +1,46 @@
+package org.h2.legendTests;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import java.sql.*;
+
+ public class TestBooleanComparison extends TestH2Abstract
+{
+ @Test
+ public void testBooleanToVarcharComparison() throws SQLException
+ {
+ String query = "Select CASE\n" +
+ " WHEN false = 'false' THEN 'Ok'\n" +
+ " ELSE 'Error'\n" +
+ "END AS BooleanVarcharComparison";
+ ResultSet rs = h2ConnStatement.executeQuery(query);
+ rs.next();
+ Assert.assertEquals("Ok", rs.getString("BooleanVarcharComparison"));
+ }
+
+ @Test
+ public void testBooleanToIntegerComparison() throws SQLException
+ {
+ String query = "Select CASE\n" +
+ " WHEN false = 0 THEN 'Ok'\n" +
+ " ELSE 'Error'\n" +
+ "END AS BooleanIntegerComparison";
+ ResultSet rs = h2ConnStatement.executeQuery(query);
+ rs.next();
+ Assert.assertEquals("Ok", rs.getString("BooleanIntegerComparison"));
+ }
+
+ @Test
+ public void testBooleanToFloatComparison() throws SQLException
+ {
+ String query = "Select CASE\n" +
+ " WHEN false = 0.0 THEN 'Ok'\n" +
+ " ELSE 'Error'\n" +
+ "END AS BooleanFloatComparison";
+ ResultSet rs = h2ConnStatement.executeQuery(query);
+ rs.next();
+ Assert.assertEquals("Ok", rs.getString("BooleanFloatComparison"));
+ }
+}
\ No newline at end of file
diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestH2Abstract.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestH2Abstract.java
new file mode 100644
index 00000000000..da7434942ef
--- /dev/null
+++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestH2Abstract.java
@@ -0,0 +1,34 @@
+package org.h2.legendTests;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.Statement;
+
+public class TestH2Abstract
+{
+ static Connection h2Conn;
+ static Statement h2ConnStatement;
+
+ @BeforeClass
+ public static void setupClass() throws Exception
+ {
+ Class.forName("org.h2.Driver"); // Driver name
+ String defaultH2Properties = ";NON_KEYWORDS=ANY,ASYMMETRIC,AUTHORIZATION,CAST,CURRENT_PATH,CURRENT_ROLE,DAY,DEFAULT,ELSE,END,HOUR,KEY,MINUTE,MONTH,SECOND,SESSION_USER,SET,SOME,SYMMETRIC,SYSTEM_USER,TO,UESCAPE,USER,VALUE,WHEN,YEAR;MODE=LEGACY";
+ String url = "jdbc:h2:~/test"+ defaultH2Properties;
+ h2Conn = DriverManager.getConnection(url);
+ System.out.println("H2 Connection Acquired....");
+ h2ConnStatement = h2Conn.createStatement();
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception
+ {
+ h2ConnStatement.close();
+ h2Conn.close();
+ System.out.println("H2 Connection Closed....");
+ }
+
+}
diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestNoCharPadding.java b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestNoCharPadding.java
new file mode 100644
index 00000000000..c69d16fcd41
--- /dev/null
+++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/legend-engine-xt-relationalStore-h2-execution-2.1.214/src/test/java/org/h2/legendTests/TestNoCharPadding.java
@@ -0,0 +1,20 @@
+package org.h2.legendTests;
+
+import org.junit.Assert;
+import org.junit.Test;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class TestNoCharPadding extends TestH2Abstract
+{
+ @Test
+ public void testBooleanToVarcharComparison() throws SQLException
+ {
+ h2ConnStatement.execute("create table myTable (charCol char(10));");
+ h2ConnStatement.execute("insert into myTable (charCol) values ('val');");
+
+ ResultSet rs = h2ConnStatement.executeQuery("select charCol from myTable");
+ rs.next();
+ Assert.assertEquals("val", rs.getString(1)); // instead 'val ' ( padded 10 length)
+ }
+}
diff --git a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/pom.xml b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/pom.xml
index f46684eead6..a761fa59ad7 100644
--- a/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/pom.xml
+++ b/legend-engine-xts-relationalStore/legend-engine-xt-relationalStore-dbExtension/legend-engine-xt-relationalStore-h2/pom.xml
@@ -28,5 +28,6 @@
legend-engine-xt-relationalStore-h2-PCT
+ legend-engine-xt-relationalStore-h2-execution-2.1.214
\ No newline at end of file