public void execute()

in baremaps-calcite/src/main/java/org/apache/baremaps/calcite/postgres/PostgresDdlExecutor.java [573:720]


  public void execute(SqlCreateTable create,
      CalcitePrepare.Context context) {
    final SchemaInfo schemaInfo =
        schema(context, true, create.name);
    requireNonNull(schemaInfo.schema()); // TODO: should not assume parent schema exists
    final JavaTypeFactory typeFactory = context.getTypeFactory();
    final RelDataType queryRowType;
    if (create.query != null) {
      // A bit of a hack: pretend it's a view, to get its row type
      final String sql =
          create.query.toSqlString(CalciteSqlDialect.DEFAULT).getSql();
      final ViewTableMacro viewTableMacro =
          ViewTable.viewMacro(schemaInfo.schema().plus(), sql, schemaInfo.schema().path(null),
              context.getObjectPath(), false);
      final TranslatableTable x = viewTableMacro.apply(ImmutableList.of());
      queryRowType = x.getRowType(typeFactory);

      if (create.columnList != null
          && queryRowType.getFieldCount() != create.columnList.size()) {
        throw SqlUtil.newContextException(
            create.columnList.getParserPosition(),
            RESOURCE.columnCountMismatch());
      }
    } else {
      queryRowType = null;
    }
    final List<SqlNode> columnList;
    if (create.columnList != null) {
      columnList = create.columnList;
    } else {
      if (queryRowType == null) {
        // "CREATE TABLE t" is invalid; because there is no "AS query" we need
        // a list of column names and types, "CREATE TABLE t (INT c)".
        throw SqlUtil.newContextException(create.name.getParserPosition(),
            RESOURCE.createTableRequiresColumnList());
      }
      columnList = new ArrayList<>();
      for (String name : queryRowType.getFieldNames()) {
        columnList.add(new SqlIdentifier(name, SqlParserPos.ZERO));
      }
    }

    // Build the CREATE TABLE SQL statement for PostgreSQL
    StringBuilder createTableSql = new StringBuilder();
    createTableSql.append("CREATE TABLE ");
    if (create.ifNotExists) {
      createTableSql.append("IF NOT EXISTS ");
    }
    createTableSql.append("\"").append(schemaInfo.name()).append("\" (");

    boolean first = true;
    // Process column declarations for the CREATE TABLE statement
    final ImmutableList.Builder<ColumnDef> b = ImmutableList.builder();
    final RelDataTypeFactory.Builder storedBuilder = typeFactory.builder();
    final SqlValidator validator = validator(context, true);

    for (Ord<SqlNode> c : Ord.zip(columnList)) {
      if (!first) {
        createTableSql.append(", ");
      }
      first = false;

      if (c.e instanceof SqlColumnDeclaration) {
        final SqlColumnDeclaration d = (SqlColumnDeclaration) c.e;
        final RelDataType type = d.dataType.deriveType(validator, true);
        if (d.strategy != ColumnStrategy.VIRTUAL) {
          storedBuilder.add(d.name.getSimple(), type);
        }
        b.add(ColumnDef.of(d.expression, type, d.strategy));

        // Add column to SQL statement
        createTableSql.append("\"").append(d.name.getSimple()).append("\" ");
        createTableSql.append(PostgresTypeConversion.toPostgresTypeString(type));
        if (d.strategy == ColumnStrategy.NOT_NULLABLE) {
          createTableSql.append(" NOT NULL");
        }
      } else if (c.e instanceof SqlIdentifier) {
        final SqlIdentifier id = (SqlIdentifier) c.e;
        if (queryRowType == null) {
          throw SqlUtil.newContextException(id.getParserPosition(),
              RESOURCE.createTableRequiresColumnTypes(id.getSimple()));
        }
        final RelDataTypeField f = queryRowType.getFieldList().get(c.i);
        final ColumnStrategy strategy = f.getType().isNullable()
            ? ColumnStrategy.NULLABLE
            : ColumnStrategy.NOT_NULLABLE;
        b.add(ColumnDef.of(c.e, f.getType(), strategy));
        storedBuilder.add(id.getSimple(), f.getType());

        // Add column to SQL statement
        createTableSql.append("\"").append(id.getSimple()).append("\" ");
        createTableSql.append(PostgresTypeConversion.toPostgresTypeString(f.getType()));
        if (strategy == ColumnStrategy.NOT_NULLABLE) {
          createTableSql.append(" NOT NULL");
        }
      } else {
        throw new AssertionError(c.e.getClass());
      }
    }

    createTableSql.append(")");

    if (schemaInfo.schema().plus().getTable(schemaInfo.name()) != null) {
      // Table exists.
      if (create.ifNotExists) {
        return;
      }
      if (!create.getReplace()) {
        // They did not specify IF NOT EXISTS, so give error.
        throw SqlUtil.newContextException(create.name.getParserPosition(),
            RESOURCE.tableExists(schemaInfo.name()));
      }

      // Drop existing table
      try {
        DataSource ds = getDataSource(context);
        try (Connection connection = ds.getConnection();
            PreparedStatement stmt =
                connection.prepareStatement("DROP TABLE \"" + schemaInfo.name() + "\"")) {
          stmt.executeUpdate();
        }
      } catch (SQLException e) {
        throw new RuntimeException(
            "Error dropping existing table in PostgreSQL: " + schemaInfo.name(), e);
      }
    }

    // Create the table in PostgreSQL
    try {
      DataSource ds = getDataSource(context);
      try (Connection connection = ds.getConnection();
          PreparedStatement stmt = connection.prepareStatement(createTableSql.toString())) {
        stmt.executeUpdate();
      }

      // Create Calcite wrapper for the table
      PostgresModifiableTable table =
          new PostgresModifiableTable(ds, schemaInfo.name(), context.getTypeFactory());
      schemaInfo.schema().add(schemaInfo.name(), table);

      // Populate the table if query is provided
      if (create.query != null) {
        populate(create.name, create.query, context);
      }
    } catch (SQLException e) {
      throw new RuntimeException("Error creating table in PostgreSQL: " + schemaInfo.name(), e);
    }
  }