/** * Update a list of rows in this table. * * @param prepared the prepared statement * @param session the session * @param rows a list of row pairs of the form old row, new row, old row, new row,... */ public void updateRows(Prepared prepared, Session session, RowList rows) { // in case we need to undo the update int rollback = session.getUndoLogPos(); // remove the old rows int rowScanCount = 0; for (rows.reset(); rows.hasNext(); ) { if ((++rowScanCount & 127) == 0) { prepared.checkCanceled(); } Row o = rows.next(); rows.next(); removeRow(session, o); session.log(this, UndoLogRecord.DELETE, o); } // add the new rows for (rows.reset(); rows.hasNext(); ) { if ((++rowScanCount & 127) == 0) { prepared.checkCanceled(); } rows.next(); Row n = rows.next(); try { addRow(session, n); } catch (DbException e) { if (e.getErrorCode() == ErrorCode.CONCURRENT_UPDATE_1) { session.rollbackTo(rollback, false); } throw e; } session.log(this, UndoLogRecord.INSERT, n); } }
public void prepare() { if (columns == null) { if (list.size() > 0 && list.get(0).length == 0) { // special case where table is used as a sequence columns = new Column[0]; } else { columns = table.getColumns(); } } if (list.size() > 0) { for (Expression[] expr : list) { if (expr.length != columns.length) { throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH); } for (int i = 0; i < expr.length; i++) { Expression e = expr[i]; if (e != null) { expr[i] = e.optimize(session); } } } } else { query.prepare(); if (query.getColumnCount() != columns.length) { throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH); } } if (keys == null) { Index idx = table.getPrimaryKey(); if (idx == null) { throw DbException.get(ErrorCode.CONSTRAINT_NOT_FOUND_1, "PRIMARY KEY"); } keys = idx.getColumns(); } StatementBuilder buff = new StatementBuilder("UPDATE "); buff.append(table.getSQL()).append(" SET "); for (Column c : columns) { buff.appendExceptFirst(", "); buff.append(c.getSQL()).append("=?"); } buff.append(" WHERE "); buff.resetCount(); for (Column c : keys) { buff.appendExceptFirst(" AND "); buff.append(c.getSQL()).append("=?"); } String sql = buff.toString(); update = session.prepare(sql); }
public Index getPrimaryKey() { Index index = findPrimaryKey(); if (index != null) { return index; } throw DbException.get(ErrorCode.INDEX_NOT_FOUND_1, Constants.PREFIX_PRIMARY_KEY); }
/** * Get the column with the given name. * * @param columnName the column name * @return the column * @throws DbException if the column was not found */ public Column getColumn(String columnName) { Column column = columnMap.get(columnName); if (column == null) { throw DbException.get(ErrorCode.COLUMN_NOT_FOUND_1, columnName); } return column; }
FunctionCursorResultSet(Session session, ResultSet result) { this.session = session; this.result = result; try { this.meta = result.getMetaData(); } catch (SQLException e) { throw DbException.convert(e); } }
/** * Check that this column is not referenced by a multi-column constraint or multi-column index. If * it is, an exception is thrown. Single-column references and indexes are dropped. * * @param session the session * @param col the column * @throws DbException if the column is referenced by multi-column constraints or indexes */ public void dropSingleColumnConstraintsAndIndexes(Session session, Column col) { ArrayList<Constraint> constraintsToDrop = New.arrayList(); if (constraints != null) { for (int i = 0, size = constraints.size(); i < size; i++) { Constraint constraint = constraints.get(i); HashSet<Column> columns = constraint.getReferencedColumns(this); if (!columns.contains(col)) { continue; } if (columns.size() == 1) { constraintsToDrop.add(constraint); } else { throw DbException.get(ErrorCode.COLUMN_IS_REFERENCED_1, constraint.getSQL()); } } } ArrayList<Index> indexesToDrop = New.arrayList(); ArrayList<Index> indexes = getIndexes(); if (indexes != null) { for (int i = 0, size = indexes.size(); i < size; i++) { Index index = indexes.get(i); if (index.getCreateSQL() == null) { continue; } if (index.getColumnIndex(col) < 0) { continue; } if (index.getColumns().length == 1) { indexesToDrop.add(index); } else { throw DbException.get(ErrorCode.COLUMN_IS_REFERENCED_1, index.getSQL()); } } } for (Constraint c : constraintsToDrop) { session.getDatabase().removeSchemaObject(session, c); } for (Index i : indexesToDrop) { // the index may already have been dropped when dropping the constraint if (getIndexes().contains(i)) { session.getDatabase().removeSchemaObject(session, i); } } }
private void setColumnsInternal(Column[] columns, boolean check) { this.columns = columns; if (columnMap.size() > 0) { columnMap.clear(); } for (int i = 0; i < columns.length; i++) { Column col = columns[i]; int dataType = col.getType(); if (check && dataType == Value.UNKNOWN) { throw DbException.get(ErrorCode.UNKNOWN_DATA_TYPE_1, col.getSQL()); } col.setTable(this, i); String columnName = col.getFullName(); if (columnMap.get(columnName) != null) { throw DbException.get(ErrorCode.DUPLICATE_COLUMN_NAME_1, columnName); } columnMap.put(columnName, col); } }
private int getRedoPos() { try { byte[] data = ZKUtil.getDataAndWatch(watcher, ZooKeeperAdmin.DDL_REDO_TABLE_NODE); if (data != null && data.length > 0) { return Bytes.toInt(data); } return getDefaultStartPos(); } catch (Exception e) { throw DbException.convert(e); } }
/** * Rename a column of this table. * * @param column the column to rename * @param newName the new column name */ public void renameColumn(Column column, String newName) { for (Column c : columns) { if (c == column) { continue; } if (c.getName().equals(newName)) { throw DbException.get(ErrorCode.DUPLICATE_COLUMN_NAME_1, newName); } } columnMap.remove(column.getName()); column.rename(newName); columnMap.put(newName, column); }
@Override public int update() { session.commit(true); Database db = session.getDatabase(); Schema schema = oldIndex.getSchema(); if (schema.findIndex(session, newIndexName) != null || newIndexName.equals(oldIndex.getName())) { throw DbException.get(ErrorCode.INDEX_ALREADY_EXISTS_1, newIndexName); } session.getUser().checkRight(oldIndex.getTable(), Right.ALL); db.renameSchemaObject(session, oldIndex, newIndexName); return 0; }
private int getConstraintTypeOrder() { String constraintType = getConstraintType(); if (CHECK.equals(constraintType)) { return 0; } else if (PRIMARY_KEY.equals(constraintType)) { return 1; } else if (UNIQUE.equals(constraintType)) { return 2; } else if (REFERENTIAL.equals(constraintType)) { return 3; } else { throw DbException.throwInternalError("type: " + constraintType); } }
private void merge(Row row) { ArrayList<Parameter> k = update.getParameters(); for (int i = 0; i < columns.length; i++) { Column col = columns[i]; Value v = row.getValue(col.getColumnId()); Parameter p = k.get(i); p.setValue(v); } for (int i = 0; i < keys.length; i++) { Column col = keys[i]; Value v = row.getValue(col.getColumnId()); if (v == null) { throw DbException.get(ErrorCode.COLUMN_CONTAINS_NULL_VALUES_1, col.getSQL()); } Parameter p = k.get(columns.length + i); p.setValue(v); } int count = update.update(); if (count == 0) { try { table.validateConvertUpdateSequence(session, row); boolean done = table.fireBeforeRow(session, null, row); if (!done) { table.lock(session, true, false); table.addRow(session, row); session.log(table, UndoLogRecord.INSERT, row); table.fireAfterRow(session, null, row, false); } } catch (DbException e) { if (e.getErrorCode() == ErrorCode.DUPLICATE_KEY_1) { // possibly a concurrent merge or insert Index index = (Index) e.getSource(); if (index != null) { // verify the index columns match the key Column[] indexColumns = index.getColumns(); boolean indexMatchesKeys = false; if (indexColumns.length <= keys.length) { for (int i = 0; i < indexColumns.length; i++) { if (indexColumns[i] != keys[i]) { indexMatchesKeys = false; break; } } } if (indexMatchesKeys) { throw DbException.get(ErrorCode.CONCURRENT_UPDATE_1, table.getName()); } } } throw e; } } else if (count != 1) { throw DbException.get(ErrorCode.DUPLICATE_KEY_1, table.getSQL()); } }
public synchronized void refresh() { int newRedoPos = getRedoPos(); if (newRedoPos != redoPos) { int startPos = redoPos; int stopPos = newRedoPos; if (newRedoPos < startPos) { // Master重新计数了 startPos = getDefaultStartPos(); } try { table.redoRecords(startPos, stopPos); redoPos = newRedoPos; } catch (Exception e) { throw DbException.convert(e); } } }
private int execute(Prepared p) { beginTransaction(p); boolean isTopTransaction = false; boolean isNestedTransaction = false; Session session = p.getSession(); try { if (!p.isLocal() && p.isBatch()) { if (session.isAutoCommit()) { session.setAutoCommit(false); isTopTransaction = true; } else { isNestedTransaction = true; session.addSavepoint(TransactionCommand.INTERNAL_SAVEPOINT); } } int updateCount = 0; switch (p.getType()) { case CommandInterface.INSERT: updateCount = nestedRouter.executeInsert((Insert) p); break; case CommandInterface.UPDATE: updateCount = nestedRouter.executeUpdate((Update) p); break; case CommandInterface.DELETE: updateCount = nestedRouter.executeDelete((Delete) p); break; case CommandInterface.MERGE: updateCount = nestedRouter.executeMerge((Merge) p); break; } if (isTopTransaction) session.commit(false); return updateCount; } catch (Exception e) { if (isTopTransaction) session.rollback(); // 嵌套事务出错时提前rollback if (isNestedTransaction) session.rollbackToSavepoint(TransactionCommand.INTERNAL_SAVEPOINT); throw DbException.convert(e); } finally { if (isTopTransaction) session.setAutoCommit(true); } }
public boolean next() { row = null; try { if (result != null && result.next()) { int columnCount = meta.getColumnCount(); values = new Value[columnCount]; for (int i = 0; i < columnCount; i++) { int type = DataType.convertSQLTypeToValueType(meta.getColumnType(i + 1)); values[i] = DataType.readValue(session, result, i + 1, type); } } else { values = null; } } catch (SQLException e) { throw DbException.convert(e); } return values != null; }
/** * Try to execute the statement. * * @return the update count */ private int tryUpdate() { if (!transactional) { session.commit(true); } Database db = session.getDatabase(); Table table = getSchema().getTableOrView(session, tableName); if (getSchema().findConstraint(session, constraintName) != null) { if (ifNotExists) { return 0; } throw DbException.get(ErrorCode.CONSTRAINT_ALREADY_EXISTS_1, constraintName); } session.getUser().checkRight(table, Right.ALL); db.lockMeta(session); table.lock(session, true, true); Constraint constraint; switch (type) { case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_PRIMARY_KEY: { IndexColumn.mapColumns(indexColumns, table); index = table.findPrimaryKey(); ArrayList<Constraint> constraints = table.getConstraints(); for (int i = 0; constraints != null && i < constraints.size(); i++) { Constraint c = constraints.get(i); if (Constraint.PRIMARY_KEY.equals(c.getConstraintType())) { throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY); } } if (index != null) { // if there is an index, it must match with the one declared // we don't test ascending / descending IndexColumn[] pkCols = index.getIndexColumns(); if (pkCols.length != indexColumns.length) { throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY); } for (int i = 0; i < pkCols.length; i++) { if (pkCols[i].column != indexColumns[i].column) { throw DbException.get(ErrorCode.SECOND_PRIMARY_KEY); } } } if (index == null) { IndexType indexType = IndexType.createPrimaryKey(table.isPersistIndexes(), primaryKeyHash); String indexName = table.getSchema().getUniqueIndexName(session, table, Constants.PREFIX_PRIMARY_KEY); int id = getObjectId(); try { index = table.addIndex(session, indexName, id, indexColumns, indexType, true, null); } finally { getSchema().freeUniqueName(indexName); } } index.getIndexType().setBelongsToConstraint(true); int constraintId = getObjectId(); String name = generateConstraintName(table); ConstraintUnique pk = new ConstraintUnique(getSchema(), constraintId, name, table, true); pk.setColumns(indexColumns); pk.setIndex(index, true); constraint = pk; break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_UNIQUE: { IndexColumn.mapColumns(indexColumns, table); boolean isOwner = false; if (index != null && canUseUniqueIndex(index, table, indexColumns)) { isOwner = true; index.getIndexType().setBelongsToConstraint(true); } else { index = getUniqueIndex(table, indexColumns); if (index == null) { index = createIndex(table, indexColumns, true); isOwner = true; } } int id = getObjectId(); String name = generateConstraintName(table); ConstraintUnique unique = new ConstraintUnique(getSchema(), id, name, table, false); unique.setColumns(indexColumns); unique.setIndex(index, isOwner); constraint = unique; break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_CHECK: { int id = getObjectId(); String name = generateConstraintName(table); ConstraintCheck check = new ConstraintCheck(getSchema(), id, name, table); TableFilter filter = new TableFilter(session, table, null, false, null); checkExpression.mapColumns(filter, 0); checkExpression = checkExpression.optimize(session); check.setExpression(checkExpression); check.setTableFilter(filter); constraint = check; if (checkExisting) { check.checkExistingData(session); } break; } case CommandInterface.ALTER_TABLE_ADD_CONSTRAINT_REFERENTIAL: { Table refTable = refSchema.getTableOrView(session, refTableName); session.getUser().checkRight(refTable, Right.ALL); if (!refTable.canReference()) { throw DbException.get( ErrorCode.FEATURE_NOT_SUPPORTED_1, "Reference " + refTable.getSQL()); } boolean isOwner = false; IndexColumn.mapColumns(indexColumns, table); if (index != null && canUseIndex(index, table, indexColumns)) { isOwner = true; index.getIndexType().setBelongsToConstraint(true); } else { index = getIndex(table, indexColumns); if (index == null) { index = createIndex(table, indexColumns, false); isOwner = true; } } if (refIndexColumns == null) { Index refIdx = refTable.getPrimaryKey(); refIndexColumns = refIdx.getIndexColumns(); } else { IndexColumn.mapColumns(refIndexColumns, refTable); } if (refIndexColumns.length != indexColumns.length) { throw DbException.get(ErrorCode.COLUMN_COUNT_DOES_NOT_MATCH); } boolean isRefOwner = false; if (refIndex != null && refIndex.getTable() == refTable && canUseIndex(refIndex, refTable, refIndexColumns)) { isRefOwner = true; refIndex.getIndexType().setBelongsToConstraint(true); } else { refIndex = null; } if (refIndex == null) { refIndex = getIndex(refTable, refIndexColumns); if (refIndex == null) { refIndex = createIndex(refTable, refIndexColumns, true); isRefOwner = true; } } int id = getObjectId(); String name = generateConstraintName(table); ConstraintReferential ref = new ConstraintReferential(getSchema(), id, name, table); ref.setColumns(indexColumns); ref.setIndex(index, isOwner); ref.setRefTable(refTable); ref.setRefColumns(refIndexColumns); ref.setRefIndex(refIndex, isRefOwner); if (checkExisting) { ref.checkExistingData(session); } constraint = ref; refTable.addConstraint(constraint); ref.setDeleteAction(deleteAction); ref.setUpdateAction(updateAction); break; } default: throw DbException.throwInternalError("type=" + type); } // parent relationship is already set with addConstraint constraint.setComment(comment); if (table.isTemporary() && !table.isGlobalTemporary()) { session.addLocalTempTableConstraint(constraint); } else { db.addSchemaObject(session, constraint); } table.addConstraint(constraint); return 0; }
private int writeLobStream(Value v) throws IOException { if (!tempLobTableCreated) { add( "CREATE TABLE IF NOT EXISTS SYSTEM_LOB_STREAM" + "(ID INT NOT NULL, PART INT NOT NULL, CDATA VARCHAR, BDATA BINARY)", true); add( "CREATE PRIMARY KEY SYSTEM_LOB_STREAM_PRIMARY_KEY " + "ON SYSTEM_LOB_STREAM(ID, PART)", true); add( "CREATE ALIAS IF NOT EXISTS " + "SYSTEM_COMBINE_CLOB FOR \"" + this.getClass().getName() + ".combineClob\"", true); add( "CREATE ALIAS IF NOT EXISTS " + "SYSTEM_COMBINE_BLOB FOR \"" + this.getClass().getName() + ".combineBlob\"", true); tempLobTableCreated = true; } int id = nextLobId++; switch (v.getType()) { case Value.BLOB: { byte[] bytes = new byte[lobBlockSize]; InputStream input = v.getInputStream(); try { for (int i = 0; ; i++) { StringBuilder buff = new StringBuilder(lobBlockSize * 2); buff.append("INSERT INTO SYSTEM_LOB_STREAM VALUES(" + id + ", " + i + ", NULL, '"); int len = IOUtils.readFully(input, bytes, lobBlockSize); if (len <= 0) { break; } buff.append(StringUtils.convertBytesToHex(bytes, len)).append("')"); String sql = buff.toString(); add(sql, true); } } finally { IOUtils.closeSilently(input); } break; } case Value.CLOB: { char[] chars = new char[lobBlockSize]; Reader reader = v.getReader(); try { for (int i = 0; ; i++) { StringBuilder buff = new StringBuilder(lobBlockSize * 2); buff.append("INSERT INTO SYSTEM_LOB_STREAM VALUES(" + id + ", " + i + ", "); int len = IOUtils.readFully(reader, chars, lobBlockSize); if (len < 0) { break; } buff.append(StringUtils.quoteStringSQL(new String(chars, 0, len))).append(", NULL)"); String sql = buff.toString(); add(sql, true); } } finally { IOUtils.closeSilently(reader); } break; } default: DbException.throwInternalError("type:" + v.getType()); } return id; }
@Override public ResultInterface query(int maxrows) { session.getUser().checkAdmin(); reset(); Database db = session.getDatabase(); if (schemaNames != null) { for (String schemaName : schemaNames) { Schema schema = db.findSchema(schemaName); if (schema == null) { throw DbException.get(ErrorCode.SCHEMA_NOT_FOUND_1, schemaName); } } } try { result = createResult(); deleteStore(); openOutput(); if (out != null) { buffer = new byte[Constants.IO_BUFFER_SIZE]; } if (settings) { for (Setting setting : db.getAllSettings()) { if (setting.getName().equals(SetTypes.getTypeName(SetTypes.CREATE_BUILD))) { // don't add CREATE_BUILD to the script // (it is only set when creating the database) continue; } add(setting.getCreateSQL(), false); } } if (out != null) { add("", true); } for (User user : db.getAllUsers()) { add(user.getCreateSQL(passwords), false); } for (Role role : db.getAllRoles()) { add(role.getCreateSQL(true), false); } for (Schema schema : db.getAllSchemas()) { if (excludeSchema(schema)) { continue; } add(schema.getCreateSQL(), false); } for (UserDataType datatype : db.getAllUserDataTypes()) { if (drop) { add(datatype.getDropSQL(), false); } add(datatype.getCreateSQL(), false); } for (SchemaObject obj : db.getAllSchemaObjects(DbObject.CONSTANT)) { if (excludeSchema(obj.getSchema())) { continue; } Constant constant = (Constant) obj; add(constant.getCreateSQL(), false); } final ArrayList<Table> tables = db.getAllTablesAndViews(false); // sort by id, so that views are after tables and views on views // after the base views Collections.sort( tables, new Comparator<Table>() { @Override public int compare(Table t1, Table t2) { return t1.getId() - t2.getId(); } }); // Generate the DROP XXX ... IF EXISTS for (Table table : tables) { if (excludeSchema(table.getSchema())) { continue; } if (excludeTable(table)) { continue; } if (table.isHidden()) { continue; } table.lock(session, false, false); String sql = table.getCreateSQL(); if (sql == null) { // null for metadata tables continue; } if (drop) { add(table.getDropSQL(), false); } } for (SchemaObject obj : db.getAllSchemaObjects(DbObject.FUNCTION_ALIAS)) { if (excludeSchema(obj.getSchema())) { continue; } if (drop) { add(obj.getDropSQL(), false); } add(obj.getCreateSQL(), false); } for (UserAggregate agg : db.getAllAggregates()) { if (drop) { add(agg.getDropSQL(), false); } add(agg.getCreateSQL(), false); } for (SchemaObject obj : db.getAllSchemaObjects(DbObject.SEQUENCE)) { if (excludeSchema(obj.getSchema())) { continue; } Sequence sequence = (Sequence) obj; if (drop) { add(sequence.getDropSQL(), false); } add(sequence.getCreateSQL(), false); } // Generate CREATE TABLE and INSERT...VALUES int count = 0; for (Table table : tables) { if (excludeSchema(table.getSchema())) { continue; } if (excludeTable(table)) { continue; } if (table.isHidden()) { continue; } table.lock(session, false, false); String createTableSql = table.getCreateSQL(); if (createTableSql == null) { // null for metadata tables continue; } final String tableType = table.getTableType(); add(createTableSql, false); final ArrayList<Constraint> constraints = table.getConstraints(); if (constraints != null) { for (Constraint constraint : constraints) { if (Constraint.PRIMARY_KEY.equals(constraint.getConstraintType())) { add(constraint.getCreateSQLWithoutIndexes(), false); } } } if (Table.TABLE.equals(tableType)) { if (table.canGetRowCount()) { String rowcount = "-- " + table.getRowCountApproximation() + " +/- SELECT COUNT(*) FROM " + table.getSQL(); add(rowcount, false); } if (data) { count = generateInsertValues(count, table); } } final ArrayList<Index> indexes = table.getIndexes(); for (int j = 0; indexes != null && j < indexes.size(); j++) { Index index = indexes.get(j); if (!index.getIndexType().getBelongsToConstraint()) { add(index.getCreateSQL(), false); } } } if (tempLobTableCreated) { add("DROP TABLE IF EXISTS SYSTEM_LOB_STREAM", true); add("CALL SYSTEM_COMBINE_BLOB(-1)", true); add("DROP ALIAS IF EXISTS SYSTEM_COMBINE_CLOB", true); add("DROP ALIAS IF EXISTS SYSTEM_COMBINE_BLOB", true); tempLobTableCreated = false; } // Generate CREATE CONSTRAINT ... final ArrayList<SchemaObject> constraints = db.getAllSchemaObjects(DbObject.CONSTRAINT); Collections.sort( constraints, new Comparator<SchemaObject>() { @Override public int compare(SchemaObject c1, SchemaObject c2) { return ((Constraint) c1).compareTo((Constraint) c2); } }); for (SchemaObject obj : constraints) { if (excludeSchema(obj.getSchema())) { continue; } Constraint constraint = (Constraint) obj; if (excludeTable(constraint.getTable())) { continue; } if (constraint.getTable().isHidden()) { continue; } if (!Constraint.PRIMARY_KEY.equals(constraint.getConstraintType())) { add(constraint.getCreateSQLWithoutIndexes(), false); } } // Generate CREATE TRIGGER ... for (SchemaObject obj : db.getAllSchemaObjects(DbObject.TRIGGER)) { if (excludeSchema(obj.getSchema())) { continue; } TriggerObject trigger = (TriggerObject) obj; if (excludeTable(trigger.getTable())) { continue; } add(trigger.getCreateSQL(), false); } // Generate GRANT ... for (Right right : db.getAllRights()) { Table table = right.getGrantedTable(); if (table != null) { if (excludeSchema(table.getSchema())) { continue; } if (excludeTable(table)) { continue; } } add(right.getCreateSQL(), false); } // Generate COMMENT ON ... for (Comment comment : db.getAllComments()) { add(comment.getCreateSQL(), false); } if (out != null) { out.close(); } } catch (IOException e) { throw DbException.convertIOException(e, getFileName()); } finally { closeIO(); } result.done(); LocalResult r = result; reset(); return r; }
public boolean previous() { throw DbException.throwInternalError(); }
public String getCreateSQLForCopy(Table table, String quotedName) { throw DbException.throwInternalError(); }
@Override protected void checkParameterCount(int len) { if (len < 1) { throw DbException.get(ErrorCode.INVALID_PARAMETER_COUNT_2, getName(), ">0"); } }