use of herddb.model.Column in project herddb by diennea.
the class JSQLParserPlanner method parseForeignKeyIndex.
private ForeignKeyDef parseForeignKeyIndex(ForeignKeyIndex fk, Table table, String tableName, String tableSpace) throws StatementExecutionException {
String indexName = fixMySqlBackTicks(fk.getName().toLowerCase());
if (indexName.equals("generate_unnamed")) {
indexName = "fk_" + tableName + "_" + System.nanoTime();
}
int onUpdateCascadeAction = parseForeignKeyAction(fk.getOnUpdateReferenceOption());
int onDeleteCascadeAction = parseForeignKeyAction(fk.getOnDeleteReferenceOption());
Table parentTableSchema = getTable(table.tablespace, fk.getTable());
herddb.model.ForeignKeyDef.Builder builder = herddb.model.ForeignKeyDef.builder().name(indexName).parentTableId(parentTableSchema.uuid).onUpdateAction(onUpdateCascadeAction).onDeleteAction(onDeleteCascadeAction);
for (String columnName : fk.getColumnsNames()) {
columnName = fixMySqlBackTicks(columnName.toLowerCase());
Column column = table.getColumn(columnName);
if (column == null) {
throw new StatementExecutionException("no such column " + columnName + " on table " + tableName + " in tablespace " + tableSpace);
}
builder.column(column.name);
}
for (String columnName : fk.getReferencedColumnNames()) {
columnName = fixMySqlBackTicks(columnName.toLowerCase());
Column column = parentTableSchema.getColumn(columnName);
if (column == null) {
throw new StatementExecutionException("no such column " + columnName + " on table " + parentTableSchema.name + " in tablespace " + parentTableSchema.tablespace);
}
builder.parentTableColumn(column.name);
}
ForeignKeyDef fkDef = builder.build();
return fkDef;
}
use of herddb.model.Column in project herddb by diennea.
the class JSQLParserPlanner method buildCreateTableStatement.
private Statement buildCreateTableStatement(String defaultTableSpace, CreateTable s) throws StatementExecutionException {
String tableSpace = fixMySqlBackTicks(s.getTable().getSchemaName());
String tableName = fixMySqlBackTicks(s.getTable().getName());
if (tableSpace == null) {
tableSpace = defaultTableSpace;
}
if (s.getColumnDefinitions() == null) {
throw new StatementExecutionException("A table must have at least 1 column");
}
final boolean isNotExsists = s.isIfNotExists();
try {
boolean foundPk = false;
Table.Builder tablebuilder = Table.builder().uuid(UUID.randomUUID().toString()).name(tableName).tablespace(tableSpace);
Set<String> primaryKey = new HashSet<>();
Set<String> simpleUniqueFields = new HashSet<>();
if (s.getIndexes() != null) {
for (Index index : s.getIndexes()) {
if (index.getType().equalsIgnoreCase("PRIMARY KEY")) {
for (String n : index.getColumnsNames()) {
n = fixMySqlBackTicks(n.toLowerCase());
tablebuilder.primaryKey(n);
primaryKey.add(n);
foundPk = true;
}
}
}
}
int position = 0;
for (ColumnDefinition cf : s.getColumnDefinitions()) {
String columnName = fixMySqlBackTicks(cf.getColumnName().toLowerCase());
int type;
String dataType = cf.getColDataType().getDataType();
List<String> columnSpecs = decodeColumnSpecs(cf.getColumnSpecs());
type = sqlDataTypeToColumnType(dataType, cf.getColDataType().getArgumentsStringList(), columnSpecs);
Bytes defaultValue = decodeDefaultValue(cf, type);
if (!columnSpecs.isEmpty()) {
boolean auto_increment = decodeAutoIncrement(columnSpecs);
if (columnSpecs.contains("PRIMARY")) {
foundPk = true;
tablebuilder.primaryKey(columnName, auto_increment);
}
if (auto_increment && primaryKey.contains(columnName)) {
tablebuilder.primaryKey(columnName, auto_increment);
}
boolean isUnique = columnSpecs.contains("UNIQUE");
if (isUnique) {
simpleUniqueFields.add(columnName);
}
}
tablebuilder.column(columnName, type, position++, defaultValue);
}
if (!foundPk) {
tablebuilder.column("_pk", ColumnTypes.LONG, position++, null);
tablebuilder.primaryKey("_pk", true);
}
Table table = tablebuilder.build();
List<herddb.model.Index> otherIndexes = new ArrayList<>();
List<herddb.model.ForeignKeyDef> foreignKeys = new ArrayList<>();
if (s.getIndexes() != null) {
for (Index index : s.getIndexes()) {
if (index.getType().equalsIgnoreCase("PRIMARY KEY")) {
} else if (index.getType().equalsIgnoreCase("INDEX") || index.getType().equalsIgnoreCase("KEY") || index.getType().equalsIgnoreCase("UNIQUE KEY")) {
String indexName = fixMySqlBackTicks(index.getName().toLowerCase());
String indexType = convertIndexType(null);
boolean unique = index.getType().equalsIgnoreCase("UNIQUE KEY");
herddb.model.Index.Builder builder = herddb.model.Index.builder().onTable(table).name(indexName).unique(unique).type(indexType).uuid(UUID.randomUUID().toString());
for (String columnName : index.getColumnsNames()) {
columnName = fixMySqlBackTicks(columnName.toLowerCase());
Column column = table.getColumn(columnName);
if (column == null) {
throw new StatementExecutionException("no such column " + columnName + " on table " + tableName + " in tablespace " + tableSpace);
}
builder.column(column.name, column.type);
}
otherIndexes.add(builder.build());
} else if (index.getType().equals("FOREIGN KEY")) {
ForeignKeyIndex fk = (ForeignKeyIndex) index;
ForeignKeyDef fkDef = parseForeignKeyIndex(fk, table, tableName, tableSpace);
foreignKeys.add(fkDef);
} else {
throw new StatementExecutionException("Unsupported index type " + index.getType());
}
}
}
for (String col : simpleUniqueFields) {
herddb.model.Index.Builder builder = herddb.model.Index.builder().onTable(table).name(table.name + "_unique_" + col).unique(true).type(herddb.model.Index.TYPE_BRIN).uuid(UUID.randomUUID().toString()).column(col, table.getColumn(col).type);
otherIndexes.add(builder.build());
}
if (!foreignKeys.isEmpty()) {
table = table.withForeignKeys(foreignKeys.toArray(new ForeignKeyDef[0]));
}
CreateTableStatement statement = new CreateTableStatement(table, otherIndexes, isNotExsists);
return statement;
} catch (IllegalArgumentException err) {
throw new StatementExecutionException("bad table definition: " + err.getMessage(), err);
}
}
use of herddb.model.Column in project herddb by diennea.
the class JSQLParserPlanner method planAggregate.
private PlannerOp planAggregate(List<SelectExpressionItem> fieldList, OpSchema inputSchema, PlannerOp input, OpSchema originalTableSchema, GroupByElement groupBy) {
List<Column> outputSchemaKeysInGroupBy = new ArrayList<>();
List<String> fieldnamesKeysInGroupBy = new ArrayList<>();
List<Column> outputSchemaAggregationResults = new ArrayList<>();
List<String> fieldnamesAggregationResults = new ArrayList<>();
List<Integer> projectionAggregationResults = new ArrayList<>();
List<List<Integer>> argLists = new ArrayList<>();
List<String> aggtypes = new ArrayList<>();
List<Column> originalOutputSchema = new ArrayList<>();
List<String> originalFieldNames = new ArrayList<>();
Set<String> nonAggregateColumns = new HashSet<>();
int k = 0;
for (SelectExpressionItem sel : fieldList) {
Alias alias = sel.getAlias();
String fieldName = null;
if (alias != null) {
checkSupported(alias.getAliasColumns() == null);
fieldName = fixMySqlBackTicks(alias.getName().toLowerCase());
}
Expression exp = sel.getExpression();
Function fn = SQLParserExpressionCompiler.detectAggregatedFunction(exp);
if (fn != null) {
int type = SQLParserExpressionCompiler.getAggregateFunctionType(exp, inputSchema);
ColumnRef additionalColumn = SQLParserExpressionCompiler.getAggregateFunctionArgument(fn, inputSchema);
aggtypes.add(fixMySqlBackTicks(fn.getName().toLowerCase()));
if (additionalColumn != null) {
// SELECT min(col) -> we have to add "col" to the scan
IntHolder pos = new IntHolder();
findColumnInSchema(additionalColumn.tableName, fixMySqlBackTicks(additionalColumn.name), originalTableSchema, pos);
checkSupported(pos.value >= 0);
argLists.add(Collections.singletonList(pos.value));
} else {
argLists.add(Collections.emptyList());
}
if (fieldName == null) {
fieldName = "expr$" + k;
}
Column col = Column.column(fieldName, type);
outputSchemaAggregationResults.add(col);
originalFieldNames.add(fieldName);
originalOutputSchema.add(col);
fieldnamesAggregationResults.add(fieldName);
projectionAggregationResults.add(k);
} else if (exp instanceof net.sf.jsqlparser.schema.Column) {
net.sf.jsqlparser.schema.Column colRef = (net.sf.jsqlparser.schema.Column) exp;
String tableAlias = extractTableName(colRef);
ColumnRef colInSchema = findColumnInSchema(tableAlias, fixMySqlBackTicks(colRef.getColumnName()), inputSchema, new IntHolder());
checkSupported(colInSchema != null);
if (fieldName == null) {
fieldName = colInSchema.name;
}
Column col = Column.column(fieldName, colInSchema.type);
originalFieldNames.add(fieldName);
originalOutputSchema.add(col);
nonAggregateColumns.add(fieldName);
} else {
checkSupported(false);
}
k++;
}
// GROUP BY
List<Integer> groupedFieldsIndexes = new ArrayList<>();
List<Integer> projectionForGroupByFields = new ArrayList<>();
if (groupBy != null) {
checkSupported(groupBy.getGroupingSets() == null || groupBy.getGroupingSets().isEmpty());
int posInGroupBy = 0;
for (Expression exp : groupBy.getGroupByExpressions()) {
if (exp instanceof net.sf.jsqlparser.schema.Column) {
net.sf.jsqlparser.schema.Column colRef = (net.sf.jsqlparser.schema.Column) exp;
String tableName = extractTableName(colRef);
IntHolder pos = new IntHolder();
ColumnRef colInSchema = findColumnInSchema(tableName, fixMySqlBackTicks(colRef.getColumnName()), inputSchema, pos);
checkSupported(colInSchema != null);
groupedFieldsIndexes.add(pos.value);
fieldnamesKeysInGroupBy.add(fixMySqlBackTicks(colRef.getColumnName()));
outputSchemaKeysInGroupBy.add(colInSchema.toColumn());
projectionForGroupByFields.add(posInGroupBy);
} else {
checkSupported(false);
}
posInGroupBy++;
}
} else {
// -> column MUST be in GROUP BY !
for (String s : nonAggregateColumns) {
throw new StatementExecutionException("field " + s + " MUST appear in GROUP BY clause");
}
}
PlannerOp op;
if (!groupedFieldsIndexes.isEmpty()) {
// this is tricky,
// the AggregateOp always create a result in the form of
// FIELD1,FIELD2......AGG1,AGG2
// Basically it puts all of the results of the aggregation to the right
// So we have to add a projection that makes the resultset appear
// as it is defined in the SELECT clause
List<Column> outputSchema = new ArrayList<>();
outputSchema.addAll(outputSchemaKeysInGroupBy);
outputSchema.addAll(outputSchemaAggregationResults);
Column[] outputSchemaArray = outputSchema.toArray(new Column[0]);
List<String> aggreateFieldNames = new ArrayList<>();
aggreateFieldNames.addAll(fieldnamesKeysInGroupBy);
aggreateFieldNames.addAll(fieldnamesAggregationResults);
op = new AggregateOp(input, aggreateFieldNames.toArray(new String[0]), outputSchemaArray, aggtypes.toArray(new String[0]), argLists, groupedFieldsIndexes);
String[] reodereded = originalFieldNames.toArray(new String[0]);
int[] projections = new int[originalFieldNames.size()];
int i = 0;
for (int pos : projectionForGroupByFields) {
projections[pos] = i++;
}
for (int pos : projectionAggregationResults) {
projections[pos] = i++;
}
ProjectOp.ZeroCopyProjection projection = new ProjectOp.ZeroCopyProjection(reodereded, originalOutputSchema.toArray(new Column[0]), projections);
op = new ProjectOp(projection, op);
} else {
// no "GROUP BY", so no need for an additional projection
// this is the SELECT COUNT(*) FROM TABLE case
op = new AggregateOp(input, originalFieldNames.toArray(new String[0]), originalOutputSchema.toArray(new Column[0]), aggtypes.toArray(new String[0]), argLists, groupedFieldsIndexes);
}
return op;
}
use of herddb.model.Column in project herddb by diennea.
the class JSQLParserPlanner method buildCreateIndexStatement.
private Statement buildCreateIndexStatement(String defaultTableSpace, CreateIndex s) throws StatementExecutionException {
try {
String tableSpace = s.getTable().getSchemaName();
if (tableSpace == null) {
tableSpace = defaultTableSpace;
}
tableSpace = fixMySqlBackTicks(tableSpace);
String tableName = fixMySqlBackTicks(s.getTable().getName().toLowerCase());
String indexName = fixMySqlBackTicks(s.getIndex().getName().toLowerCase());
boolean unique = isUnique(s.getIndex().getType());
String indexType = convertIndexType(s.getIndex().getType());
herddb.model.Index.Builder builder = herddb.model.Index.builder().name(indexName).uuid(UUID.randomUUID().toString()).type(indexType).unique(unique).table(tableName).tablespace(tableSpace);
AbstractTableManager tableDefinition = manager.getTableSpaceManager(tableSpace).getTableManager(tableName);
if (tableDefinition == null) {
throw new TableDoesNotExistException("no such table " + tableName + " in tablespace " + tableSpace);
}
for (String columnName : s.getIndex().getColumnsNames()) {
columnName = fixMySqlBackTicks(columnName.toLowerCase());
Column column = tableDefinition.getTable().getColumn(columnName);
if (column == null) {
throw new StatementExecutionException("no such column " + columnName + " on table " + tableName + " in tablespace " + tableSpace);
}
builder.column(column.name, column.type);
}
CreateIndexStatement statement = new CreateIndexStatement(builder.build());
return statement;
} catch (IllegalArgumentException err) {
throw new StatementExecutionException("bad index definition: " + err.getMessage(), err);
}
}
use of herddb.model.Column in project herddb by diennea.
the class JSQLParserPlanner method buildProjection.
private Projection buildProjection(final List<SelectExpressionItem> projects, final boolean allowIdentity, final OpSchema tableSchema) {
boolean allowZeroCopyProjection = true;
List<CompiledSQLExpression> fields = new ArrayList<>(projects.size());
Column[] columns = new Column[projects.size()];
String[] fieldNames = new String[columns.length];
int i = 0;
int[] zeroCopyProjections = new int[fieldNames.length];
boolean identity = allowIdentity && tableSchema != null && tableSchema.columns.length == fieldNames.length;
for (SelectExpressionItem node : projects) {
int type = ColumnTypes.ANYTYPE;
CompiledSQLExpression exp;
String alias = null;
if (node.getAlias() != null) {
alias = fixMySqlBackTicks(node.getAlias().getName().toLowerCase());
checkSupported(node.getAlias().getAliasColumns() == null);
}
if (node.getExpression() instanceof net.sf.jsqlparser.schema.Column && !isBooleanLiteral((net.sf.jsqlparser.schema.Column) node.getExpression())) {
net.sf.jsqlparser.schema.Column col = (net.sf.jsqlparser.schema.Column) node.getExpression();
// checkSupported(col.getTable() == null);
String columnName = fixMySqlBackTicks(col.getColumnName());
String tableAlias = extractTableName(col);
if (alias == null) {
alias = columnName;
}
IntHolder indexInSchema = new IntHolder(-1);
ColumnRef found = findColumnInSchema(tableAlias, columnName, tableSchema, indexInSchema);
if (indexInSchema.value == -1 || found == null) {
String nameInError = tableAlias != null ? tableAlias + "." + columnName : columnName;
throw new StatementExecutionException("Column " + nameInError + " not found in target table (schema " + tableSchema + ")");
}
exp = new AccessCurrentRowExpression(indexInSchema.value, found.type);
type = found.type;
} else {
exp = SQLParserExpressionCompiler.compileExpression(node.getExpression(), tableSchema);
if (alias == null) {
alias = "col" + i;
}
}
if (exp instanceof AccessCurrentRowExpression) {
AccessCurrentRowExpression accessCurrentRowExpression = (AccessCurrentRowExpression) exp;
int mappedIndex = accessCurrentRowExpression.getIndex();
zeroCopyProjections[i] = mappedIndex;
if (i != mappedIndex) {
identity = false;
}
} else {
allowZeroCopyProjection = false;
}
fields.add(exp);
Column col = Column.column(alias, type);
identity = identity && col.name.equals(tableSchema.columns[i].name);
fieldNames[i] = alias;
columns[i++] = col;
}
if (allowZeroCopyProjection) {
if (identity) {
return Projection.IDENTITY(fieldNames, columns);
}
return new ProjectOp.ZeroCopyProjection(fieldNames, columns, zeroCopyProjections);
} else {
return new ProjectOp.BasicProjection(fieldNames, columns, fields);
}
}
Aggregations