use of herddb.model.Table in project herddb by diennea.
the class JSQLParserPlanner method buildAlterStatement.
private Statement buildAlterStatement(String defaultTableSpace, Alter alter) throws StatementExecutionException {
if (alter.getTable() == null) {
throw new StatementExecutionException("missing table name");
}
String tableSpace = alter.getTable().getSchemaName();
if (tableSpace == null) {
tableSpace = defaultTableSpace;
}
tableSpace = fixMySqlBackTicks(tableSpace);
List<Column> addColumns = new ArrayList<>();
List<Column> modifyColumns = new ArrayList<>();
List<String> dropColumns = new ArrayList<>();
List<String> dropForeignKeys = new ArrayList<>();
List<ForeignKeyDef> addForeignKeys = new ArrayList<>();
String tableName = fixMySqlBackTicks(alter.getTable().getName().toLowerCase());
if (alter.getAlterExpressions() == null || alter.getAlterExpressions().size() != 1) {
throw new StatementExecutionException("supported multi-alter operation '" + alter + "'");
}
AlterExpression alterExpression = alter.getAlterExpressions().get(0);
AlterOperation operation = alterExpression.getOperation();
Boolean changeAutoIncrement = null;
TableSpaceManager tableSpaceManager = manager.getTableSpaceManager(tableSpace);
if (tableSpaceManager == null) {
throw new StatementExecutionException("bad tablespace '" + tableSpace + "'");
}
Table table = getTable(defaultTableSpace, alter.getTable());
switch(operation) {
case ADD:
{
if (alterExpression.getColDataTypeList() != null) {
List<AlterExpression.ColumnDataType> cols = alterExpression.getColDataTypeList();
for (AlterExpression.ColumnDataType cl : cols) {
List<String> columnSpecs = decodeColumnSpecs(cl.getColumnSpecs());
int type = sqlDataTypeToColumnType(cl.getColDataType().getDataType(), cl.getColDataType().getArgumentsStringList(), columnSpecs);
Column newColumn = Column.column(fixMySqlBackTicks(cl.getColumnName()), type, decodeDefaultValue(cl, type));
addColumns.add(newColumn);
}
} else if (alterExpression.getIndex() != null && alterExpression.getIndex() instanceof ForeignKeyIndex) {
ForeignKeyDef fkIndex = parseForeignKeyIndex((ForeignKeyIndex) alterExpression.getIndex(), table, tableName, tableSpace);
addForeignKeys.add(fkIndex);
} else {
throw new StatementExecutionException("Unrecognized ALTER TABLE ADD ... statement");
}
}
break;
case DROP:
if (alterExpression.getColumnName() != null) {
dropColumns.add(fixMySqlBackTicks(alterExpression.getColumnName()));
} else if (alterExpression.getConstraintName() != null) {
dropForeignKeys.add(fixMySqlBackTicks(alterExpression.getConstraintName()));
} else {
throw new StatementExecutionException("Unrecognized ALTER TABLE DROP ... statement");
}
break;
case MODIFY:
{
List<AlterExpression.ColumnDataType> cols = alterExpression.getColDataTypeList();
for (AlterExpression.ColumnDataType cl : cols) {
String columnName = fixMySqlBackTicks(cl.getColumnName().toLowerCase());
Column oldColumn = table.getColumn(columnName);
if (oldColumn == null) {
throw new StatementExecutionException("bad column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
}
Map<String, AbstractIndexManager> indexes = tableSpaceManager.getIndexesOnTable(tableName);
if (indexes != null) {
for (AbstractIndexManager am : indexes.values()) {
for (String indexedColumn : am.getColumnNames()) {
indexedColumn = fixMySqlBackTicks(indexedColumn);
if (indexedColumn.equalsIgnoreCase(oldColumn.name)) {
throw new StatementExecutionException("cannot alter indexed " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'," + "index name is " + am.getIndexName());
}
}
}
}
List<String> columnSpecs = decodeColumnSpecs(cl.getColumnSpecs());
int newType = sqlDataTypeToColumnType(cl.getColDataType().getDataType(), cl.getColDataType().getArgumentsStringList(), columnSpecs);
if (oldColumn.type != newType) {
if (ColumnTypes.isNotNullToNullConversion(oldColumn.type, newType)) {
// allow change from "STRING NOT NULL" to "STRING NULL"
} else if (ColumnTypes.isNullToNotNullConversion(oldColumn.type, newType)) {
// allow change from "STRING NULL" to "STRING NOT NULL"
// it will require a check on table at execution time
} else {
throw new StatementExecutionException("cannot change datatype to " + ColumnTypes.typeToString(newType) + " for column " + columnName + " (" + ColumnTypes.typeToString(oldColumn.type) + ") in table " + tableName + " in tablespace '" + tableSpace + "'");
}
}
if (table.isPrimaryKeyColumn(columnName)) {
boolean new_auto_increment = decodeAutoIncrement(columnSpecs);
if (new_auto_increment && table.primaryKey.length > 1) {
throw new StatementExecutionException("cannot add auto_increment flag to " + cl.getColDataType().getDataType() + " for column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
}
if (table.auto_increment != new_auto_increment) {
changeAutoIncrement = new_auto_increment;
}
}
Bytes newDefault = oldColumn.defaultValue;
if (containsDefaultClause(cl)) {
newDefault = decodeDefaultValue(cl, newType);
}
Column newColumnDef = Column.column(columnName, newType, oldColumn.serialPosition, newDefault);
modifyColumns.add(newColumnDef);
}
}
break;
case CHANGE:
{
String columnName = alterExpression.getColOldName();
List<AlterExpression.ColumnDataType> cols = alterExpression.getColDataTypeList();
if (cols.size() != 1) {
throw new StatementExecutionException("bad CHANGE column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
}
AlterExpression.ColumnDataType cl = cols.get(0);
Column oldColumn = table.getColumn(columnName);
if (oldColumn == null) {
throw new StatementExecutionException("bad column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
}
Map<String, AbstractIndexManager> indexes = tableSpaceManager.getIndexesOnTable(tableName);
if (indexes != null) {
for (AbstractIndexManager am : indexes.values()) {
for (String indexedColumn : am.getColumnNames()) {
indexedColumn = fixMySqlBackTicks(indexedColumn);
if (indexedColumn.equalsIgnoreCase(oldColumn.name)) {
throw new StatementExecutionException("cannot alter indexed " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'," + "index name is " + am.getIndexName());
}
}
}
}
List<String> columnSpecs = decodeColumnSpecs(cl.getColumnSpecs());
int newType = sqlDataTypeToColumnType(cl.getColDataType().getDataType(), cl.getColDataType().getArgumentsStringList(), columnSpecs);
if (oldColumn.type != newType) {
throw new StatementExecutionException("cannot change datatype to " + ColumnTypes.typeToString(newType) + " for column " + columnName + " (" + ColumnTypes.typeToString(oldColumn.type) + ") in table " + tableName + " in tablespace '" + tableSpace + "'");
}
if (table.isPrimaryKeyColumn(columnName)) {
boolean new_auto_increment = decodeAutoIncrement(columnSpecs);
if (new_auto_increment && table.primaryKey.length > 1) {
throw new StatementExecutionException("cannot add auto_increment flag to " + cl.getColDataType().getDataType() + " for column " + columnName + " in table " + tableName + " in tablespace '" + tableSpace + "'");
}
if (table.auto_increment != new_auto_increment) {
changeAutoIncrement = new_auto_increment;
}
}
String renameTo = fixMySqlBackTicks(cl.getColumnName().toLowerCase());
if (renameTo != null) {
columnName = renameTo;
}
Column newColumnDef = Column.column(columnName, newType, oldColumn.serialPosition, oldColumn.defaultValue);
modifyColumns.add(newColumnDef);
}
break;
default:
throw new StatementExecutionException("supported alter operation '" + alter + "'");
}
return new AlterTableStatement(addColumns, modifyColumns, dropColumns, changeAutoIncrement, tableName.toLowerCase(), tableSpace, null, dropForeignKeys, addForeignKeys);
}
use of herddb.model.Table in project herddb by diennea.
the class JSQLParserPlanner method buildSelectStatement.
private ExecutionPlan buildSelectStatement(String defaultTableSpace, int maxRows, Select select, boolean forceScan) throws StatementExecutionException {
checkSupported(select.getWithItemsList() == null);
SelectBody selectBody = select.getSelectBody();
PlannerOp op = buildSelectBody(defaultTableSpace, maxRows, selectBody, forceScan).optimize();
// Simplify Scan to Get
if (!forceScan && op instanceof BindableTableScanOp) {
ScanStatement scanStatement = op.unwrap(ScanStatement.class);
if (scanStatement != null && scanStatement.getPredicate() != null) {
Table tableDef = scanStatement.getTableDef();
CompiledSQLExpression where = scanStatement.getPredicate().unwrap(CompiledSQLExpression.class);
SQLRecordKeyFunction keyFunction = IndexUtils.findIndexAccess(where, tableDef.getPrimaryKey(), tableDef, "=", tableDef);
if (keyFunction == null || !keyFunction.isFullPrimaryKey()) {
throw new StatementExecutionException("unsupported GET not on PK (" + keyFunction + ")");
}
GetStatement get = new GetStatement(scanStatement.getTableSpace(), scanStatement.getTable(), keyFunction, scanStatement.getPredicate(), true);
return ExecutionPlan.simple(get);
}
}
return ExecutionPlan.simple(new SQLPlannedOperationStatement(op), op);
}
use of herddb.model.Table in project herddb by diennea.
the class FileDataStorageManager method readTablespaceStructure.
public static List<Table> readTablespaceStructure(Path file, String tableSpace, LogSequenceNumber sequenceNumber) throws IOException, DataStorageManagerException {
try (InputStream input = new BufferedInputStream(Files.newInputStream(file, StandardOpenOption.READ), 4 * 1024 * 1024);
ExtendedDataInputStream din = new ExtendedDataInputStream(input)) {
// version
long version = din.readVLong();
// flags for future implementations
long flags = din.readVLong();
if (version != 1 || flags != 0) {
throw new DataStorageManagerException("corrupted table list file " + file.toAbsolutePath());
}
String readname = din.readUTF();
if (!readname.equals(tableSpace)) {
throw new DataStorageManagerException("file " + file.toAbsolutePath() + " is not for spablespace " + tableSpace);
}
long ledgerId = din.readZLong();
long offset = din.readZLong();
if (sequenceNumber != null) {
if (ledgerId != sequenceNumber.ledgerId || offset != sequenceNumber.offset) {
throw new DataStorageManagerException("file " + file.toAbsolutePath() + " is not for sequence number " + sequenceNumber);
}
}
int numTables = din.readInt();
List<Table> res = new ArrayList<>();
for (int i = 0; i < numTables; i++) {
byte[] tableData = din.readArray();
Table table = Table.deserialize(tableData);
res.add(table);
}
return Collections.unmodifiableList(res);
}
}
use of herddb.model.Table in project herddb by diennea.
the class FileDataStorageManager method writeTables.
@Override
public Collection<PostCheckpointAction> writeTables(String tableSpace, LogSequenceNumber sequenceNumber, List<Table> tables, List<Index> indexlist, boolean prepareActions) throws DataStorageManagerException {
if (sequenceNumber.isStartOfTime() && !tables.isEmpty()) {
throw new DataStorageManagerException("impossible to write a non empty table list at start-of-time");
}
Path tableSpaceDirectory = getTablespaceDirectory(tableSpace);
try {
Files.createDirectories(tableSpaceDirectory);
Path fileTables = getTablespaceTablesMetadataFile(tableSpace, sequenceNumber);
Path fileIndexes = getTablespaceIndexesMetadataFile(tableSpace, sequenceNumber);
Path parent = getParent(fileTables);
Files.createDirectories(parent);
LOGGER.log(Level.FINE, "writeTables for tableSpace " + tableSpace + " sequenceNumber " + sequenceNumber + " to " + fileTables.toAbsolutePath().toString());
try (ManagedFile file = ManagedFile.open(fileTables, requirefsync);
SimpleBufferedOutputStream buffer = new SimpleBufferedOutputStream(file.getOutputStream(), COPY_BUFFERS_SIZE);
ExtendedDataOutputStream dout = new ExtendedDataOutputStream(buffer)) {
// version
dout.writeVLong(1);
// flags for future implementations
dout.writeVLong(0);
dout.writeUTF(tableSpace);
dout.writeZLong(sequenceNumber.ledgerId);
dout.writeZLong(sequenceNumber.offset);
dout.writeInt(tables.size());
for (Table t : tables) {
byte[] tableSerialized = t.serialize();
dout.writeArray(tableSerialized);
}
dout.flush();
file.sync();
} catch (IOException err) {
throw new DataStorageManagerException(err);
}
try (ManagedFile file = ManagedFile.open(fileIndexes, requirefsync);
SimpleBufferedOutputStream buffer = new SimpleBufferedOutputStream(file.getOutputStream(), COPY_BUFFERS_SIZE);
ExtendedDataOutputStream dout = new ExtendedDataOutputStream(buffer)) {
// version
dout.writeVLong(1);
// flags for future implementations
dout.writeVLong(0);
dout.writeUTF(tableSpace);
dout.writeZLong(sequenceNumber.ledgerId);
dout.writeZLong(sequenceNumber.offset);
if (indexlist != null) {
dout.writeInt(indexlist.size());
for (Index t : indexlist) {
byte[] indexSerialized = t.serialize();
dout.writeArray(indexSerialized);
}
} else {
dout.writeInt(0);
}
dout.flush();
file.sync();
} catch (IOException err) {
throw new DataStorageManagerException(err);
}
} catch (IOException err) {
throw new DataStorageManagerException(err);
}
Collection<PostCheckpointAction> result = new ArrayList<>();
if (prepareActions) {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(tableSpaceDirectory)) {
for (Path p : stream) {
if (isTablespaceIndexesMetadataFile(p)) {
try {
LogSequenceNumber logPositionInFile = readLogSequenceNumberFromIndexMetadataFile(tableSpace, p);
if (sequenceNumber.after(logPositionInFile)) {
LOGGER.log(Level.FINEST, "indexes metadata file " + p.toAbsolutePath() + ". will be deleted after checkpoint end");
result.add(new DeleteFileAction(tableSpace, "indexes", "delete indexesmetadata file " + p.toAbsolutePath(), p));
}
} catch (DataStorageManagerException ignore) {
LOGGER.log(Level.SEVERE, "Unparsable indexesmetadata file " + p.toAbsolutePath(), ignore);
result.add(new DeleteFileAction(tableSpace, "indexes", "delete unparsable indexesmetadata file " + p.toAbsolutePath(), p));
}
} else if (isTablespaceTablesMetadataFile(p)) {
try {
LogSequenceNumber logPositionInFile = readLogSequenceNumberFromTablesMetadataFile(tableSpace, p);
if (sequenceNumber.after(logPositionInFile)) {
LOGGER.log(Level.FINEST, "tables metadata file " + p.toAbsolutePath() + ". will be deleted after checkpoint end");
result.add(new DeleteFileAction(tableSpace, "tables", "delete tablesmetadata file " + p.toAbsolutePath(), p));
}
} catch (DataStorageManagerException ignore) {
LOGGER.log(Level.SEVERE, "Unparsable tablesmetadata file " + p.toAbsolutePath(), ignore);
result.add(new DeleteFileAction(tableSpace, "transactions", "delete unparsable tablesmetadata file " + p.toAbsolutePath(), p));
}
}
}
} catch (IOException err) {
LOGGER.log(Level.SEVERE, "Could not list dir " + tableSpaceDirectory, err);
}
}
return result;
}
use of herddb.model.Table in project herddb by diennea.
the class SortOp method optimize.
@Override
public PlannerOp optimize() {
if (input instanceof BindableTableScanOp) {
BindableTableScanOp op = (BindableTableScanOp) input;
// we can change the statement, this node will be lost and the tablescan too
ScanStatement statement = op.getStatement();
statement.setComparator(this);
if (fields.length == 1 && directions[0]) {
Table tableDef = statement.getTableDef();
if (tableDef.getPrimaryKey().length == 1) {
if (statement.getProjection() != null && statement.getProjection() instanceof ZeroCopyProjection) {
ZeroCopyProjection zeroCopyProjection = (ZeroCopyProjection) statement.getProjection();
int index = zeroCopyProjection.mapPosition(fields[0]);
Column col = tableDef.resolveColumName(index);
if (col.name.equals(tableDef.getPrimaryKey()[0])) {
this.onlyPrimaryKeyAndAscending = true;
}
} else if (statement.getProjection() != null && statement.getProjection() instanceof IdentityProjection) {
Column col = tableDef.resolveColumName(fields[0]);
if (col.name.equals(tableDef.getPrimaryKey()[0])) {
this.onlyPrimaryKeyAndAscending = true;
}
}
}
}
return new SortedBindableTableScanOp(statement);
} else if (input instanceof TableScanOp) {
TableScanOp op = (TableScanOp) input;
// we can change the statement, this node will be lost and the tablescan too
ScanStatement statement = op.getStatement();
statement.setComparator(this);
if (fields.length == 1 && directions[0]) {
Table tableDef = statement.getTableDef();
if (tableDef.getPrimaryKey().length == 1) {
if (statement.getProjection() != null && statement.getProjection() instanceof ZeroCopyProjection) {
ZeroCopyProjection zeroCopyProjection = (ZeroCopyProjection) statement.getProjection();
int index = zeroCopyProjection.mapPosition(fields[0]);
Column col = tableDef.resolveColumName(index);
if (col.name.equals(tableDef.getPrimaryKey()[0])) {
this.onlyPrimaryKeyAndAscending = true;
}
} else if (statement.getProjection() != null && statement.getProjection() instanceof IdentityProjection) {
Column col = tableDef.resolveColumName(fields[0]);
if (col.name.equals(tableDef.getPrimaryKey()[0])) {
this.onlyPrimaryKeyAndAscending = true;
}
}
}
}
return new SortedTableScanOp(statement);
}
return this;
}
Aggregations