提交 8582753e authored 作者: alexpaschenko's avatar alexpaschenko 提交者: Sergi Vladykin

Ignite SQL mode (#519)

上级 ceebdf6c
...@@ -4681,6 +4681,10 @@ public class Parser { ...@@ -4681,6 +4681,10 @@ public class Parser {
return false; return false;
} }
private boolean readIfAffinity() {
return readIf("AFFINITY") || readIf("SHARD");
}
private CreateConstant parseCreateConstant() { private CreateConstant parseCreateConstant() {
boolean ifNotExists = readIfNotExists(); boolean ifNotExists = readIfNotExists();
String constantName = readIdentifierWithSchema(); String constantName = readIdentifierWithSchema();
...@@ -5905,6 +5909,7 @@ public class Parser { ...@@ -5905,6 +5909,7 @@ public class Parser {
String constraintName = null, comment = null; String constraintName = null, comment = null;
boolean ifNotExists = false; boolean ifNotExists = false;
boolean allowIndexDefinition = database.getMode().indexDefinitionInCreateTable; boolean allowIndexDefinition = database.getMode().indexDefinitionInCreateTable;
boolean allowAffinityKey = database.getMode().allowAffinityKey;
if (readIf("CONSTRAINT")) { if (readIf("CONSTRAINT")) {
ifNotExists = readIfNotExists(); ifNotExists = readIfNotExists();
constraintName = readIdentifierWithSchema(schema.getName()); constraintName = readIdentifierWithSchema(schema.getName());
...@@ -5956,6 +5961,12 @@ public class Parser { ...@@ -5956,6 +5961,12 @@ public class Parser {
read("BTREE"); read("BTREE");
} }
return command; return command;
} else if (allowAffinityKey && readIfAffinity()) {
read("KEY");
read("(");
CreateIndex command = createAffinityIndex(schema, tableName, parseIndexColumnList());
command.setIfTableExists(ifTableExists);
return command;
} }
AlterTableAddConstraint command; AlterTableAddConstraint command;
if (readIf("CHECK")) { if (readIf("CHECK")) {
...@@ -6123,6 +6134,9 @@ public class Parser { ...@@ -6123,6 +6134,9 @@ public class Parser {
if (readIf("CONSTRAINT")) { if (readIf("CONSTRAINT")) {
constraintName = readColumnIdentifier(); constraintName = readColumnIdentifier();
} }
// For compatibility with Apache Ignite.
boolean allowAffinityKey = database.getMode().allowAffinityKey;
boolean affinity = allowAffinityKey && readIfAffinity();
if (readIf("PRIMARY")) { if (readIf("PRIMARY")) {
read("KEY"); read("KEY");
boolean hash = readIf("HASH"); boolean hash = readIf("HASH");
...@@ -6138,6 +6152,16 @@ public class Parser { ...@@ -6138,6 +6152,16 @@ public class Parser {
if (readIf("AUTO_INCREMENT")) { if (readIf("AUTO_INCREMENT")) {
parseAutoIncrement(column); parseAutoIncrement(column);
} }
if (affinity) {
CreateIndex idx = createAffinityIndex(schema, tableName, cols);
command.addConstraintCommand(idx);
}
} else if (affinity) {
read("KEY");
IndexColumn[] cols = { new IndexColumn() };
cols[0].columnName = column.getName();
CreateIndex idx = createAffinityIndex(schema, tableName, cols);
command.addConstraintCommand(idx);
} else if (readIf("UNIQUE")) { } else if (readIf("UNIQUE")) {
AlterTableAddConstraint unique = new AlterTableAddConstraint( AlterTableAddConstraint unique = new AlterTableAddConstraint(
session, schema, false); session, schema, false);
...@@ -6256,6 +6280,14 @@ public class Parser { ...@@ -6256,6 +6280,14 @@ public class Parser {
return command; return command;
} }
private CreateIndex createAffinityIndex(Schema schema, String tableName, IndexColumn[] indexColumns) {
CreateIndex idx = new CreateIndex(session, schema);
idx.setTableName(tableName);
idx.setIndexColumns(indexColumns);
idx.setAffinity(true);
return idx;
}
private static int getCompareType(int tokenType) { private static int getCompareType(int tokenType) {
switch (tokenType) { switch (tokenType) {
case EQUAL: case EQUAL:
......
...@@ -26,7 +26,7 @@ public class CreateIndex extends SchemaCommand { ...@@ -26,7 +26,7 @@ public class CreateIndex extends SchemaCommand {
private String tableName; private String tableName;
private String indexName; private String indexName;
private IndexColumn[] indexColumns; private IndexColumn[] indexColumns;
private boolean primaryKey, unique, hash, spatial; private boolean primaryKey, unique, hash, spatial, affinity;
private boolean ifTableExists; private boolean ifTableExists;
private boolean ifNotExists; private boolean ifNotExists;
private String comment; private String comment;
...@@ -98,6 +98,8 @@ public class CreateIndex extends SchemaCommand { ...@@ -98,6 +98,8 @@ public class CreateIndex extends SchemaCommand {
indexType = IndexType.createPrimaryKey(persistent, hash); indexType = IndexType.createPrimaryKey(persistent, hash);
} else if (unique) { } else if (unique) {
indexType = IndexType.createUnique(persistent, hash); indexType = IndexType.createUnique(persistent, hash);
} else if (affinity) {
indexType = IndexType.createAffinity();
} else { } else {
indexType = IndexType.createNonUnique(persistent, hash, spatial); indexType = IndexType.createNonUnique(persistent, hash, spatial);
} }
...@@ -123,6 +125,10 @@ public class CreateIndex extends SchemaCommand { ...@@ -123,6 +125,10 @@ public class CreateIndex extends SchemaCommand {
this.spatial = b; this.spatial = b;
} }
public void setAffinity(boolean b) {
this.affinity = b;
}
public void setComment(String comment) { public void setComment(String comment) {
this.comment = comment; this.comment = comment;
} }
......
...@@ -80,5 +80,4 @@ public class CreateTableData { ...@@ -80,5 +80,4 @@ public class CreateTableData {
* The table is hidden. * The table is hidden.
*/ */
public boolean isHidden; public boolean isHidden;
} }
...@@ -155,6 +155,11 @@ public class Mode { ...@@ -155,6 +155,11 @@ public class Mode {
*/ */
public boolean prohibitEmptyInPredicate; public boolean prohibitEmptyInPredicate;
/**
* Whether AFFINITY KEY keywords are supported.
*/
public boolean allowAffinityKey;
private final String name; private final String name;
static { static {
...@@ -252,6 +257,12 @@ public class Mode { ...@@ -252,6 +257,12 @@ public class Mode {
Pattern.compile("ApplicationName"); Pattern.compile("ApplicationName");
mode.prohibitEmptyInPredicate = true; mode.prohibitEmptyInPredicate = true;
add(mode); add(mode);
mode = new Mode("Ignite");
mode.nullConcatIsNull = true;
mode.allowAffinityKey = true;
mode.indexDefinitionInCreateTable = true;
add(mode);
} }
private Mode(String name) { private Mode(String name) {
......
...@@ -10,7 +10,7 @@ package org.h2.index; ...@@ -10,7 +10,7 @@ package org.h2.index;
*/ */
public class IndexType { public class IndexType {
private boolean primaryKey, persistent, unique, hash, scan, spatial; private boolean primaryKey, persistent, unique, hash, scan, spatial, affinity;
private boolean belongsToConstraint; private boolean belongsToConstraint;
/** /**
...@@ -71,6 +71,16 @@ public class IndexType { ...@@ -71,6 +71,16 @@ public class IndexType {
return type; return type;
} }
/**
* Create an affinity index.
*
*/
public static IndexType createAffinity() {
IndexType type = new IndexType();
type.affinity = true;
return type;
}
/** /**
* Create a scan pseudo-index. * Create a scan pseudo-index.
* *
...@@ -148,6 +158,15 @@ public class IndexType { ...@@ -148,6 +158,15 @@ public class IndexType {
return unique; return unique;
} }
/**
* Does this index represent an affinity key?
*
* @return true if it does
*/
public boolean isAffinity() {
return affinity;
}
/** /**
* Get the SQL snippet to create such an index. * Get the SQL snippet to create such an index.
* *
......
...@@ -200,7 +200,8 @@ public class MetaTable extends Table { ...@@ -200,7 +200,8 @@ public class MetaTable extends Table {
"ID INT", "ID INT",
"SORT_TYPE INT", "SORT_TYPE INT",
"CONSTRAINT_NAME", "CONSTRAINT_NAME",
"INDEX_CLASS" "INDEX_CLASS",
"AFFINITY BIT"
); );
indexColumnName = "TABLE_NAME"; indexColumnName = "TABLE_NAME";
break; break;
...@@ -912,7 +913,10 @@ public class MetaTable extends Table { ...@@ -912,7 +913,10 @@ public class MetaTable extends Table {
// CONSTRAINT_NAME // CONSTRAINT_NAME
constraintName, constraintName,
// INDEX_CLASS // INDEX_CLASS
indexClass indexClass,
// AFFINITY
index.getIndexType().isAffinity() ?
"TRUE" : "FALSE"
); );
} }
} }
......
...@@ -50,6 +50,7 @@ public class TestCompatibility extends TestBase { ...@@ -50,6 +50,7 @@ public class TestCompatibility extends TestBase {
testDB2(); testDB2();
testDerby(); testDerby();
testSybaseAndMSSQLServer(); testSybaseAndMSSQLServer();
testIgnite();
conn.close(); conn.close();
deleteDb("compatibility"); deleteDb("compatibility");
...@@ -487,4 +488,26 @@ public class TestCompatibility extends TestBase { ...@@ -487,4 +488,26 @@ public class TestCompatibility extends TestBase {
conn.close(); conn.close();
conn = getConnection("compatibility"); conn = getConnection("compatibility");
} }
private void testIgnite() throws SQLException {
Statement stat = conn.createStatement();
stat.execute("SET MODE Ignite");
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int affinity key)");
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int affinity primary key)");
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int, v1 varchar, v2 long affinity key, primary key(v1, id))");
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int, v1 varchar, v2 long, primary key(v1, id), affinity key (id))");
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int shard key)");
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int shard primary key)");
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int, v1 varchar, v2 long shard key, primary key(v1, id))");
stat.execute("DROP TABLE IF EXISTS TEST");
stat.execute("create table test(id int, v1 varchar, v2 long, primary key(v1, id), shard key (id))");
}
} }
...@@ -41,13 +41,7 @@ import org.h2.message.DbException; ...@@ -41,13 +41,7 @@ import org.h2.message.DbException;
import org.h2.result.Row; import org.h2.result.Row;
import org.h2.result.SearchRow; import org.h2.result.SearchRow;
import org.h2.result.SortOrder; import org.h2.result.SortOrder;
import org.h2.table.Column; import org.h2.table.*;
import org.h2.table.IndexColumn;
import org.h2.table.SubQueryInfo;
import org.h2.table.Table;
import org.h2.table.TableBase;
import org.h2.table.TableFilter;
import org.h2.table.TableType;
import org.h2.test.TestBase; import org.h2.test.TestBase;
import org.h2.util.DoneFuture; import org.h2.util.DoneFuture;
import org.h2.util.New; import org.h2.util.New;
...@@ -82,6 +76,7 @@ public class TestTableEngines extends TestBase { ...@@ -82,6 +76,7 @@ public class TestTableEngines extends TestBase {
testSimpleQuery(); testSimpleQuery();
testMultiColumnTreeSetIndex(); testMultiColumnTreeSetIndex();
testBatchedJoin(); testBatchedJoin();
testAffinityKey();
} }
private void testEarlyFilter() throws SQLException { private void testEarlyFilter() throws SQLException {
...@@ -504,6 +499,25 @@ public class TestTableEngines extends TestBase { ...@@ -504,6 +499,25 @@ public class TestTableEngines extends TestBase {
deleteDb("testBatchedJoin"); deleteDb("testBatchedJoin");
} }
private void testAffinityKey() throws SQLException {
deleteDb("tableEngine");
Connection conn = getConnection("tableEngine;mode=Ignite;MV_STORE=FALSE");
Statement stat = conn.createStatement();
stat.executeUpdate("CREATE TABLE T(ID INT AFFINITY PRIMARY KEY, NAME VARCHAR, AGE INT)" +
" ENGINE \"" + AffinityTableEngine.class.getName() + "\"");
Table tbl = AffinityTableEngine.createdTbl;
assertTrue(tbl != null);
assertEquals(3, tbl.getIndexes().size());
Index aff = tbl.getIndexes().get(2);
assertTrue(aff.getIndexType().isAffinity());
assertEquals("T_AFF", aff.getName());
assertEquals(1, aff.getIndexColumns().length);
assertEquals("ID", aff.getIndexColumns()[0].columnName);
conn.close();
deleteDb("tableEngine");
}
private static void forceJoinOrder(Statement s, boolean force) throws SQLException { private static void forceJoinOrder(Statement s, boolean force) throws SQLException {
s.executeUpdate("SET FORCE_JOIN_ORDER " + force); s.executeUpdate("SET FORCE_JOIN_ORDER " + force);
} }
...@@ -1098,6 +1112,144 @@ public class TestTableEngines extends TestBase { ...@@ -1098,6 +1112,144 @@ public class TestTableEngines extends TestBase {
} }
/**
* A test table factory producing affinity aware tables.
*/
public static class AffinityTableEngine implements TableEngine {
public static Table createdTbl;
/**
* A table able to handle affinity indexes.
*/
private static class AffinityTable extends RegularTable {
/**
* A (no-op) affinity index.
*/
public class AffinityIndex extends BaseIndex {
AffinityIndex(Table table, int id, String name, IndexColumn[] newIndexColumns) {
initBaseIndex(table, id, name, newIndexColumns, IndexType.createAffinity());
}
@Override
public long getRowCountApproximation() {
return table.getRowCountApproximation();
}
@Override
public long getDiskSpaceUsed() {
return table.getDiskSpaceUsed();
}
@Override
public long getRowCount(Session session) {
return table.getRowCount(session);
}
@Override
public void checkRename() {
// do nothing
}
@Override
public void truncate(Session session) {
// do nothing
}
@Override
public void remove(Session session) {
// do nothing
}
@Override
public void remove(Session session, Row r) {
// do nothing
}
@Override
public boolean needRebuild() {
return false;
}
@Override
public double getCost(Session session, int[] masks,
TableFilter[] filters, int filter, SortOrder sortOrder,
HashSet<Column> allColumnsSet) {
return 0;
}
@Override
public Cursor findFirstOrLast(Session session, boolean first) {
throw DbException.getUnsupportedException("TEST");
}
@Override
public Cursor find(Session session, SearchRow first, SearchRow last) {
throw DbException.getUnsupportedException("TEST");
}
@Override
public void close(Session session) {
// do nothing
}
@Override
public boolean canGetFirstOrLast() {
return false;
}
@Override
public void add(Session session, Row r) {
// do nothing
}
}
AffinityTable(CreateTableData data) {
super(data);
}
@Override
public Index addIndex(Session session, String indexName,
int indexId, IndexColumn[] cols, IndexType indexType,
boolean create, String indexComment) {
if (!indexType.isAffinity()) {
return super.addIndex(session, indexName, indexId, cols, indexType, create, indexComment);
}
boolean isSessionTemporary = isTemporary() && !isGlobalTemporary();
if (!isSessionTemporary) {
database.lockMeta(session);
}
AffinityIndex index = new AffinityIndex(this, indexId, getName() + "_AFF", cols);
index.setTemporary(isTemporary());
if (index.getCreateSQL() != null) {
index.setComment(indexComment);
if (isSessionTemporary) {
session.addLocalTempTableIndex(index);
} else {
database.addSchemaObject(session, index);
}
}
getIndexes().add(index);
setModified();
return index;
}
}
/**
* Create a new OneRowTable.
*
* @param data the meta data of the table to create
* @return the new table
*/
@Override
public Table createTable(CreateTableData data) {
return (createdTbl = new AffinityTable(data));
}
}
/** /**
* A test table factory. * A test table factory.
*/ */
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论