void InformationSchemaCatalog::FillTableConstraintsTable()

in backend/query/information_schema_catalog.cc [1488:1695]


void InformationSchemaCatalog::FillTableConstraintsTable() {
  auto table_constraints =
      tables_by_name_.at(GetNameForDialect(kTableConstraints)).get();

  std::vector<std::vector<zetasql::Value>> rows;

  // Add the user table constraints.
  for (const auto* table : default_schema_->tables()) {
    const auto& [table_schema_part, table_name_part] =
        GetSchemaAndNameForInformationSchema(table->Name());
    // Add the primary key.
    rows.push_back({
        // constraint_catalog
        DialectTableCatalog(),
        // constraint_schema
        String(table_schema_part),
        // constraint_name
        String(PrimaryKeyName(table)),
        // table_catalog
        DialectTableCatalog(),
        // table_schema
        String(table_schema_part),
        // table_name
        String(table_name_part),
        // constraint_type,
        String(kPrimaryKey),
        // is_deferrable,
        String(kNo),
        // initially_deferred,
        String(kNo),
        // enforced,
        String(kYes),
    });

    // Add the NOT NULL check constraints.
    for (const auto* column : table->columns()) {
      if (column->is_nullable()) {
        continue;
      }
      rows.push_back({
          // constraint_catalog
          DialectTableCatalog(),
          // constraint_schema
          String(table_schema_part),
          // constraint_name
          String(CheckNotNullName(table, column)),
          // table_catalog
          DialectTableCatalog(),
          // table_schema
          String(table_schema_part),
          // table_name
          String(table_name_part),
          // constraint_type,
          String(kCheck),
          // is_deferrable,
          String(kNo),
          // initially_deferred,
          String(kNo),
          // enforced,
          String(kYes),
      });
    }

    // Add the check constraints defined by the ZETASQL_VLOG keyword.
    for (const auto* check_constraint : table->check_constraints()) {
      rows.push_back({
          // constraint_catalog
          DialectTableCatalog(),
          // constraint_schema
          String(table_schema_part),
          // constraint_name
          String(check_constraint->Name()),
          // table_catalog
          DialectTableCatalog(),
          // table_schema
          String(table_schema_part),
          // table_name
          String(table_name_part),
          // constraint_type,
          String(kCheck),
          // is_deferrable,
          String(kNo),
          // initially_deferred,
          String(kNo),
          // enforced,
          String(kYes),
      });
    }
    // Add the foreign keys.
    for (const auto* foreign_key : table->foreign_keys()) {
      rows.push_back({
          // constraint_catalog
          DialectTableCatalog(),
          // constraint_schema
          String(table_schema_part),
          // constraint_name
          String(SDLObjectName::GetInSchemaName(foreign_key->Name())),
          // table_catalog
          DialectTableCatalog(),
          // table_schema
          String(table_schema_part),
          // table_name
          String(table_name_part),
          // constraint_type,
          String(kForeignKey),
          // is_deferrable,
          String(kNo),
          // initially_deferred,
          String(kNo),
          // enforced,
          String(kYes),
      });

      // Add the foreign key's unique backing index as a unique constraint.
      const auto& [referenced_table_schema_part, referenced_table_name_part] =
          GetSchemaAndNameForInformationSchema(
              foreign_key->referenced_table()->Name());
      if (foreign_key->referenced_index()) {
        rows.push_back({
            // constraint_catalog
            DialectTableCatalog(),
            // constraint_schema
            DialectDefaultSchema(),
            // constraint_name
            String(foreign_key->referenced_index()->Name()),
            // table_catalog
            DialectTableCatalog(),
            // table_schema
            String(referenced_table_schema_part),
            // table_name
            String(referenced_table_name_part),
            // constraint_type,
            String(kUnique),
            // is_deferrable,
            String(kNo),
            // initially_deferred,
            String(kNo),
            // enforced,
            String(kYes),
        });
      }
    }
  }

  // Production doesn't add check constraints for the information schema so we
  // also don't add it in the emulator.
  if (dialect_ != DatabaseDialect::POSTGRESQL) {
    // Add the information schema constraints.
    for (const auto* table : this->tables()) {
      // Add the primary key.
      rows.push_back({
          // constraint_catalog
          DialectTableCatalog(),
          // constraint_schema
          String(kInformationSchema),
          // constraint_name
          String(PrimaryKeyName(table)),
          // table_catalog
          DialectTableCatalog(),
          // table_schema
          String(kInformationSchema),
          // table_name
          String(table->Name()),
          // constraint_type
          String(kPrimaryKey),
          // is_deferrable,
          String(kNo),
          // initially_deferred
          String(kNo),
          // enforced
          String(kYes),
      });

      // Add the NOT NULL check constraints.
      for (int i = 0; i < table->NumColumns(); ++i) {
        const auto* column = table->GetColumn(i);
        const auto& metadata = GetColumnMetadata(dialect_, table, column);
        if (IsNullable(metadata)) {
          continue;
        }
        rows.push_back({
            // constraint_catalog
            DialectTableCatalog(),
            // constraint_schema
            String(kInformationSchema),
            // constraint_name
            String(CheckNotNullName(table, column)),
            // table_catalog
            DialectTableCatalog(),
            // table_schema
            String(kInformationSchema),
            // table_name
            String(table->Name()),
            // constraint_type,
            String(kCheck),
            // is_deferrable,
            String(kNo),
            // initially_deferred,
            String(kNo),
            // enforced,
            String(kYes),
        });
      }
    }
  }

  table_constraints->SetContents(rows);
}