Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions modules/calcite/src/main/codegen/config.fmpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ data: {
"DATA_REGION"
# "KEY_TYPE" // already presented in Calcite
"VALUE_TYPE"
"WRAP_KEY"
"WRAP_VALUE"
"ENCRYPTED"
"INDEX"
"PARALLEL"
Expand Down Expand Up @@ -88,6 +90,8 @@ data: {
"DATA_REGION"
# "KEY_TYPE" // already presented in Calcite
"VALUE_TYPE"
"WRAP_KEY"
"WRAP_VALUE"
"ENCRYPTED"
"PARALLEL"
"INLINE_SIZE"
Expand Down
4 changes: 4 additions & 0 deletions modules/calcite/src/main/codegen/includes/parserImpls.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ SqlLiteral CreateTableOptionKey() :
<VALUE_TYPE> { return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.VALUE_TYPE, getPos()); }
|
<ENCRYPTED> { return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.ENCRYPTED, getPos()); }
|
<WRAP_KEY> { return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.WRAP_KEY, getPos()); }
|
<WRAP_VALUE> { return SqlLiteral.createSymbol(IgniteSqlCreateTableOptionEnum.WRAP_VALUE, getPos()); }
}

void CreateTableOption(List<SqlNode> list) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@

import static org.apache.ignite.internal.processors.query.QueryUtils.convert;
import static org.apache.ignite.internal.processors.query.QueryUtils.isDdlOnSchemaSupported;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.KEY_TYPE;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.VALUE_TYPE;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.WRAP_KEY;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.WRAP_VALUE;

/** */
public class DdlCommandHandler {
Expand Down Expand Up @@ -136,6 +140,8 @@
throw new SchemaOperationException(SchemaOperationException.CODE_TABLE_EXISTS, cmd.tableName());
}

checkKVWrappedParam(cmd);

CacheConfiguration<?, ?> ccfg = new CacheConfiguration<>(cmd.tableName());

QueryEntity e = toQueryEntity(cmd);
Expand Down Expand Up @@ -177,6 +183,42 @@
}
}

/** */
private void checkKVWrappedParam(CreateTableCommand cmd) {

Check failure on line 187 in modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ddl/DdlCommandHandler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this method to reduce its Cognitive Complexity from 18 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=apache_ignite&issues=AZ2wqN_EvFOPm-nvQhmh&open=AZ2wqN_EvFOPm-nvQhmh&pullRequest=13037
Boolean wrapKey = cmd.wrapKey();

if (wrapKey != null) {
if (!wrapKey) {
if (cmd.primaryKeyColumns().size() > 1) {
throw new IgniteSQLException(WRAP_KEY + " parameter cannot be \"false\" when composite primary key exists.",
IgniteQueryErrorCode.PARSING);
}

if (!F.isEmpty(cmd.keyTypeName())) {
throw new IgniteSQLException(WRAP_KEY + " parameter cannot be \"false\" when " + KEY_TYPE + " is defined.",
IgniteQueryErrorCode.PARSING);
}
}
}
else
cmd.wrapKey(!F.isEmpty(cmd.keyTypeName()) || cmd.primaryKeyColumns().size() > 1);

Boolean wrapVal = cmd.wrapValue();

if (wrapVal != null && !wrapVal) {
if (!cmd.primaryKeyColumns().isEmpty() && cmd.columns().size() - cmd.primaryKeyColumns().size() > 1) {
throw new IgniteSQLException(WRAP_VALUE + " parameter cannot be \"false\" with multiple columns.",
IgniteQueryErrorCode.PARSING);
}

if (!F.isEmpty(cmd.valueTypeName())) {
throw new IgniteSQLException(WRAP_VALUE + " parameter cannot be \"false\" when " + VALUE_TYPE + " is defined.",
IgniteQueryErrorCode.PARSING);
}
}
// By default, value is always wrapped to allow for ALTER TABLE ADD COLUMN commands.
}

/** */
private void handle0(DropTableCommand cmd) throws IgniteCheckedException {
isDdlOnSchemaSupported(cmd.schemaName());
Expand Down Expand Up @@ -214,7 +256,7 @@

if (QueryUtils.isSqlType(typeDesc.valueClass())) {
throw new SchemaOperationException("Cannot add column(s) because table was created " +
"with WRAP_VALUE=false option.");
"based on cache configured with built-in types or with " + WRAP_VALUE + "=false option.");
}
Comment thread
zstan marked this conversation as resolved.

