Skip to content

Commit

Permalink
IGNITE-5623: SQL: default column values support for CREATE TABLE. This
Browse files Browse the repository at this point in the history
…closes apache#3256.
  • Loading branch information
tledkov-gridgain authored and devozerov committed Jan 5, 2018
1 parent 2f2fa8b commit 78e79e0
Show file tree
Hide file tree
Showing 37 changed files with 721 additions and 44 deletions.
Expand Up @@ -138,7 +138,8 @@ protected CacheConfiguration cacheConfiguration(QueryEntity qryEntity) {
try (Connection conn = DriverManager.getConnection(URL)) {
Statement stmt = conn.createStatement();

stmt.execute("CREATE TABLE TEST (ID INT, NAME VARCHAR(50), VAL VARCHAR(50), PRIMARY KEY (ID, NAME))");
stmt.execute("CREATE TABLE TEST (ID INT, NAME VARCHAR(50) default 'default name', " +
"age int default 21, VAL VARCHAR(50), PRIMARY KEY (ID, NAME))");
stmt.execute("CREATE TABLE \"Quoted\" (\"Id\" INT primary key, \"Name\" VARCHAR(50)) WITH WRAP_KEY");
stmt.execute("CREATE INDEX \"MyTestIndex quoted\" on \"Quoted\" (\"Id\" DESC)");
stmt.execute("CREATE INDEX IDX ON TEST (ID ASC)");
Expand Down Expand Up @@ -371,23 +372,25 @@ public void testGetAllColumns() throws Exception {
ResultSet rs = meta.getColumns(null, null, null, null);

Set<String> expectedCols = new HashSet<>(Arrays.asList(
"org.ORGANIZATION.ID",
"org.ORGANIZATION.NAME",
"pers.PERSON.ORGID",
"pers.PERSON.AGE",
"pers.PERSON.NAME",
"PUBLIC.TEST.ID",
"PUBLIC.TEST.NAME",
"PUBLIC.TEST.VAL",
"PUBLIC.Quoted.Id",
"PUBLIC.Quoted.Name"));
"org.ORGANIZATION.ID.null",
"org.ORGANIZATION.NAME.null",
"pers.PERSON.ORGID.null",
"pers.PERSON.AGE.null",
"pers.PERSON.NAME.null",
"PUBLIC.TEST.ID.null",
"PUBLIC.TEST.NAME.'default name'",
"PUBLIC.TEST.VAL.null",
"PUBLIC.TEST.AGE.21",
"PUBLIC.Quoted.Id.null",
"PUBLIC.Quoted.Name.null"));

Set<String> actualCols = new HashSet<>(expectedCols.size());

while(rs.next()) {
actualCols.add(rs.getString("TABLE_SCHEM") + '.'
+ rs.getString("TABLE_NAME") + "."
+ rs.getString("COLUMN_NAME"));
+ rs.getString("COLUMN_NAME") + "."
+ rs.getString("COLUMN_DEF"));
}

