backend/query/populate_info_schema_columns_metadata.cc (261 lines of code) (raw):
//
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <iostream>
#include <string>
#include "absl/flags/parse.h"
#include "zetasql/base/logging.h"
#include "google/spanner/admin/database/v1/common.pb.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "riegeli/bytes/cfile_reader.h"
#include "riegeli/csv/csv_reader.h"
#include "riegeli/csv/csv_record.h"
using ::google::spanner::admin::database::v1::DatabaseDialect;
using ::riegeli::CsvReader;
using ::riegeli::CsvReaderBase;
using ::riegeli::CsvRecord;
using ::riegeli::CFileReader;
static constexpr char kCsvSeparator = ',';
std::string GetMetadataFileByDialect(const DatabaseDialect& dialect,
absl::string_view gsql_file,
absl::string_view pg_file) {
std::string metadata_file;
switch (dialect) {
case DatabaseDialect::DATABASE_DIALECT_UNSPECIFIED:
case DatabaseDialect::GOOGLE_STANDARD_SQL:
metadata_file = gsql_file;
break;
case DatabaseDialect::POSTGRESQL:
metadata_file = pg_file;
break;
default:
// Should never get here.
break;
}
constexpr absl::string_view kInfoSchemaColumnsMetadataPath =
"backend/query/";
return absl::StrCat(kInfoSchemaColumnsMetadataPath, metadata_file);
}
// This is used to create c++ code which are used to populate information
// schema. It reads information schema data from csv files and
// populates a header file with a static vector.
std::string PopulateInfoSchemaColumnsMetadata(const DatabaseDialect& dialect) {
std::string prefix = "";
if (dialect == DatabaseDialect::POSTGRESQL) {
prefix = "PG";
}
std::string metadata_code = absl::Substitute(
R"(inline const std::vector<ColumnsMetaEntry>& $0ColumnsMetadata() {
// clang-format off
static const zetasql_base::NoDestructor<std::vector<ColumnsMetaEntry>>
kColumnsMetadata({
)",
prefix);
constexpr absl::string_view kGSQLInfoSchemaColumnsMetadata =
"info_schema_columns_metadata.csv";
constexpr absl::string_view kPGInfoSchemaColumnsMetadata =
"pg_info_schema_columns_metadata.csv";
std::string metadata_file = GetMetadataFileByDialect(
dialect, kGSQLInfoSchemaColumnsMetadata, kPGInfoSchemaColumnsMetadata);
CsvReaderBase::Options options;
options.set_field_separator(kCsvSeparator);
options.set_required_header(
{"table_name", "column_name", "is_nullable", "spanner_type"});
options.set_comment('#');
CFileReader file_reader = CFileReader(metadata_file);
CsvReader csv_reader(&file_reader, options);
ZETASQL_VLOG(csv_reader.status().ok())
<< "Error reading csv file:" << csv_reader.status();
absl::StrAppend(&metadata_code, " // NOLINTBEGIN(whitespace/line_length)\n");
for (CsvRecord record; csv_reader.ReadRecord(record);) {
std::string table_name = absl::StrCat("\"", record["table_name"], "\"");
std::string column_name = absl::StrCat("\"", record["column_name"], "\"");
std::string is_nullable = absl::StrCat("\"", record["is_nullable"], "\"");
std::string spanner_type = absl::StrCat("\"", record["spanner_type"], "\"");
absl::StrAppend(&metadata_code, " {", table_name, ", ", column_name,
", ", is_nullable, ", ", spanner_type, "},\n");
}
absl::StrAppend(&metadata_code, R"( });
// NOLINTEND(whitespace/line_length)
// clang-format on
return *kColumnsMetadata;
}
)");
ZETASQL_VLOG(csv_reader.Close()) << csv_reader.status();
return metadata_code;
}
std::string PopulateInfoSchemaColumnsMetadataForIndex(
const DatabaseDialect& dialect) {
std::string prefix = "";
if (dialect == DatabaseDialect::POSTGRESQL) {
prefix = "PG";
}
std::string metadata_for_index_code = absl::Substitute(
R"(inline const std::vector<IndexColumnsMetaEntry>& $0IndexColumnsMetadata() {
// clang-format off
static const zetasql_base::NoDestructor<std::vector<IndexColumnsMetaEntry>>
kColumnsMetadataForIndex({
)",
prefix);
constexpr absl::string_view kGSQLInfoSchemaColumnsMetadataForIndex =
"info_schema_columns_metadata_for_index.csv";
constexpr absl::string_view kPGInfoSchemaColumnsMetadataForIndex =
"pg_info_schema_columns_metadata_for_index.csv";
std::string metadata_file =
GetMetadataFileByDialect(dialect, kGSQLInfoSchemaColumnsMetadataForIndex,
kPGInfoSchemaColumnsMetadataForIndex);
CsvReaderBase::Options options;
options.set_field_separator(kCsvSeparator);
options.set_required_header({"table_name", "column_name", "is_nullable",
"column_ordering", "spanner_type",
"ordinal_position"});
options.set_comment('#');
CFileReader file_reader = CFileReader(metadata_file);
CsvReader csv_reader(&file_reader, options);
ZETASQL_VLOG(csv_reader.status().ok())
<< "Error reading csv file:" << csv_reader.status();
absl::StrAppend(&metadata_for_index_code,
" // NOLINTBEGIN(whitespace/line_length)\n");
for (CsvRecord record; csv_reader.ReadRecord(record);) {
std::string table_name = absl::StrCat("\"", record["table_name"], "\"");
std::string column_name = absl::StrCat("\"", record["column_name"], "\"");
std::string is_nullable = absl::StrCat("\"", record["is_nullable"], "\"");
std::string column_ordering =
absl::StrCat("\"", record["column_ordering"], "\"");
std::string spanner_type = absl::StrCat("\"", record["spanner_type"], "\"");
std::string ordinal_position = record["ordinal_position"];
absl::StrAppend(&metadata_for_index_code, " {", table_name, ", ",
column_name, ", ", is_nullable, ", ", column_ordering, ", ",
spanner_type, ", ", ordinal_position, "},\n");
}
absl::StrAppend(&metadata_for_index_code, R"( });
// NOLINTEND(whitespace/line_length)
// clang-format on
return *kColumnsMetadataForIndex;
}
)");
ZETASQL_VLOG(csv_reader.Close()) << csv_reader.status();
return metadata_for_index_code;
}
std::string PopulateSpannerSysColumnsMetadata() {
std::string metadata_code =
R"(struct SpannerSysColumnsMetaEntry {
const char* table_name;
const char* column_name;
const char* is_nullable;
const char* spanner_type;
int primary_key_ordinal;
};
inline const std::vector<SpannerSysColumnsMetaEntry>&
SpannerSysColumnsMetadata() {
// clang-format off
static const zetasql_base::NoDestructor<std::vector<SpannerSysColumnsMetaEntry>>
kSpannerSysColumnsMetadata({
)";
// clang-format off
constexpr absl::string_view kSpannerSysColumnsMetadata =
"backend/query/spanner_sys_columns_metadata.csv"; // NOLINT
// clang-format on
CsvReaderBase::Options options;
options.set_field_separator(kCsvSeparator);
options.set_required_header({"table_name", "column_name", "is_nullable",
"spanner_type", "ordinal_position"});
CFileReader file_reader = CFileReader(kSpannerSysColumnsMetadata);
CsvReader csv_reader(&file_reader, options);
ZETASQL_VLOG(csv_reader.status().ok())
<< "Error reading csv file:" << csv_reader.status();
absl::StrAppend(&metadata_code, " // NOLINTBEGIN(whitespace/line_length)\n");
for (CsvRecord record; csv_reader.ReadRecord(record);) {
std::string table_name = absl::StrCat("\"", record["table_name"], "\"");
std::string column_name = absl::StrCat("\"", record["column_name"], "\"");
std::string is_nullable = absl::StrCat("\"", record["is_nullable"], "\"");
std::string spanner_type = absl::StrCat("\"", record["spanner_type"], "\"");
std::string ordinal_position = record["ordinal_position"];
absl::StrAppend(&metadata_code, " {", table_name, ", ", column_name,
", ", is_nullable, ", ", spanner_type, ", ",
ordinal_position, "},\n");
}
absl::StrAppend(&metadata_code, R"( });
// NOLINTEND(whitespace/line_length)
// clang-format on
return *kSpannerSysColumnsMetadata;
}
)");
ZETASQL_VLOG(csv_reader.Close()) << csv_reader.status();
return metadata_code;
}
std::string PopulatePGCatalogColumnsMetadata() {
std::string metadata_code =
R"(inline const std::vector<ColumnsMetaEntry>& PGCatalogColumnsMetadata() {
// clang-format off
static const zetasql_base::NoDestructor<std::vector<ColumnsMetaEntry>>
kPGCatalogColumnsMetadata({
)";
// clang-format off
constexpr absl::string_view kPGCatalogColumnsMetadata =
"backend/query/pg_catalog_columns_metadata.csv"; // NOLINT
// clang-format on
CsvReaderBase::Options options;
options.set_field_separator(kCsvSeparator);
options.set_required_header(
{"table_name", "column_name", "is_nullable", "spanner_type"});
CFileReader file_reader = CFileReader(kPGCatalogColumnsMetadata);
CsvReader csv_reader(&file_reader, options);
ZETASQL_VLOG(csv_reader.status().ok()) // crash ok
<< "Error reading csv file:" << csv_reader.status();
absl::StrAppend(&metadata_code, " // NOLINTBEGIN(whitespace/line_length)\n");
for (CsvRecord record; csv_reader.ReadRecord(record);) {
std::string table_name = absl::StrCat("\"", record["table_name"], "\"");
std::string column_name = absl::StrCat("\"", record["column_name"], "\"");
std::string is_nullable = absl::StrCat("\"", record["is_nullable"], "\"");
std::string spanner_type = absl::StrCat("\"", record["spanner_type"], "\"");
absl::StrAppend(&metadata_code, " {", table_name, ", ", column_name,
", ", is_nullable, ", ", spanner_type, "},\n");
}
absl::StrAppend(&metadata_code, R"( });
// NOLINTEND(whitespace/line_length)
// clang-format on
return *kPGCatalogColumnsMetadata;
}
)");
ZETASQL_VLOG(csv_reader.Close()) << csv_reader.status(); // crash ok
return metadata_code;
}
int main(int argc, char* argv[]) {
absl::ParseCommandLine(argc, argv);
constexpr absl::string_view kTemplate =
R"(#ifndef $0
#define $0
#include <string>
#include <vector>
#include "zetasql/base/no_destructor.h"
// WARNING - DO NOT EDIT
// AUTOGENERATED FILE USING BUILD RULE:
// populate_info_schema_columns_metadata
namespace google::spanner::emulator::backend {
struct ColumnsMetaEntry {
const char* table_name;
const char* column_name;
const char* is_nullable;
const char* spanner_type;
};
struct IndexColumnsMetaEntry {
const char* table_name;
const char* column_name;
const char* is_nullable;
const char* column_ordering;
const char* spanner_type;
int primary_key_ordinal = 0;
};
$1
$2
$3
$4
$5
$6
} // namespace google::spanner::emulator::backend
#endif // $0
)";
std::cout << absl::Substitute(
kTemplate,
"THIRD_PARTY_CLOUD_SPANNER_EMULATOR_BACKEND_QUERY_INFO_SCHEMA_",
PopulateInfoSchemaColumnsMetadata(DatabaseDialect::GOOGLE_STANDARD_SQL),
PopulateInfoSchemaColumnsMetadataForIndex(
DatabaseDialect::GOOGLE_STANDARD_SQL),
PopulateInfoSchemaColumnsMetadata(DatabaseDialect::POSTGRESQL),
PopulateInfoSchemaColumnsMetadataForIndex(DatabaseDialect::POSTGRESQL),
PopulatePGCatalogColumnsMetadata(),
PopulateSpannerSysColumnsMetadata());
return 0;
}