List<QueryField> cols = new ArrayList<>(cmd.columns().size());
Expand Down Expand Up @@ -309,7 +351,7 @@

/** */
private QueryEntity toQueryEntity(CreateTableCommand cmd) {
QueryEntity res = new QueryEntity();
QueryEntityEx res = new QueryEntityEx();

res.setTableName(cmd.tableName());

Expand Down Expand Up @@ -369,21 +411,46 @@
if (!F.isEmpty(cmd.primaryKeyColumns())) {
res.setKeyFields(new LinkedHashSet<>(cmd.primaryKeyColumns()));

res = new QueryEntityEx(res).setPreserveKeysOrder(true);
res.setPreserveKeysOrder(true);
}
}
else if (!F.isEmpty(cmd.primaryKeyColumns()) && cmd.primaryKeyColumns().size() == 1) {
String pkFieldName = cmd.primaryKeyColumns().get(0);

keyTypeName = res.getFields().get(pkFieldName);
if (cmd.wrapKey()) {

Check warning on line 420 in modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/ddl/DdlCommandHandler.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Use a primitive boolean expression here.

See more on https://sonarcloud.io/project/issues?id=apache_ignite&issues=AZ2wqN_EvFOPm-nvQhmg&open=AZ2wqN_EvFOPm-nvQhmg&pullRequest=13037
res.setKeyFields(Set.copyOf(cmd.primaryKeyColumns()));

keyTypeName = QueryUtils.createTableKeyTypeName(valTypeName);

res.setPreserveKeysOrder(true);
}
else {
keyTypeName = res.getFields().get(pkFieldName);

res.setKeyFieldName(pkFieldName);
res.setKeyFieldName(pkFieldName);
}
}
else {
// if pk is not explicitly set, we create it ourselves
keyTypeName = IgniteUuid.class.getName();

res = new QueryEntityEx(res).implicitPk(true);
res.implicitPk(true);
}

if (cmd.wrapValue() != null && !cmd.wrapValue()) {
ColumnDefinition valCol = null;

for (ColumnDefinition col : cmd.columns()) {
if (!cmd.primaryKeyColumns().contains(col.name())) {
valCol = col;
break;
}
}

if (valCol != null) {
valTypeName = Commons.typeFactory().getResultClass(valCol.type()).getTypeName();
res.setValueFieldName(valCol.name());
}
}

res.setValueType(F.isEmpty(cmd.valueTypeName()) ? valTypeName : cmd.valueTypeName());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package org.apache.ignite.internal.processors.query.calcite.prepare.ddl;

