Пример #1
0
 private void addColumnMutation(
     String schemaName, String tableName, PColumn column, PreparedStatement colUpsert)
     throws SQLException {
   colUpsert.setString(1, schemaName);
   colUpsert.setString(2, tableName);
   colUpsert.setString(3, column.getName().getString());
   colUpsert.setString(
       4, column.getFamilyName() == null ? null : column.getFamilyName().getString());
   colUpsert.setInt(5, column.getDataType().getSqlType());
   colUpsert.setInt(
       6,
       column.isNullable() ? ResultSetMetaData.columnNullable : ResultSetMetaData.columnNoNulls);
   if (column.getMaxLength() == null) {
     colUpsert.setNull(7, Types.INTEGER);
   } else {
     colUpsert.setInt(7, column.getMaxLength());
   }
   if (column.getScale() == null) {
     colUpsert.setNull(8, Types.INTEGER);
   } else {
     colUpsert.setInt(8, column.getScale());
   }
   colUpsert.setInt(9, column.getPosition() + 1);
   colUpsert.setInt(10, ColumnModifier.toSystemValue(column.getColumnModifier()));
   colUpsert.execute();
 }
Пример #2
0
  public MutationState addColumn(AddColumnStatement statement) throws SQLException {
    connection.rollback();
    boolean wasAutoCommit = connection.getAutoCommit();
    try {
      connection.setAutoCommit(false);
      TableName tableNameNode = statement.getTableName();
      String schemaName = tableNameNode.getSchemaName();
      String tableName = tableNameNode.getTableName();

      PTable table = getLatestTable(schemaName, tableName);
      PSchema schema = connection.getPMetaData().getSchema(schemaName);
      boolean retried = false;
      while (true) {
        int ordinalPosition = table.getColumns().size();

        List<PColumn> currentPKs = table.getPKColumns();
        PColumn lastPK = currentPKs.get(currentPKs.size() - 1);
        // Disallow adding columns if the last column is VARBIANRY.
        if (lastPK.getDataType() == PDataType.VARBINARY) {
          throw new SQLExceptionInfo.Builder(SQLExceptionCode.VARBINARY_LAST_PK)
              .setColumnName(lastPK.getName().getString())
              .build()
              .buildException();
        }
        // Disallow adding columns if last column is fixed width and nullable.
        if (lastPK.isNullable() && lastPK.getDataType().isFixedWidth()) {
          throw new SQLExceptionInfo.Builder(SQLExceptionCode.NULLABLE_FIXED_WIDTH_LAST_PK)
              .setColumnName(lastPK.getName().getString())
              .build()
              .buildException();
        }

        List<PColumn> columns = Lists.newArrayListWithExpectedSize(1);
        ColumnDef colDef = statement.getColumnDef();
        if (!colDef.isNull() && colDef.isPK()) {
          throw new SQLExceptionInfo.Builder(SQLExceptionCode.NOT_NULLABLE_COLUMN_IN_ROW_KEY)
              .setColumnName(colDef.getColumnDefName().getColumnName().getName())
              .build()
              .buildException();
        }

        PreparedStatement colUpsert = connection.prepareStatement(INSERT_COLUMN);
        Pair<byte[], Map<String, Object>> family = null;
        PColumn column = newColumn(ordinalPosition++, colDef, null);
        addColumnMutation(schemaName, tableName, column, colUpsert);
        columns.add(column);
        if (column.getFamilyName() != null) {
          family =
              new Pair<byte[], Map<String, Object>>(
                  column.getFamilyName().getBytes(), statement.getProps());
        }
        final long seqNum = table.getSequenceNumber() + 1;
        PreparedStatement tableUpsert = connection.prepareStatement(MUTATE_TABLE);
        tableUpsert.setString(1, schemaName);
        tableUpsert.setString(2, tableName);
        tableUpsert.setString(3, table.getType().getSerializedValue());
        tableUpsert.setLong(4, seqNum);
        tableUpsert.setInt(5, ordinalPosition);
        tableUpsert.execute();

        final List<Mutation> tableMetaData = connection.getMutationState().toMutations();
        connection.rollback();
        byte[] emptyCF = null;
        if (table.getType() != PTableType.VIEW
            && family != null
            && table.getColumnFamilies().isEmpty()) {
          emptyCF = family.getFirst();
        }
        MetaDataMutationResult result =
            connection
                .getQueryServices()
                .addColumn(tableMetaData, table.getType() == PTableType.VIEW, family);
        try {
          MutationCode code = processMutationResult(schemaName, tableName, result);
          if (code == MutationCode.COLUMN_ALREADY_EXISTS) {
            connection.addTable(schemaName, result.getTable());
            if (!statement.ifNotExists()) {
              throw new ColumnAlreadyExistsException(
                  schemaName, tableName, SchemaUtil.findExistingColumn(result.getTable(), columns));
            }
            return new MutationState(0, connection);
          }
          connection.addColumn(schemaName, tableName, columns, seqNum, result.getMutationTime());
          if (emptyCF != null) {
            Long scn = connection.getSCN();
            connection.setAutoCommit(true);
            // Delete everything in the column. You'll still be able to do queries at earlier
            // timestamps
            long ts = (scn == null ? result.getMutationTime() : scn);
            TableRef tableRef = new TableRef(null, table, schema, ts);
            MutationPlan plan =
                new PostDDLCompiler(connection).compile(tableRef, emptyCF, null, ts);
            return connection.getQueryServices().updateData(plan);
          }
          return new MutationState(0, connection);
        } catch (ConcurrentTableMutationException e) {
          if (retried) {
            throw e;
          }
          table = connection.getPMetaData().getSchema(schemaName).getTable(tableName);
          retried = true;
        }
      }
    } finally {
      connection.setAutoCommit(wasAutoCommit);
    }
  }