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

Ignite SQL mode (#519)

上级 ceebdf6c
......@@ -4681,6 +4681,10 @@ public class Parser {
return false;
}
private boolean readIfAffinity() {
return readIf("AFFINITY") || readIf("SHARD");
}
private CreateConstant parseCreateConstant() {
boolean ifNotExists = readIfNotExists();
String constantName = readIdentifierWithSchema();
......@@ -5905,6 +5909,7 @@ public class Parser {
String constraintName = null, comment = null;
boolean ifNotExists = false;
boolean allowIndexDefinition = database.getMode().indexDefinitionInCreateTable;
boolean allowAffinityKey = database.getMode().allowAffinityKey;
if (readIf("CONSTRAINT")) {
ifNotExists = readIfNotExists();
constraintName = readIdentifierWithSchema(schema.getName());
......@@ -5956,6 +5961,12 @@ public class Parser {
read("BTREE");
}
return command;
} else if (allowAffinityKey && readIfAffinity()) {
read("KEY");
read("(");
CreateIndex command = createAffinityIndex(schema, tableName, parseIndexColumnList());
command.setIfTableExists(ifTableExists);
return command;
}
AlterTableAddConstraint command;
if (readIf("CHECK")) {
......@@ -6123,6 +6134,9 @@ public class Parser {
if (readIf("CONSTRAINT")) {
constraintName = readColumnIdentifier();
}
// For compatibility with Apache Ignite.
boolean allowAffinityKey = database.getMode().allowAffinityKey;
boolean affinity = allowAffinityKey && readIfAffinity();
if (readIf("PRIMARY")) {
read("KEY");
boolean hash = readIf("HASH");
......@@ -6138,6 +6152,16 @@ public class Parser {
if (readIf("AUTO_INCREMENT")) {
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")) {
AlterTableAddConstraint unique = new AlterTableAddConstraint(
session, schema, false);
......@@ -6256,6 +6280,14 @@ public class Parser {
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) {
switch (tokenType) {
case EQUAL:
......
......@@ -26,7 +26,7 @@ public class CreateIndex extends SchemaCommand {
private String tableName;
private String indexName;
private IndexColumn[] indexColumns;
private boolean primaryKey, unique, hash, spatial;
private boolean primaryKey, unique, hash, spatial, affinity;
private boolean ifTableExists;
private boolean ifNotExists;
private String comment;
......@@ -98,6 +98,8 @@ public class CreateIndex extends SchemaCommand {
indexType = IndexType.createPrimaryKey(persistent, hash);
} else if (unique) {
indexType = IndexType.createUnique(persistent, hash);
} else if (affinity) {
indexType = IndexType.createAffinity();
} else {
indexType = IndexType.createNonUnique(persistent, hash, spatial);
}
......@@ -123,6 +125,10 @@ public class CreateIndex extends SchemaCommand {
this.spatial = b;
}
public void setAffinity(boolean b) {
this.affinity = b;
}
public void setComment(String comment) {
this.comment = comment;
}
......
......@@ -80,5 +80,4 @@ public class CreateTableData {
* The table is hidden.
*/
public boolean isHidden;
}
......@@ -155,6 +155,11 @@ public class Mode {
*/
public boolean prohibitEmptyInPredicate;
/**
* Whether AFFINITY KEY keywords are supported.
*/
public boolean allowAffinityKey;
private final String name;
static {
......@@ -252,6 +257,12 @@ public class Mode {
Pattern.compile("ApplicationName");
mode.prohibitEmptyInPredicate = true;
add(mode);
mode = new Mode("Ignite");
mode.nullConcatIsNull = true;
mode.allowAffinityKey = true;
mode.indexDefinitionInCreateTable = true;
add(mode);
}
private Mode(String name) {
......
......@@ -10,7 +10,7 @@ package org.h2.index;
*/
public class IndexType {
private boolean primaryKey, persistent, unique, hash, scan, spatial;
private boolean primaryKey, persistent, unique, hash, scan, spatial, affinity;
private boolean belongsToConstraint;
/**
......@@ -71,6 +71,16 @@ public class IndexType {
return type;
}
/**
* Create an affinity index.
*
*/
public static IndexType createAffinity() {
IndexType type = new IndexType();
type.affinity = true;
return type;
}
/**
* Create a scan pseudo-index.
*
......@@ -148,6 +158,15 @@ public class IndexType {
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.
*
......
......@@ -200,7 +200,8 @@ public class MetaTable extends Table {
"ID INT",
"SORT_TYPE INT",
"CONSTRAINT_NAME",
"INDEX_CLASS"
"INDEX_CLASS",
"AFFINITY BIT"
);
indexColumnName = "TABLE_NAME";
break;
......@@ -912,7 +913,10 @@ public class MetaTable extends Table {
// CONSTRAINT_NAME
constraintName,
// INDEX_CLASS
indexClass
indexClass,
// AFFINITY
index.getIndexType().isAffinity() ?
"TRUE" : "FALSE"
);
}
}
......
......@@ -50,6 +50,7 @@ public class TestCompatibility extends TestBase {
testDB2();
testDerby();
testSybaseAndMSSQLServer();
testIgnite();
conn.close();
deleteDb("compatibility");
......@@ -487,4 +488,26 @@ public class TestCompatibility extends TestBase {
conn.close();
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;
import org.h2.result.Row;
import org.h2.result.SearchRow;
import org.h2.result.SortOrder;
import org.h2.table.Column;
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.table.*;
import org.h2.test.TestBase;
import org.h2.util.DoneFuture;
import org.h2.util.New;
......@@ -82,6 +76,7 @@ public class TestTableEngines extends TestBase {
testSimpleQuery();
testMultiColumnTreeSetIndex();
testBatchedJoin();
testAffinityKey();
}
private void testEarlyFilter() throws SQLException {
......@@ -504,6 +499,25 @@ public class TestTableEngines extends TestBase {
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 {
s.executeUpdate("SET FORCE_JOIN_ORDER " + force);
}
......@@ -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.
*/
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论