private void readShema(ISqlJetBtreeSchemaTable table) throws SqlJetException { for (table.first(); !table.eof(); table.next()) { final String type = table.getTypeField(); if (null == type) { continue; } final String name = table.getNameField(); if (null == name) { continue; } final int page = table.getPageField(); if (TABLE_TYPE.equals(type)) { String sql = table.getSqlField(); // System.err.println(sql); final CommonTree ast = (CommonTree) parseTable(sql).getTree(); if (!isCreateVirtualTable(ast)) { final SqlJetTableDef tableDef = new SqlJetTableDef(ast, page); if (!name.equals(tableDef.getName())) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } tableDef.setRowId(table.getRowId()); tableDefs.put(name, tableDef); } else { final SqlJetVirtualTableDef virtualTableDef = new SqlJetVirtualTableDef(ast, page); if (!name.equals(virtualTableDef.getTableName())) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } virtualTableDef.setRowId(table.getRowId()); virtualTableDefs.put(name, virtualTableDef); } } else if (INDEX_TYPE.equals(type)) { final String tableName = table.getTableField(); final String sql = table.getSqlField(); if (null != sql) { // System.err.println(sql); final CommonTree ast = (CommonTree) parseIndex(sql).getTree(); final SqlJetIndexDef indexDef = new SqlJetIndexDef(ast, page); if (!name.equals(indexDef.getName())) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } if (!tableName.equals(indexDef.getTableName())) { throw new SqlJetException(SqlJetErrorCode.CORRUPT); } indexDef.setRowId(table.getRowId()); indexDefs.put(name, indexDef); } else { SqlJetBaseIndexDef indexDef = new SqlJetBaseIndexDef(name, tableName, page); indexDef.setRowId(table.getRowId()); indexDefs.put(name, indexDef); } } } bindIndexes(); }
public SqlJetViewDef(String sql, CommonTree ast) { CommonTree optionsNode = (CommonTree) ast.getChild(0); sqlStatement = sql; temporary = SqlJetTableDef.hasOption(optionsNode, "temporary"); ifNotExists = SqlJetTableDef.hasOption(optionsNode, "exists"); CommonTree nameNode = (CommonTree) ast.getChild(1); name = nameNode.getText(); databaseName = nameNode.getChildCount() > 0 ? nameNode.getChild(0).getText() : null; }
/** * @param schemaTable * @param tableDef * @throws SqlJetException */ private void addConstraints(ISqlJetBtreeSchemaTable schemaTable, final SqlJetTableDef tableDef) throws SqlJetException { final String tableName = tableDef.getName(); final List<ISqlJetColumnDef> columns = tableDef.getColumns(); int i = 0; for (final ISqlJetColumnDef column : columns) { final List<ISqlJetColumnConstraint> constraints = column.getConstraints(); if (null == constraints) continue; for (final ISqlJetColumnConstraint constraint : constraints) { if (constraint instanceof ISqlJetColumnPrimaryKey) { final ISqlJetColumnPrimaryKey pk = (ISqlJetColumnPrimaryKey) constraint; if (!column.hasExactlyIntegerType()) { if (pk.isAutoincremented()) { throw new SqlJetException( SqlJetErrorCode.ERROR, "AUTOINCREMENT is allowed only for INTEGER PRIMARY KEY fields"); } createAutoIndex(schemaTable, tableName, generateAutoIndexName(tableName, ++i)); } else if (pk.isAutoincremented()) { checkSequenceTable(); } } else if (constraint instanceof ISqlJetColumnUnique) { createAutoIndex(schemaTable, tableName, generateAutoIndexName(tableName, ++i)); } } } final List<ISqlJetTableConstraint> constraints = tableDef.getConstraints(); if (null != constraints) { for (final ISqlJetTableConstraint constraint : constraints) { if (constraint instanceof ISqlJetTablePrimaryKey) { boolean b = false; final ISqlJetTablePrimaryKey pk = (ISqlJetTablePrimaryKey) constraint; if (pk.getColumns().size() == 1) { final String n = pk.getColumns().get(0); final ISqlJetColumnDef c = tableDef.getColumn(n); b = c != null && c.hasExactlyIntegerType(); } if (!b) { createAutoIndex(schemaTable, tableName, generateAutoIndexName(tableName, ++i)); } } else if (constraint instanceof ISqlJetTableUnique) { createAutoIndex(schemaTable, tableName, generateAutoIndexName(tableName, ++i)); } } } }
private void dropTableSafe(String tableName) throws SqlJetException { if (null == tableName || "".equals(tableName)) throw new SqlJetException(SqlJetErrorCode.MISUSE, "Table name must be not empty"); if (!tableDefs.containsKey(tableName)) throw new SqlJetException(SqlJetErrorCode.MISUSE, "Table not found: " + tableName); final SqlJetTableDef tableDef = (SqlJetTableDef) tableDefs.get(tableName); dropTableIndexes(tableDef); final ISqlJetBtreeSchemaTable schemaTable = openSchemaTable(true); try { schemaTable.lock(); try { db.getOptions().changeSchemaVersion(); if (!schemaTable.goToRow(tableDef.getRowId()) || !TABLE_TYPE.equals(schemaTable.getTypeField())) throw new SqlJetException(SqlJetErrorCode.CORRUPT); final String n = schemaTable.getNameField(); if (null == n || !tableName.equals(n)) throw new SqlJetException(SqlJetErrorCode.CORRUPT); schemaTable.delete(); } finally { schemaTable.unlock(); } } finally { schemaTable.close(); } final int page = tableDef.getPage(); final int moved = btree.dropTable(page); if (moved != 0) { movePage(page, moved); } tableDefs.remove(tableName); }
/** * @param schemaTable * @param tableDef * @throws SqlJetException */ private void dropTableIndexes(SqlJetTableDef tableDef) throws SqlJetException { final String tableName = tableDef.getName(); final Iterator<Map.Entry<String, ISqlJetIndexDef>> iterator = indexDefs.entrySet().iterator(); while (iterator.hasNext()) { final Map.Entry<String, ISqlJetIndexDef> indexDefEntry = iterator.next(); final String indexName = indexDefEntry.getKey(); final ISqlJetIndexDef indexDef = indexDefEntry.getValue(); if (indexDef.getTableName().equals(tableName)) { if (doDropIndex(indexName, true, false)) { iterator.remove(); } } } }
/** * @param page * @param moved * @throws SqlJetException */ private void movePage(final int page, final int moved) throws SqlJetException { final ISqlJetBtreeSchemaTable schemaTable = openSchemaTable(true); try { schemaTable.lock(); try { for (schemaTable.first(); !schemaTable.eof(); schemaTable.next()) { final long pageField = schemaTable.getPageField(); if (pageField == moved) { final String nameField = schemaTable.getNameField(); schemaTable.updateRecord( schemaTable.getRowId(), schemaTable.getTypeField(), nameField, schemaTable.getTableField(), page, schemaTable.getSqlField()); final ISqlJetIndexDef index = getIndex(nameField); if (index != null) { if (index instanceof SqlJetBaseIndexDef) { ((SqlJetBaseIndexDef) index).setPage(page); } } else { final ISqlJetTableDef table = getTable(nameField); if (table != null) { if (table instanceof SqlJetTableDef) { ((SqlJetTableDef) table).setPage(page); } } } return; } } } finally { schemaTable.unlock(); } } finally { schemaTable.close(); } }
/** * @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(); } }
private ISqlJetTableDef createTableSafe(String sql, boolean internal) throws SqlJetException { final RuleReturnScope parseTable = parseTable(sql); final CommonTree ast = (CommonTree) parseTable.getTree(); if (isCreateVirtualTable(ast)) { throw new SqlJetException(SqlJetErrorCode.ERROR); } final SqlJetTableDef tableDef = new SqlJetTableDef(ast, 0); if (null == tableDef.getName()) throw new SqlJetException(SqlJetErrorCode.ERROR); final String tableName = tableDef.getName(); if ("".equals(tableName)) throw new SqlJetException(SqlJetErrorCode.ERROR); if (!internal) { checkNameReserved(tableName); } if (tableDefs.containsKey(tableName)) { if (tableDef.isKeepExisting()) { return tableDefs.get(tableName); } else { throw new SqlJetException( SqlJetErrorCode.ERROR, "Table \"" + tableName + "\" exists already"); } } checkNameConflict(SqlJetSchemaObjectType.TABLE, tableName); checkFieldNamesRepeatsConflict(tableDef.getName(), tableDef.getColumns()); final List<ISqlJetColumnDef> columns = tableDef.getColumns(); if (null == columns || 0 == columns.size()) throw new SqlJetException(SqlJetErrorCode.ERROR); final String createTableSql = getCreateTableSql(parseTable); final ISqlJetBtreeSchemaTable schemaTable = openSchemaTable(true); try { schemaTable.lock(); try { db.getOptions().changeSchemaVersion(); final int page = btree.createTable(BTREE_CREATE_TABLE_FLAGS); final long rowId = schemaTable.insertRecord(TABLE_TYPE, tableName, tableName, page, createTableSql); addConstraints(schemaTable, tableDef); tableDef.setPage(page); tableDef.setRowId(rowId); tableDefs.put(tableName, tableDef); return tableDef; } finally { schemaTable.unlock(); } } finally { schemaTable.close(); } }