assert expectedCols.equals(actualCols) : "expectedCols=" + expectedCols +
Expand Down
Expand Up @@ -86,6 +86,9 @@ public class QueryEntity implements Serializable {
/** Fields that must have non-null value. NB: DO NOT remove underscore to avoid clashes with QueryEntityEx. */
private Set<String> _notNullFields;

/** Fields default values. */
private Map<String, Object> defaultFieldValues = new HashMap<>();

/**
* Creates an empty query entity.
*/
Expand Down Expand Up @@ -114,6 +117,9 @@ public QueryEntity(QueryEntity other) {
tableName = other.tableName;

_notNullFields = other._notNullFields != null ? new HashSet<>(other._notNullFields) : null;

defaultFieldValues = other.defaultFieldValues != null ? new HashMap<>(other.defaultFieldValues)
: new HashMap<String, Object>();
}

/**
Expand Down Expand Up @@ -355,9 +361,12 @@ public String getTableName() {
* Sets table name for this query entity.
*
* @param tableName table name
* @return {@code this} for chaining.
*/
public void setTableName(String tableName) {
public QueryEntity setTableName(String tableName) {
this.tableName = tableName;

return this;
}

/**
Expand All @@ -381,6 +390,27 @@ public QueryEntity setNotNullFields(@Nullable Set<String> notNullFields) {
return this;
}

/**
* Gets fields default values.
*
* @return Field's name to default value map.
*/
public Map<String, Object> getDefaultFieldValues() {
return defaultFieldValues;
}

/**
* Sets fields default values.
*
* @param defaultFieldValues Field's name to default value map.
* @return {@code this} for chaining.
*/
public QueryEntity setDefaultFieldValues(Map<String, Object> defaultFieldValues) {
this.defaultFieldValues = defaultFieldValues;

return this;
}

/**
* Utility method for building query entities programmatically.
*
Expand Down Expand Up @@ -639,13 +669,14 @@ private static void processAnnotation(boolean key, QuerySqlField sqlAnn, QueryTe
F.eq(aliases, entity.aliases) &&
F.eqNotOrdered(idxs, entity.idxs) &&
F.eq(tableName, entity.tableName) &&
F.eq(_notNullFields, entity._notNullFields);
F.eq(_notNullFields, entity._notNullFields) &&
F.eq(defaultFieldValues, entity.defaultFieldValues);
}

/** {@inheritDoc} */
@Override public int hashCode() {
return Objects.hash(keyType, valType, keyFieldName, valueFieldName, fields, keyFields, aliases, idxs,
tableName, _notNullFields);
tableName, _notNullFields, defaultFieldValues);
}

/** {@inheritDoc} */
Expand Down
Expand Up @@ -56,6 +56,8 @@ public class BinaryFieldImpl implements BinaryFieldEx {
/**
* Constructor.
*
* @param ctx Binary context.
* @param typeId Type ID.
* @param schemas Schemas.
* @param fieldName Field name.
* @param fieldId Field ID.
Expand Down Expand Up @@ -278,6 +280,9 @@ public int fieldOrder(BinaryObjectExImpl obj) {

int schemaId = obj.schemaId();

if (schemaId == 0)
return BinarySchema.ORDER_NOT_FOUND;

BinarySchema schema = schemas.schema(schemaId);

if (schema == null) {
Expand Down
Expand Up @@ -852,7 +852,7 @@ private List<Object> columnRow(JdbcColumnMeta colMeta, int pos) {
row.add(10); // 10. NUM_PREC_RADIX
row.add(colMeta.isNullable() ? columnNullable : columnNoNulls); // 11. NULLABLE
row.add((String)null); // 12. REMARKS
row.add((String)null); // 13. COLUMN_DEF
row.add(colMeta.defaultValue()); // 13. COLUMN_DEF
row.add(colMeta.dataType()); // 14. SQL_DATA_TYPE
row.add((Integer)null); // 15. SQL_DATETIME_SUB
row.add(Integer.MAX_VALUE); // 16. CHAR_OCTET_LENGTH
Expand Down
Expand Up @@ -74,8 +74,11 @@ public class JdbcThinTcpIo {
/** Version 2.3.1. */
private static final ClientListenerProtocolVersion VER_2_3_0 = ClientListenerProtocolVersion.create(2, 3, 0);

/** Version 2.4.0. */
private static final ClientListenerProtocolVersion VER_2_4_0 = ClientListenerProtocolVersion.create(2, 4, 0);

/** Current version. */
private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_3_0;
private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_4_0;

/** Initial output stream capacity for handshake. */
private static final int HANDSHAKE_MSG_SIZE = 13;
Expand Down Expand Up @@ -212,8 +215,8 @@ public void handshake(ClientListenerProtocolVersion ver) throws IOException, SQL

ClientListenerProtocolVersion srvProtocolVer = ClientListenerProtocolVersion.create(maj, min, maintenance);

if (VER_2_1_5.equals(srvProtocolVer))
handshake(VER_2_1_5);
if (VER_2_3_0.equals(srvProtocolVer) || VER_2_1_5.equals(srvProtocolVer))
handshake(srvProtocolVer);
else if (VER_2_1_0.equals(srvProtocolVer))
handshake_2_1_0();
else {
Expand Down
Expand Up @@ -127,6 +127,13 @@ public String dataTypeClass() {
return dataTypeClass;
}

/**
* @return Column's default value.
*/
public String defaultValue() {
return null;
}

/**
* Return 'nullable' flag in compatibility mode (according with column name and column type).
*
Expand Down
@@ -0,0 +1,83 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ignite.internal.processors.odbc.jdbc;

import org.apache.ignite.internal.binary.BinaryReaderExImpl;
import org.apache.ignite.internal.binary.BinaryWriterExImpl;
import org.apache.ignite.internal.util.typedef.internal.S;

/**
* JDBC column metadata V3.
*/
public class JdbcColumnMetaV3 extends JdbcColumnMetaV2 {
/** Default value. */
private String dfltValue;

/**
* Default constructor is used for serialization.
*/
JdbcColumnMetaV3() {
// No-op.
}

/**
* @param schemaName Schema.
* @param tblName Table.
* @param colName Column.
* @param cls Type.
* @param nullable Allow nulls.
* @param dfltVal Default value.
*/
public JdbcColumnMetaV3(String schemaName, String tblName, String colName, Class<?> cls, boolean nullable,
Object dfltVal) {
super(schemaName, tblName, colName, cls, nullable);

if (dfltVal == null)
dfltValue = null;
else {
if (dfltVal instanceof String)
dfltValue = "'" + String.valueOf(dfltVal) + "'";
else
dfltValue = String.valueOf(dfltVal);
}
}

/** {@inheritDoc} */
@Override public String defaultValue() {
return dfltValue;
}

/** {@inheritDoc} */
@Override public void writeBinary(BinaryWriterExImpl writer) {
super.writeBinary(writer);

writer.writeString(dfltValue);
}

/** {@inheritDoc} */
@Override public void readBinary(BinaryReaderExImpl reader) {
super.readBinary(reader);

dfltValue = reader.readString();
}

/** {@inheritDoc} */
@Override public String toString() {
return S.toString(JdbcColumnMetaV3.class, this);
}
}
Expand Up @@ -40,8 +40,11 @@ public class JdbcConnectionContext implements ClientListenerConnectionContext {
/** Version 2.3.1: added "multiple statements query" feature. */
public static final ClientListenerProtocolVersion VER_2_3_0 = ClientListenerProtocolVersion.create(2, 3, 0);

/** Version 2.4.0: adds default values for columns feature. */
public static final ClientListenerProtocolVersion VER_2_4_0 = ClientListenerProtocolVersion.create(2, 4, 0);

/** Current version. */
private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_3_0;
private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_4_0;

/** Supported versions. */
private static final Set<ClientListenerProtocolVersion> SUPPORTED_VERS = new HashSet<>();
Expand All @@ -63,6 +66,7 @@ public class JdbcConnectionContext implements ClientListenerConnectionContext {

static {
SUPPORTED_VERS.add(CURRENT_VER);
SUPPORTED_VERS.add(VER_2_3_0);
SUPPORTED_VERS.add(VER_2_1_5);
SUPPORTED_VERS.add(VER_2_1_0);
}
Expand Down
@@ -0,0 +1,50 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.ignite.internal.processors.odbc.jdbc;

import java.util.Collection;
import org.apache.ignite.internal.util.typedef.internal.S;

/**
* JDBC columns metadata result.
*/
public class JdbcMetaColumnsResultV3 extends JdbcMetaColumnsResult {
/**
* Default constructor is used for deserialization.
*/
JdbcMetaColumnsResultV3() {
super(META_COLUMNS_V3);
}

/**
* @param meta Columns metadata.
*/
JdbcMetaColumnsResultV3(Collection<JdbcColumnMeta> meta) {
super(META_COLUMNS_V3, meta);
}

/** {@inheritDoc} */
@Override protected JdbcColumnMeta createMetaColumn() {
return new JdbcColumnMetaV3();
}

/** {@inheritDoc} */
@Override public String toString() {
return S.toString(JdbcMetaColumnsResultV3.class, this);
}
}
Expand Up @@ -54,6 +54,7 @@
import org.apache.ignite.internal.util.typedef.internal.U;

import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_3_0;
import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcConnectionContext.VER_2_4_0;
import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.BATCH_EXEC;
import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.META_COLUMNS;
import static org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest.META_INDEXES;
Expand Down Expand Up @@ -592,7 +593,13 @@ private JdbcResponse getColumnsMeta(JdbcMetaColumnsRequest req) {

JdbcColumnMeta columnMeta;

if (protocolVer.compareTo(VER_2_3_0) >= 0) {
if (protocolVer.compareTo(VER_2_4_0) >= 0) {
GridQueryProperty prop = table.property(colName);

columnMeta = new JdbcColumnMetaV3(table.schemaName(), table.tableName(),
field.getKey(), field.getValue(), !prop.notNull(), prop.defaultValue());
}
else if (protocolVer.compareTo(VER_2_3_0) >= 0) {
GridQueryProperty prop = table.property(colName);

columnMeta = new JdbcColumnMetaV2(table.schemaName(), table.tableName(),
Expand All @@ -610,7 +617,9 @@ private JdbcResponse getColumnsMeta(JdbcMetaColumnsRequest req) {

JdbcMetaColumnsResult res;

if (protocolVer.compareTo(VER_2_3_0) >= 0)
if (protocolVer.compareTo(VER_2_4_0) >= 0)
res = new JdbcMetaColumnsResultV3(meta);
else if (protocolVer.compareTo(VER_2_3_0) >= 0)
res = new JdbcMetaColumnsResultV2(meta);
else
res = new JdbcMetaColumnsResult(meta);
Expand Down

0 comments on commit 78e79e0

Please sign in to comment.