/** * @param sql * @param alterTableDef * @return * @throws SqlJetException */ private String getTableAlteredSql(String sql, SqlJetAlterTableDef alterTableDef) throws SqlJetException { final RuleReturnScope parsedSQL = parseTable(sql); final CommonTree ast = (CommonTree) parsedSQL.getTree(); final CommonToken nameToken = (CommonToken) ((CommonTree) ast.getChild(1)).getToken(); final CharStream inputStream = nameToken.getInputStream(); final CommonToken stopToken = (CommonToken) parsedSQL.getStop(); final StringBuilder b = new StringBuilder(); if (alterTableDef.getNewTableName() != null) { b.append(inputStream.substring(0, nameToken.getStartIndex() - 1)); b.append(getAlterTableName(alterTableDef)); b.append(inputStream.substring(nameToken.getStopIndex() + 1, stopToken.getStopIndex())); } else if (alterTableDef.getNewColumnDef() != null) { b.append(inputStream.substring(0, stopToken.getStartIndex() - 1)); b.append(",").append(getAlterTableName(alterTableDef)); b.append(inputStream.substring(stopToken.getStartIndex(), stopToken.getStopIndex())); } else { throw new SqlJetException("Wrong ALTER TABLE statement"); } return b.toString(); }
/** * @param tableName * @param newTableName * @param newColumnDef * @return * @throws SqlJetException */ private ISqlJetTableDef alterTableSafe(final SqlJetAlterTableDef alterTableDef) throws SqlJetException { assert (null != alterTableDef); String tableName = alterTableDef.getTableName(); String newTableName = alterTableDef.getNewTableName(); ISqlJetColumnDef newColumnDef = alterTableDef.getNewColumnDef(); if (null == tableName) { throw new SqlJetException(SqlJetErrorCode.MISUSE, "Table name isn't defined"); } if (null == newTableName && null == newColumnDef) { throw new SqlJetException(SqlJetErrorCode.MISUSE, "Not defined any altering"); } boolean renameTable = false; if (null != newTableName) { renameTable = true; } else { newTableName = tableName; } if (renameTable && tableDefs.containsKey(newTableName)) { throw new SqlJetException( SqlJetErrorCode.MISUSE, String.format("Table \"%s\" already exists", newTableName)); } final SqlJetTableDef tableDef = (SqlJetTableDef) tableDefs.get(tableName); if (null == tableDef) { throw new SqlJetException( SqlJetErrorCode.MISUSE, String.format("Table \"%s\" not found", tableName)); } List<ISqlJetColumnDef> columns = tableDef.getColumns(); if (null != newColumnDef) { final String fieldName = newColumnDef.getName(); if (tableDef.getColumn(fieldName) != null) { throw new SqlJetException( SqlJetErrorCode.MISUSE, String.format("Field \"%s\" already exists in table \"%s\"", fieldName, tableName)); } final List<ISqlJetColumnConstraint> constraints = newColumnDef.getConstraints(); if (null != constraints && 0 != constraints.size()) { boolean notNull = false; boolean defaultValue = false; for (final ISqlJetColumnConstraint constraint : constraints) { if (constraint instanceof ISqlJetColumnNotNull) { notNull = true; } else if (constraint instanceof ISqlJetColumnDefault) { defaultValue = true; } else { throw new SqlJetException( SqlJetErrorCode.MISUSE, String.format("Invalid constraint: %s", constraint.toString())); } } if (notNull && !defaultValue) { throw new SqlJetException( SqlJetErrorCode.MISUSE, "NOT NULL requires to have DEFAULT value"); } } columns = new ArrayList<ISqlJetColumnDef>(columns); columns.add(newColumnDef); } final int page = tableDef.getPage(); final long rowId = tableDef.getRowId(); final SqlJetTableDef alterDef = new SqlJetTableDef( newTableName, null, tableDef.isTemporary(), false, columns, tableDef.getConstraints(), page, rowId); final ISqlJetBtreeSchemaTable schemaTable = openSchemaTable(true); try { schemaTable.lock(); try { if (!schemaTable.goToRow(rowId)) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } final String typeField = schemaTable.getTypeField(); final String nameField = schemaTable.getNameField(); final String tableField = schemaTable.getTableField(); final int pageField = schemaTable.getPageField(); if (null == typeField || !TABLE_TYPE.equals(typeField)) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } if (null == nameField || !tableName.equals(nameField)) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } if (null == tableField || !tableName.equals(tableField)) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } if (0 == pageField || pageField != page) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } final String alteredSql = getTableAlteredSql(schemaTable.getSqlField(), alterTableDef); db.getOptions().changeSchemaVersion(); schemaTable.insertRecord(TABLE_TYPE, newTableName, newTableName, page, alteredSql); if (renameTable && !tableName.equals(newTableName)) { renameTablesIndices( schemaTable, tableName, newTableName, getAlterTableName(alterTableDef)); } tableDefs.remove(tableName); tableDefs.put(newTableName, alterDef); return alterDef; } finally { schemaTable.unlock(); } } finally { schemaTable.close(); } }