Пример #1
0
 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());
   }
 }
Пример #2
0
 /**
  * Remove the given index from the list.
  *
  * @param index the index to remove
  */
 public void removeIndex(Index index) {
   ArrayList<Index> indexes = getIndexes();
   if (indexes != null) {
     remove(indexes, index);
     if (index.getIndexType().isPrimaryKey()) {
       for (Column col : index.getColumns()) {
         col.setPrimaryKey(false);
       }
     }
   }
 }
Пример #3
0
 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);
 }
Пример #4
0
 /**
  * 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 static boolean canUseIndex(Index existingIndex, Table table, IndexColumn[] cols) {
   if (existingIndex.getTable() != table || existingIndex.getCreateSQL() == null) {
     // can't use the scan index or index of another table
     return false;
   }
   Column[] indexCols = existingIndex.getColumns();
   if (indexCols.length < cols.length) {
     return false;
   }
   for (IndexColumn col : cols) {
     // all columns of the list must be part of the index,
     // but not all columns of the index need to be part of the list
     // holes are not allowed (index=a,b,c & list=a,b is ok; but list=a,c
     // is not)
     int idx = existingIndex.getColumnIndex(col.column);
     if (idx < 0 || idx >= cols.length) {
       return false;
     }
   }
   return true;
 }
 private static boolean canUseUniqueIndex(Index idx, Table table, IndexColumn[] cols) {
   if (idx.getTable() != table || !idx.getIndexType().isUnique()) {
     return false;
   }
   Column[] indexCols = idx.getColumns();
   if (indexCols.length > cols.length) {
     return false;
   }
   HashSet<Column> set = New.hashSet();
   for (IndexColumn c : cols) {
     set.add(c.column);
   }
   for (Column c : indexCols) {
     // all columns of the index must be part of the list,
     // but not all columns of the list need to be part of the index
     if (!set.contains(c)) {
       return false;
     }
   }
   return true;
 }