void PGCatalog::FillPGConstraintTable()

in backend/query/pg_catalog.cc [1402:1652]


void PGCatalog::FillPGConstraintTable() {
  auto pg_constraint = tables_by_name_.at(kPGConstraint).get();

  std::vector<std::vector<zetasql::Value>> rows;
  for (const Table* table : default_schema_->tables()) {
    if (!table->postgresql_oid().has_value()) {
      ZETASQL_VLOG(1) << "Table " << table->Name()
              << " does not have a PostgreSQL OID.";
      continue;
    }
    const auto& [table_schema, _] = GetSchemaAndNameForPGCatalog(table->Name());
    int namespace_oid = 0;
    if (kHardCodedNamedSchemaOid.contains(table_schema)) {
      namespace_oid = kHardCodedNamedSchemaOid.at(table_schema);
    } else {
      const NamedSchema* named_schema =
          default_schema_->FindNamedSchema(table_schema);
      if (!named_schema->postgresql_oid().has_value()) {
        ZETASQL_VLOG(1) << "Named schema " << table_schema
                << " does not have a PostgreSQL OID.";
        continue;
      }
      namespace_oid = named_schema->postgresql_oid().value();
    }
    int ordinal_position = 1;
    std::map<std::string, int> column_name_to_index;
    for (const Column* column : table->columns()) {
      column_name_to_index[column->Name()] = ordinal_position++;
    }
    for (const CheckConstraint* check_constraint : table->check_constraints()) {
      if (!check_constraint->postgresql_oid().has_value()) {
        ZETASQL_VLOG(1) << "Check constraint " << check_constraint->Name()
                << " does not have a PostgreSQL OID.";
        continue;
      }
      std::vector<int64_t> key_attnums;
      for (const Column* column : check_constraint->dependent_columns()) {
        key_attnums.push_back(column_name_to_index[column->Name()]);
      }
      rows.push_back({
          // oid
          CreatePgOidValue(check_constraint->postgresql_oid().value()).value(),
          // conname
          String(check_constraint->Name()),
          // connamespace
          CreatePgOidValue(namespace_oid).value(),
          // contype
          String("c"),
          // condeferrable
          NullBool(),
          // condeferred
          NullBool(),
          // convalidated
          Bool(true),
          // conrelid
          CreatePgOidValue(table->postgresql_oid().value()).value(),
          // contypid
          NullPgOid(),
          // conindid
          NullPgOid(),
          // conparentid
          NullPgOid(),
          // confrelid
          CreatePgOidValue(0).value(),
          // confupdtype
          String(" "),
          // confdeltype
          String(" "),
          // confmatchtype
          NullString(),
          // conislocal
          NullBool(),
          // coninhcount
          NullInt64(),
          // connoinherit
          NullBool(),
          // conkey
          Int64Array(key_attnums),
          // confkey
          Null(Int64ArrayType()),
          // conpfeqop
          Null(GetPgOidArrayType()),
          // conppeqop
          Null(GetPgOidArrayType()),
          // conffeqop
          Null(GetPgOidArrayType()),
          // conexclop
          Null(GetPgOidArrayType()),
          // conbin
          NullString(),
      });
    }
    for (const ForeignKey* foreign_key : table->foreign_keys()) {
      if (!foreign_key->postgresql_oid().has_value()) {
        ZETASQL_VLOG(1) << "Foreign key " << foreign_key->Name()
                << " does not have a PostgreSQL OID.";
        continue;
      }
      if (!foreign_key->referencing_table()->postgresql_oid().has_value()) {
        ZETASQL_VLOG(1) << "Referencing table " <<
            foreign_key->referencing_table()->Name() << "of foreign key "
            << foreign_key->Name() << " does not have a PostgreSQL OID.";
        continue;
      }
      std::string on_delete_action;
      switch (foreign_key->on_delete_action()) {
        case ForeignKey::Action::kNoAction:
          on_delete_action = "a";
          break;
        case ForeignKey::Action::kCascade:
          on_delete_action = "c";
          break;
        default:
          on_delete_action = " ";
      }
      std::vector<int64_t> key_attnums;
      for (const Column* column : foreign_key->referencing_columns()) {
        key_attnums.push_back(column_name_to_index[column->Name()]);
      }
      int ordinal_position = 1;
      std::map<std::string, int> foreign_column_name_to_index;
      for (const Column* column : foreign_key->referenced_table()->columns()) {
        foreign_column_name_to_index[column->Name()] = ordinal_position++;
      }
      std::vector<int64_t> confkey_attnums;
      for (const Column* column : foreign_key->referenced_columns()) {
        confkey_attnums.push_back(foreign_column_name_to_index[column->Name()]);
      }
      rows.push_back({
          // oid
          CreatePgOidValue(foreign_key->postgresql_oid().value()).value(),
          // conname
          String(foreign_key->Name()),
          // connamespace
          CreatePgOidValue(namespace_oid).value(),
          // contype
          String("f"),
          // condeferrable
          NullBool(),
          // condeferred
          NullBool(),
          // convalidated
          Bool(true),
          // conrelid
          CreatePgOidValue(
              foreign_key->referencing_table()->postgresql_oid().value())
              .value(),
          // contypid
          NullPgOid(),
          // conindid
          NullPgOid(),
          // conparentid
          NullPgOid(),
          // confrelid
          CreatePgOidValue(
              foreign_key->referenced_table()->postgresql_oid().value())
              .value(),
          // confupdtype
          String(" "),  // For update is not yet supported in the emulator.
          // confdeltype
          String(on_delete_action),
          // confmatchtype
          NullString(),
          // conislocal
          NullBool(),
          // coninhcount
          NullInt64(),
          // connoinherit
          NullBool(),
          // conkey
          Int64Array(key_attnums),
          // confkey
          Int64Array(confkey_attnums),
          // conpfeqop
          Null(GetPgOidArrayType()),
          // conppeqop
          Null(GetPgOidArrayType()),
          // conffeqop
          Null(GetPgOidArrayType()),
          // conexclop
          Null(GetPgOidArrayType()),
          // conbin
          NullString(),
      });
    }
    if (!table->primary_key()[0]->postgresql_oid().has_value()) {
      ZETASQL_VLOG(1) << "Primary key constraint for table " << table->Name()
              << " does not have a PostgreSQL OID.";
      continue;
    }
    std::vector<int64_t> key_attnums;
    for (const KeyColumn* key_column : table->primary_key()) {
      key_attnums.push_back(column_name_to_index[key_column->column()->Name()]);
    }
    // Primary key constraint.
    rows.push_back({
        // oid
        CreatePgOidValue(table->primary_key()[0]->postgresql_oid().value())
            .value(),
        // conname
        String(PrimaryKeyName(table)),
        // connamespace
        CreatePgOidValue(namespace_oid).value(),
        // contype
        String("p"),
        // condeferrable
        NullBool(),
        // condeferred
        NullBool(),
        // convalidated
        Bool(true),
        // conrelid
        CreatePgOidValue(table->postgresql_oid().value()).value(),
        // contypid
        NullPgOid(),
        // conindid
        NullPgOid(),
        // conparentid
        NullPgOid(),
        // confrelid
        CreatePgOidValue(0).value(),
        // confupdtype
        String(" "),
        // confdeltype
        String(" "),
        // confmatchtype
        NullString(),
        // conislocal
        NullBool(),
        // coninhcount
        NullInt64(),
        // connoinherit
        NullBool(),
        // conkey
        Int64Array(key_attnums),
        // confkey
        Null(Int64ArrayType()),
        // conpfeqop
        Null(GetPgOidArrayType()),
        // conppeqop
        Null(GetPgOidArrayType()),
        // conffeqop
        Null(GetPgOidArrayType()),
        // conexclop
        Null(GetPgOidArrayType()),
        // conbin
        NullString(),
    });
  }
  pg_constraint->SetContents(rows);
}