IGNITE-28556 Calcite. Support wrap_key and wrap_value flags#13037
IGNITE-28556 Calcite. Support wrap_key and wrap_value flags#13037zstan wants to merge 3 commits intoapache:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds Calcite-side support for wrap_key / wrap_value CREATE TABLE options (parsing, command propagation, and validation), plus tests to verify wrapping behavior and related DDL constraints.
Changes:
- Extend Calcite CREATE TABLE option set with
WRAP_KEYandWRAP_VALUEand parse them intoCreateTableCommand. - Add DDL-time validation for invalid wrap combinations and implement
wrap_value=falsemapping to a “flat” value field. - Add/adjust JDBC and integration tests covering wrapping combinations and error scenarios.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/H2DynamicTableSelfTest.java | Minor test Callable signature adjustment. |
| modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/index/DynamicColumnsAbstractTest.java | Minor test Callable signature adjustment. |
| modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlCreateTable.java | Javadoc punctuation fix. |
| modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/jdbc/JdbcQueryTest.java | Adds JDBC tests for wrapped/unwrapped key/value behavior (incl. UUID). |
| modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/TableDdlIntegrationTest.java | Adds integration tests for wrap options and constraints; re-enables an ALTER TABLE test. |
| modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/sql/IgniteSqlCreateTableOptionEnum.java | Adds WRAP_KEY / WRAP_VALUE option enums. |
| modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java | Adds parsing/validation for wrap options. |
| modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/CreateTableCommand.java | Adds wrap flags to the DDL command model (defaults: key=false, value=true). |
| modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ddl/DdlCommandHandler.java | Validates wrap flags and applies wrap_value=false mapping; updates ALTER TABLE ADD error message. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
f375220 to
abd690c
Compare
|
| throwOptionParsingException(opt, SIMPLE_PREDICATE, ctx.query()); | ||
|
|
||
| String simple = ((SqlIdentifier)val).getSimple().toLowerCase(Locale.ROOT); | ||
| if (!"true".equals(simple) && !"false".equals(simple)) |
| private String paramIsSqlIdentifierValidator(IgniteSqlCreateTableOption opt, PlanningContext ctx) { | ||
| if (!(opt.value() instanceof SqlIdentifier) || !((SqlIdentifier)opt.value()).isSimple()) | ||
| throwOptionParsingException(opt, "a simple identifier", ctx.query()); | ||
| throwOptionParsingException(opt, SIMPLE_PREDICATE, ctx.query()); |
There was a problem hiding this comment.
This method is not used, but can be used to simplify VALUE_IS_IDENTIFIER_VALIDATOR and VALUE_IS_BOOL_IDENTIFIER_VALIDATOR
| private Boolean wrapKey; | ||
|
|
||
| /** Wrap value flag. */ | ||
| private boolean wrapValue = true; |
There was a problem hiding this comment.
Maybe we should use Boolean here and move default logic to command handler? This class is a representation of parsed command, if WRAP_VALUE is not provided it's more correct to see null here.
Let's also add the same comment as for H2 somewhere:
By default value is always wrapped to allow for ALTER TABLE ADD COLUMN commands.
|
|
||
| /** */ | ||
| @SuppressWarnings("ThrowableNotThrown") | ||
| private static void assertThrowsSqlException(Callable<?> call, @Nullable String msg) { |
There was a problem hiding this comment.
We have assertThrows(sql, cls, msg) in parent class, why do we need yet another method?
| */ | ||
| @Test | ||
| public void testAlterTableFailOnSingleCacheValue() { | ||
| CacheConfiguration c = |
| res = new QueryEntityEx(res).implicitPk(true); | ||
| } | ||
|
|
||
| if (!cmd.wrapValue()) { |
There was a problem hiding this comment.
wrapKey is not handled. Only validated.
| public void testInlineSizeNoWrap() { | ||
| try { | ||
| sql("CREATE TABLE IF NOT EXISTS T ( " + | ||
| " id varchar(15), " + | ||
| " col varchar(100), " + | ||
| " PRIMARY KEY(id) ) "); | ||
| assertEquals(18, sql( | ||
| "select INLINE_SIZE from SYS.INDEXES where TABLE_NAME = 'T' and IS_PK = true").get(0).get(0)); | ||
| } | ||
| finally { | ||
| sql("DROP TABLE IF EXISTS T"); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Test single column PK with wrapping calculate correct inline size. | ||
| */ | ||
| @Test | ||
| public void testInlineSizeWrap() { | ||
| try { | ||
| sql("CREATE TABLE IF NOT EXISTS T ( " + | ||
| " id varchar(15), " + | ||
| " col varchar(100), " + | ||
| " PRIMARY KEY(id) ) WITH \"wrap_key=true\""); | ||
| assertEquals(18, sql( | ||
| "select INLINE_SIZE from SYS.INDEXES where TABLE_NAME = 'T' and IS_PK = true").get(0).get(0)); | ||
| } | ||
| finally { | ||
| sql("DROP TABLE IF EXISTS T"); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Test two column PK with wrapping calculate correct inline size. | ||
| */ | ||
| @Test | ||
| public void testInlineSizeWrapMultiPk() { | ||
| try { | ||
| sql("CREATE TABLE IF NOT EXISTS T ( " + | ||
| " id varchar(15), " + | ||
| " id2 uuid, " + | ||
| " col varchar(100), " + | ||
| " PRIMARY KEY(id, id2) ) WITH \"wrap_key=true\""); | ||
| assertEquals(35, sql( | ||
| "select INLINE_SIZE from SYS.INDEXES where TABLE_NAME = 'T' and IS_PK = true").get(0).get(0)); | ||
| } | ||
| finally { | ||
| sql("DROP TABLE IF EXISTS T"); | ||
| } | ||
| } |
There was a problem hiding this comment.
It's not a correct tests for wrapping. PK index is always unwrapped if table was created via DDL. You can change wrap_key to false in all these test and get the same result. To test wrap_key correctly you can iterate over cache values and check key, if it primitive type or binary object.
| * @param wrapVal Whether value wrap should be enforced. | ||
| * @throws SQLException if failed. | ||
| */ | ||
| private void doTestKeyValueWrap(boolean wrapKey, boolean wrapVal, boolean testUuid) throws SQLException { |
There was a problem hiding this comment.
Looks like it's not related to JDBC somehow, just ordinal integration test.
|
|
||
| UUID guid = UUID.randomUUID(); | ||
|
|
||
| if (wrapKey) |
There was a problem hiding this comment.
Case with wrap_key=true and without key_type is not covered (and has errors, since wrap_key=true never handled)



No description provided.