import java.util.Collections;
import java.util.List;
import org.apache.calcite.sql.SqlInsert;
import org.apache.ignite.cache.CacheAtomicityMode;
Expand Down Expand Up @@ -45,6 +46,12 @@ public class CreateTableCommand implements DdlCommand {
/** Name of cache key type. */
private String keyTypeName;

/** Wrap key flag. */
private Boolean wrapKey;

/** Wrap value flag. */
private Boolean wrapValue;

/** Name of cache value type. */
private String valTypeName;

Expand All @@ -67,7 +74,7 @@ public class CreateTableCommand implements DdlCommand {
private List<ColumnDefinition> cols;

/** Primary key columns. */
private List<String> pkCols;
private List<String> pkCols = Collections.emptyList();

/** Name of the column that represents affinity key. */
private String affinityKey;
Expand Down Expand Up @@ -109,6 +116,34 @@ public void cacheName(String cacheName) {
this.cacheName = cacheName;
}

/**
* @return wrap_key flag.
*/
@Nullable public Boolean wrapKey() {
return wrapKey;
}

/**
* @param wrapKey wrap_key flag.
*/
public void wrapKey(boolean wrapKey) {
this.wrapKey = wrapKey;
}

/**
* @return wrap_value flag.
*/
@Nullable public Boolean wrapValue() {
return wrapValue;
}

/**
* @param wrapValue wrap_value flag.
*/
public void wrapValue(boolean wrapValue) {
this.wrapValue = wrapValue;
}

/**
* @return Name of cache key type.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,19 +74,49 @@
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.KEY_TYPE;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.TEMPLATE;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.VALUE_TYPE;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.WRAP_KEY;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.WRAP_VALUE;
import static org.apache.ignite.internal.processors.query.calcite.sql.IgniteSqlCreateTableOptionEnum.WRITE_SYNCHRONIZATION_MODE;
import static org.apache.ignite.internal.processors.query.calcite.util.PlanUtils.deriveObjectName;
import static org.apache.ignite.internal.processors.query.calcite.util.PlanUtils.deriveSchemaName;

/** */
public class DdlSqlToCommandConverter {
/** */
private static final String SIMPLE_PREDICATE = "a simple identifier";

/** Processor that validates a value is a Sql Identifier. */
private static final BiFunction<IgniteSqlCreateTableOption, PlanningContext, String> VALUE_IS_IDENTIFIER_VALIDATOR = (opt, ctx) -> {
private static final BiFunction<IgniteSqlCreateTableOption, PlanningContext, String> VALUE_IS_IDENTIFIER_VALIDATOR =
DdlSqlToCommandConverter::paramAsSimpleSqlIdentifier;

/** Processor that validates that value can be parsed as boolean. */
private static final BiFunction<IgniteSqlCreateTableOption, PlanningContext, Boolean> VALUE_IS_BOOL_IDENTIFIER_VALIDATOR =

Check warning on line 93 in modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/ddl/DdlSqlToCommandConverter.java

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this code to use the more specialised Functional Interface 'BiPredicate<IgniteSqlCreateTableOption, PlanningContext>'

See more on https://sonarcloud.io/project/issues?id=apache_ignite&issues=AZ2VKVlPb4f8_FaZV4Dm&open=AZ2VKVlPb4f8_FaZV4Dm&pullRequest=13037
(opt, ctx) -> {
SqlNode val = opt.value();
if (val instanceof SqlLiteral)
return ((SqlLiteral)val).booleanValue();

String simple = paramAsSimpleSqlIdentifier(opt, ctx);

if (!"true".equalsIgnoreCase(simple) && !"false".equalsIgnoreCase(simple))
throwOptionParsingException(opt, "Unexpected identifier: " + simple, ctx.query());

return Boolean.valueOf(((SqlIdentifier)val).getSimple());
};

/**
* Shortcut for validating that option value is a simple identifier.
*
* @param opt An option to validate.
* @param ctx Planning context.
* @throws IgniteSQLException In case the param is not a simple identifier.
*/
private static String paramAsSimpleSqlIdentifier(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());

return ((SqlIdentifier)opt.value()).getSimple();
};
}

/** Processor that unconditionally throws an AssertionException. */
private static final TableOptionProcessor<Void> UNSUPPORTED_OPTION_PROCESSOR = new TableOptionProcessor<>(
Expand All @@ -105,6 +135,8 @@
new TableOptionProcessor<>(DATA_REGION, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::dataRegionName),
new TableOptionProcessor<>(KEY_TYPE, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::keyTypeName),
new TableOptionProcessor<>(VALUE_TYPE, VALUE_IS_IDENTIFIER_VALIDATOR, CreateTableCommand::valueTypeName),
new TableOptionProcessor<>(WRAP_KEY, VALUE_IS_BOOL_IDENTIFIER_VALIDATOR, CreateTableCommand::wrapKey),
new TableOptionProcessor<>(WRAP_VALUE, VALUE_IS_BOOL_IDENTIFIER_VALIDATOR, CreateTableCommand::wrapValue),
new TableOptionProcessor<>(ATOMICITY, validatorForEnumValue(CacheAtomicityMode.class), CreateTableCommand::atomicityMode),
new TableOptionProcessor<>(WRITE_SYNCHRONIZATION_MODE, validatorForEnumValue(CacheWriteSynchronizationMode.class),
CreateTableCommand::writeSynchronizationMode),
Expand Down Expand Up @@ -441,20 +473,6 @@
return alterTblCmd;
}

/**
* Short cut for validating that option value is a simple identifier.
*
* @param opt An option to validate.
* @param ctx Planning context.
* @throws IgniteSQLException In case the validation was failed.
*/
private String paramIsSqlIdentifierValidator(IgniteSqlCreateTableOption opt, PlanningContext ctx) {
if (!(opt.value() instanceof SqlIdentifier) || !((SqlIdentifier)opt.value()).isSimple())
throwOptionParsingException(opt, "a simple identifier", ctx.query());

return ((SqlIdentifier)opt.value()).getSimple();
}

/**
* Creates a validator for an option which value should be value of given enumeration.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,10 @@ public enum IgniteSqlCreateTableOptionEnum {

/** This flag specified whether the encryption should be enabled for the underlying cache. */
ENCRYPTED,

/** Flag controls whether a single column PRIMARY KEY should be wrapped in the BinaryObjects format. */
WRAP_KEY,

/** Flag controls whether a single column value of a primitive type should be wrapped in the BinaryObjects format. */
WRAP_VALUE,
}
Loading
Loading