in backend/query/information_schema_catalog.cc [878:1087]
void InformationSchemaCatalog::FillColumnsTable() {
auto columns = tables_by_name_.at(GetNameForDialect(kColumns)).get();
// Add table rows.
std::vector<std::vector<zetasql::Value>> rows;
absl::flat_hash_map<std::string, zetasql::Value> specific_kvs;
for (const Table* table : default_schema_->tables()) {
int pos = 1;
for (const Column* column : table->columns()) {
if (dialect_ == DatabaseDialect::POSTGRESQL) {
specific_kvs[kColumnDefault] =
column->has_default_value() && !column->is_identity_column()
? String(column->original_expression().value())
: NullString();
const zetasql::Type* type = column->GetType();
if (column->has_allows_commit_timestamp()) {
specific_kvs[kDataType] = String(kSpannerCommitTimestamp);
specific_kvs[kSpannerType] = String(kSpannerCommitTimestamp);
} else {
specific_kvs[kDataType] = PGDataType(type);
specific_kvs[kSpannerType] = GetSpannerType(column);
}
specific_kvs[kCharacterMaximumLength] =
(!type->IsArray() && column->declared_max_length() != std::nullopt)
? Int64(column->declared_max_length().value())
: NullInt64();
specific_kvs[kNumericPrecision] = GetPGNumericPrecision(type);
specific_kvs[kNumericPrecisionRadix] = GetPGNumericPrecisionRadix(type);
specific_kvs[kNumericScale] = type->IsInt64() ? Int64(0) : NullInt64();
specific_kvs[kGenerationExpression] =
column->is_generated()
? String(column->original_expression().value())
: NullString();
} else {
specific_kvs[kGenerationExpression] = NullString();
if (column->is_generated()) {
absl::string_view expression = column->expression().value();
absl::ConsumePrefix(&expression, "(");
absl::ConsumeSuffix(&expression, ")");
specific_kvs[kGenerationExpression] = String(expression);
}
specific_kvs[kColumnDefault] =
(column->has_default_value() && !column->is_identity_column())
? String(column->expression().value())
: NullString();
specific_kvs[kDataType] = NullString();
specific_kvs[kSpannerType] = GetSpannerType(column);
}
const auto& [table_schema_part, table_name_part] =
GetSchemaAndNameForInformationSchema(table->Name());
specific_kvs[kTableCatalog] = DialectTableCatalog();
specific_kvs[kTableSchema] = String(table_schema_part);
specific_kvs[kTableName] = String(table_name_part);
specific_kvs[kColumnName] = String(column->Name());
specific_kvs[kOrdinalPosition] = Int64(pos++);
specific_kvs[kIsNullable] = String(column->is_nullable() ? kYes : kNo);
specific_kvs[kIsGenerated] =
String(column->is_generated() ? kAlways : kNever);
if (column->is_generated()) {
specific_kvs[kIsStored] =
column->is_stored() ? String(kYes) : String(kNo);
} else {
specific_kvs[kIsStored] = NullString();
}
// Identity column fields.
specific_kvs[kIsIdentity] =
String(column->is_identity_column() ? kYes : kNo);
specific_kvs[kSpannerState] = String(kCommitted);
specific_kvs[kIdentityGeneration] = NullString();
specific_kvs[kIdentityKind] = NullString();
specific_kvs[kIdentityStartWithCounter] = NullString();
specific_kvs[kIdentitySkipRangeMin] = NullString();
specific_kvs[kIdentitySkipRangeMax] = NullString();
if (column->is_identity_column()) {
specific_kvs[kIdentityGeneration] = String(kByDefault);
if (!column->sequences_used().empty()) {
const Sequence* seq =
static_cast<const Sequence*>(column->sequences_used().at(0));
if (!seq->use_default_sequence_kind_option()) {
specific_kvs[kIdentityKind] = String(kBitReversedPositiveSequence);
}
specific_kvs[kIdentityStartWithCounter] =
seq->start_with_counter().has_value()
? String(absl::StrCat(*seq->start_with_counter()))
: NullString();
specific_kvs[kIdentitySkipRangeMin] =
seq->skip_range_min().has_value()
? String(absl::StrCat(*seq->skip_range_min()))
: NullString();
specific_kvs[kIdentitySkipRangeMax] =
seq->skip_range_max().has_value()
? String(absl::StrCat(*seq->skip_range_max()))
: NullString();
}
}
rows.push_back(GetRowFromRowKVs(columns, specific_kvs));
specific_kvs.clear();
}
}
// Add columns for views.
for (const View* view : default_schema_->views()) {
int pos = 1;
for (const View::Column& column : view->columns()) {
if (dialect_ == DatabaseDialect::POSTGRESQL) {
// Emulator's View::Column doesn't store the length so we pass the
// length in as a std::nullopt.
specific_kvs[kDataType] = PGDataType(column.type);
specific_kvs[kSpannerType] = GetSpannerType(column.type, std::nullopt);
// Emulator's View::Column doesn't store the length so we assume the
// length is the max string or byte length.
// TODO: Update the View::Column to store the actual
// length.
specific_kvs[kCharacterMaximumLength] = NullInt64();
specific_kvs[kNumericPrecision] = GetPGNumericPrecision(column.type);
specific_kvs[kNumericPrecisionRadix] =
GetPGNumericPrecisionRadix(column.type);
specific_kvs[kNumericScale] =
column.type->IsInt64() ? Int64(0) : NullInt64();
} else {
specific_kvs[kDataType] = NullString();
specific_kvs[kSpannerType] = GetSpannerType(column.type, 0);
}
const auto& [view_schema_part, view_name_part] =
GetSchemaAndNameForInformationSchema(view->Name());
specific_kvs[kTableCatalog] = DialectTableCatalog();
specific_kvs[kTableSchema] = String(view_schema_part);
specific_kvs[kTableName] = String(view_name_part);
specific_kvs[kColumnName] = String(column.name);
specific_kvs[kOrdinalPosition] = Int64(pos++);
specific_kvs[kColumnDefault] = NullBytes();
specific_kvs[kIsNullable] = String(kYes);
specific_kvs[kIsGenerated] = String(kNever);
specific_kvs[kGenerationExpression] = NullString();
specific_kvs[kIsStored] = NullString();
specific_kvs[kSpannerState] = String(kCommitted);
specific_kvs[kIsIdentity] = String(kNo);
specific_kvs[kIdentityGeneration] = NullString();
specific_kvs[kIdentityKind] = NullString();
specific_kvs[kIdentityStartWithCounter] = NullString();
specific_kvs[kIdentitySkipRangeMin] = NullString();
specific_kvs[kIdentitySkipRangeMax] = NullString();
rows.push_back(GetRowFromRowKVs(columns, specific_kvs));
specific_kvs.clear();
}
}
// Add columns for the tables that live inside INFORMATION_SCHEMA.
for (const auto& table : this->tables()) {
int pos = 1;
for (int i = 0; i < table->NumColumns(); ++i) {
const auto* column = table->GetColumn(i);
const auto& metadata = GetColumnMetadata(dialect_, table, column);
if (dialect_ == DatabaseDialect::POSTGRESQL) {
const zetasql::Type* type = column->GetType();
// Information schema metadata doesn't store the length of a character
// varying or bytea type. So we always pass in std::nullopt as the
// length.
specific_kvs[kDataType] = PGDataType(type);
specific_kvs[kSpannerType] = GetSpannerType(type, std::nullopt);
specific_kvs[kCharacterMaximumLength] = NullInt64();
specific_kvs[kNumericPrecision] = GetPGNumericPrecision(type);
specific_kvs[kNumericPrecisionRadix] = GetPGNumericPrecisionRadix(type);
specific_kvs[kNumericScale] = type->IsInt64() ? Int64(0) : NullInt64();
} else {
specific_kvs[kDataType] = NullString();
specific_kvs[kSpannerType] = String(metadata.spanner_type);
}
specific_kvs[kTableCatalog] = DialectTableCatalog();
specific_kvs[kTableSchema] =
String(GetNameForDialect(kInformationSchema));
specific_kvs[kTableName] = String(GetNameForDialect(table->Name()));
specific_kvs[kColumnName] = String(GetNameForDialect(column->Name()));
specific_kvs[kOrdinalPosition] = Int64(pos++);
specific_kvs[kColumnDefault] = NullBytes();
specific_kvs[kIsNullable] = String(metadata.is_nullable);
specific_kvs[kIsGenerated] = String(kNever);
specific_kvs[kGenerationExpression] = NullString();
specific_kvs[kIsStored] = NullString();
specific_kvs[kSpannerState] = NullString();
specific_kvs[kIsIdentity] = String(kNo);
specific_kvs[kIdentityGeneration] = NullString();
specific_kvs[kIdentityKind] = NullString();
specific_kvs[kIdentityStartWithCounter] = NullString();
specific_kvs[kIdentitySkipRangeMin] = NullString();
specific_kvs[kIdentitySkipRangeMax] = NullString();
rows.push_back(GetRowFromRowKVs(columns, specific_kvs));
specific_kvs.clear();
}
}
// Add table to catalog.
columns->SetContents(rows);
}