Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PostgresViewEntry #183

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/include/storage/postgres_create_info.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//===----------------------------------------------------------------------===//
// DuckDB
//
// storage/postgres_create_info.hpp
//
//
//===----------------------------------------------------------------------===//

#pragma once

#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
#include "duckdb/parser/parsed_data/create_table_info.hpp"
#include "postgres_utils.hpp"

namespace duckdb {

struct PostgresCreateInfo {
public:
PostgresCreateInfo() {
}
virtual ~PostgresCreateInfo() {
}

public:
virtual CreateInfo &GetCreateInfo() = 0;
virtual const string &GetName() const = 0;
virtual void AddColumn(ColumnDefinition def, PostgresType pg_type, const string &pg_name) = 0;

public:
template <class TARGET>
TARGET &Cast() {
D_ASSERT(dynamic_cast<TARGET *>(this));
return reinterpret_cast<TARGET &>(*this);
}

template <class TARGET>
const TARGET &Cast() const {
D_ASSERT(dynamic_cast<const TARGET *>(this));
return reinterpret_cast<const TARGET &>(*this);
}

public:
idx_t approx_num_pages = 0;
};

} // namespace duckdb
23 changes: 19 additions & 4 deletions src/include/storage/postgres_table_entry.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@

#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp"
#include "duckdb/parser/parsed_data/create_table_info.hpp"
#include "storage/postgres_create_info.hpp"
#include "postgres_utils.hpp"

namespace duckdb {

struct PostgresTableInfo {
struct PostgresTableInfo : public PostgresCreateInfo {
public:
PostgresTableInfo() {
create_info = make_uniq<CreateTableInfo>();
create_info->columns.SetAllowDuplicates(true);
Expand All @@ -27,15 +29,28 @@ struct PostgresTableInfo {
create_info = make_uniq<CreateTableInfo>((SchemaCatalogEntry &)schema, table);
create_info->columns.SetAllowDuplicates(true);
}
~PostgresTableInfo() override {
}

public:
CreateInfo &GetCreateInfo() override {
return *create_info;
}

const string &GetTableName() const {
const string &GetName() const override {
return create_info->table;
}

void AddColumn(ColumnDefinition def, PostgresType pg_type, const string &pg_name) override {
postgres_types.push_back(std::move(pg_type));
postgres_names.push_back(pg_name);
create_info->columns.AddColumn(std::move(def));
}

public:
unique_ptr<CreateTableInfo> create_info;
vector<PostgresType> postgres_types;
vector<string> postgres_names;
idx_t approx_num_pages = 0;
};

class PostgresTableEntry : public TableCatalogEntry {
Expand All @@ -61,7 +76,7 @@ class PostgresTableEntry : public TableCatalogEntry {
vector<PostgresType> postgres_types;
//! Column names as they are within Postgres
//! We track these separately because of case sensitivity - Postgres allows e.g. the columns "ID" and "id" together
//! We would in this case remap them to "ID" and "id:1", while postgres_names store the original names
//! We would in this case remap them to "ID" and "id_1", while postgres_names store the original names
vector<string> postgres_names;
//! The approximate number of pages a table consumes in Postgres
idx_t approx_num_pages;
Expand Down
3 changes: 2 additions & 1 deletion src/include/storage/postgres_table_set.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class PostgresTableSet : public PostgresInSchemaSet {
void AlterTable(ClientContext &context, RemoveColumnInfo &info);

static void AddColumn(optional_ptr<PostgresTransaction> transaction, optional_ptr<PostgresSchemaEntry> schema,
PostgresResult &result, idx_t row, PostgresTableInfo &table_info, idx_t column_offset = 0);
PostgresResult &result, idx_t row, PostgresCreateInfo &pg_create_info,
idx_t column_offset = 0);

void CreateEntries(PostgresTransaction &transaction, PostgresResult &result, idx_t start, idx_t end);

Expand Down
70 changes: 70 additions & 0 deletions src/include/storage/postgres_view_entry.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
//===----------------------------------------------------------------------===//
// DuckDB
//
// storage/postgres_view_entry.hpp
//
//
//===----------------------------------------------------------------------===//

#pragma once

#include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp"
#include "duckdb/parser/parsed_data/create_view_info.hpp"
#include "storage/postgres_create_info.hpp"

namespace duckdb {

struct PostgresViewInfo : public PostgresCreateInfo {
public:
PostgresViewInfo() {
create_info = make_uniq<CreateViewInfo>();
// create_info->columns.SetAllowDuplicates(true);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about this, the Table has a ColumnsList which provides this option, but no such option exists for views because we don't have a ColumnsList, we instead just store the types+names separately

}
PostgresViewInfo(const string &schema, const string &view) {
create_info = make_uniq<CreateViewInfo>(string(), schema, view);
// create_info->columns.SetAllowDuplicates(true);
}
PostgresViewInfo(const SchemaCatalogEntry &schema, const string &view) {
create_info = make_uniq<CreateViewInfo>((SchemaCatalogEntry &)schema, view);
// create_info->columns.SetAllowDuplicates(true);
}

public:
const string &GetName() const override {
return create_info->view_name;
}

CreateInfo &GetCreateInfo() override {
return *create_info;
}

void AddColumn(ColumnDefinition def, PostgresType pg_type, const string &pg_name) override {
postgres_types.push_back(std::move(pg_type));
postgres_names.push_back(pg_name);
create_info->types.push_back(def.Type());
create_info->names.push_back(def.Name());
}

public:
unique_ptr<CreateViewInfo> create_info;
vector<PostgresType> postgres_types;
vector<string> postgres_names;
};

class PostgresViewEntry : public ViewCatalogEntry {
public:
PostgresViewEntry(Catalog &catalog, SchemaCatalogEntry &schema, CreateViewInfo &info);
PostgresViewEntry(Catalog &catalog, SchemaCatalogEntry &schema, PostgresViewInfo &info);

public:
//! Postgres type annotations
vector<PostgresType> postgres_types;
//! Column names as they are within Postgres
//! We track these separately because of case sensitivity - Postgres allows e.g. the columns "ID" and "id" together
//! We would in this case remap them to "ID" and "id_1", while postgres_names store the original names
vector<string> postgres_names;
//! The approximate number of pages a table consumes in Postgres
idx_t approx_num_pages;
};

} // namespace duckdb
4 changes: 3 additions & 1 deletion src/storage/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ add_library(
postgres_transaction_manager.cpp
postgres_type_entry.cpp
postgres_type_set.cpp
postgres_update.cpp)
postgres_update.cpp
postgres_view_entry.cpp
)
set(ALL_OBJECT_FILES
${ALL_OBJECT_FILES} $<TARGET_OBJECTS:postgres_ext_storage>
PARENT_SCOPE)
4 changes: 2 additions & 2 deletions src/storage/postgres_catalog_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ void PostgresCatalogSet::ClearEntries() {
is_loaded = false;
}

PostgresInSchemaSet::PostgresInSchemaSet(PostgresSchemaEntry &schema, bool is_loaded) :
PostgresCatalogSet(schema.ParentCatalog(), is_loaded), schema(schema) {
PostgresInSchemaSet::PostgresInSchemaSet(PostgresSchemaEntry &schema, bool is_loaded)
: PostgresCatalogSet(schema.ParentCatalog(), is_loaded), schema(schema) {
}

optional_ptr<CatalogEntry> PostgresInSchemaSet::CreateEntry(unique_ptr<CatalogEntry> entry) {
Expand Down
8 changes: 4 additions & 4 deletions src/storage/postgres_schema_entry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ PostgresSchemaEntry::PostgresSchemaEntry(Catalog &catalog, CreateSchemaInfo &inf
: SchemaCatalogEntry(catalog, info), tables(*this), indexes(*this), types(*this) {
}

PostgresSchemaEntry::PostgresSchemaEntry(Catalog &catalog, CreateSchemaInfo &info, unique_ptr<PostgresResultSlice> tables,
unique_ptr<PostgresResultSlice> enums,
PostgresSchemaEntry::PostgresSchemaEntry(Catalog &catalog, CreateSchemaInfo &info,
unique_ptr<PostgresResultSlice> tables, unique_ptr<PostgresResultSlice> enums,
unique_ptr<PostgresResultSlice> composite_types,
unique_ptr<PostgresResultSlice> indexes)
: SchemaCatalogEntry(catalog, info), tables(*this, std::move(tables)),
indexes(*this, std::move(indexes)), types(*this, std::move(enums), std::move(composite_types)) {
: SchemaCatalogEntry(catalog, info), tables(*this, std::move(tables)), indexes(*this, std::move(indexes)),
types(*this, std::move(enums), std::move(composite_types)) {
}

bool PostgresSchemaEntry::SchemaIsInternal(const string &name) {
Expand Down
15 changes: 7 additions & 8 deletions src/storage/postgres_schema_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,11 @@ void PostgresSchemaSet::LoadEntries(ClientContext &context) {
for (idx_t row = 0; row < rows; row++) {
auto oid = result->GetInt64(row, 0);
auto schema_name = result->GetString(row, 1);
CreateSchemaInfo info;
info.schema = schema_name;
info.internal = PostgresSchemaEntry::SchemaIsInternal(schema_name);
auto schema =
make_uniq<PostgresSchemaEntry>(catalog, info, std::move(tables[row]), std::move(enums[row]),
std::move(composite_types[row]), std::move(indexes[row]));
CreateSchemaInfo info;
info.schema = schema_name;
info.internal = PostgresSchemaEntry::SchemaIsInternal(schema_name);
auto schema = make_uniq<PostgresSchemaEntry>(catalog, info, std::move(tables[row]), std::move(enums[row]),
std::move(composite_types[row]), std::move(indexes[row]));
CreateEntry(std::move(schema));
}
}
Expand All @@ -76,8 +75,8 @@ optional_ptr<CatalogEntry> PostgresSchemaSet::CreateSchema(ClientContext &contex

string create_sql = "CREATE SCHEMA " + KeywordHelper::WriteQuoted(info.schema, '"');
transaction.Query(create_sql);
auto info_copy = info.Copy();
info.internal = PostgresSchemaEntry::SchemaIsInternal(info_copy->schema);
auto info_copy = info.Copy();
info.internal = PostgresSchemaEntry::SchemaIsInternal(info_copy->schema);
auto schema_entry = make_uniq<PostgresSchemaEntry>(catalog, info_copy->Cast<CreateSchemaInfo>());
return CreateEntry(std::move(schema_entry));
}
Expand Down
69 changes: 51 additions & 18 deletions src/storage/postgres_table_set.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#include "storage/postgres_table_set.hpp"
#include "storage/postgres_transaction.hpp"
#include "storage/postgres_table_entry.hpp"
#include "storage/postgres_view_entry.hpp"
#include "duckdb/parser/parsed_data/create_table_info.hpp"
#include "duckdb/parser/constraints/not_null_constraint.hpp"
#include "duckdb/parser/constraints/unique_constraint.hpp"
#include "duckdb/parser/expression/constant_expression.hpp"
#include "duckdb/planner/parsed_data/bound_create_table_info.hpp"
#include "duckdb/catalog/dependency_list.hpp"
#include "duckdb/parser/parsed_data/create_table_info.hpp"
#include "duckdb/parser/parsed_data/create_view_info.hpp"
#include "duckdb/parser/constraints/list.hpp"
#include "storage/postgres_schema_entry.hpp"
#include "duckdb/parser/parser.hpp"
Expand All @@ -20,7 +23,7 @@ PostgresTableSet::PostgresTableSet(PostgresSchemaEntry &schema, unique_ptr<Postg

string PostgresTableSet::GetInitializeQuery() {
return R"(
SELECT pg_namespace.oid, relname, relpages, attname,
SELECT pg_namespace.oid, relname, relkind, relpages, attname,
pg_type.typname type_name, atttypmod type_modifier, pg_attribute.attndims ndim
FROM pg_class
JOIN pg_namespace ON relnamespace = pg_namespace.oid
Expand All @@ -33,7 +36,7 @@ ORDER BY pg_namespace.oid, relname, attnum;

void PostgresTableSet::AddColumn(optional_ptr<PostgresTransaction> transaction,
optional_ptr<PostgresSchemaEntry> schema, PostgresResult &result, idx_t row,
PostgresTableInfo &table_info, idx_t column_offset) {
PostgresCreateInfo &pg_create_info, idx_t column_offset) {
PostgresTypeData type_info;
idx_t column_index = column_offset;
auto column_name = result.GetString(row, column_index);
Expand All @@ -44,8 +47,6 @@ void PostgresTableSet::AddColumn(optional_ptr<PostgresTransaction> transaction,

PostgresType postgres_type;
auto column_type = PostgresUtils::TypeToLogicalType(transaction, schema, type_info, postgres_type);
table_info.postgres_types.push_back(std::move(postgres_type));
table_info.postgres_names.push_back(column_name);
ColumnDefinition column(std::move(column_name), std::move(column_type));
if (!default_value.empty()) {
auto expressions = Parser::ParseExpressionList(default_value);
Expand All @@ -54,32 +55,64 @@ void PostgresTableSet::AddColumn(optional_ptr<PostgresTransaction> transaction,
}
column.SetDefaultValue(std::move(expressions[0]));
}
auto &create_info = *table_info.create_info;
create_info.columns.AddColumn(std::move(column));
pg_create_info.AddColumn(std::move(column), std::move(postgres_type), column_name);
}

static CatalogType TransformRelKind(const string &relkind) {
if (relkind == "v") {
return CatalogType::VIEW_ENTRY;
}
// For now we only support views and tables
return CatalogType::TABLE_ENTRY;
}

void PostgresTableSet::CreateEntries(PostgresTransaction &transaction, PostgresResult &result, idx_t start, idx_t end) {
vector<unique_ptr<PostgresTableInfo>> tables;
unique_ptr<PostgresTableInfo> info;
vector<unique_ptr<PostgresCreateInfo>> infos;
unique_ptr<PostgresCreateInfo> info;

for (idx_t row = start; row < end; row++) {
auto table_name = result.GetString(row, 1);
auto approx_num_pages = result.GetInt64(row, 2);
if (!info || info->GetTableName() != table_name) {
auto relname = result.GetString(row, 1);
auto relkind = result.GetString(row, 2);
auto approx_num_pages = result.GetInt64(row, 3);
if (!info || info->GetName() != relname) {
if (info) {
tables.push_back(std::move(info));
infos.push_back(std::move(info));
}
auto catalog_type = TransformRelKind(relkind);
switch (catalog_type) {
case CatalogType::TABLE_ENTRY:
info = make_uniq<PostgresTableInfo>(schema, relname);
break;
case CatalogType::VIEW_ENTRY:
info = make_uniq<PostgresViewInfo>(schema, relname);
break;
default: {
throw InternalException("Unexpected CatalogType in CreateEntries: %s",
CatalogTypeToString(catalog_type));
}
info->approx_num_pages = approx_num_pages;
}
info = make_uniq<PostgresTableInfo>(schema, table_name);
info->approx_num_pages = approx_num_pages;
}
AddColumn(&transaction, &schema, result, row, *info, 3);
}
if (info) {
tables.push_back(std::move(info));
infos.push_back(std::move(info));
}
for (auto &tbl_info : tables) {
auto table_entry = make_uniq<PostgresTableEntry>(catalog, schema, *tbl_info);
CreateEntry(std::move(table_entry));
for (auto &pg_create_info : infos) {
auto &create_info = pg_create_info->GetCreateInfo();
unique_ptr<StandardEntry> catalog_entry;
switch (create_info.type) {
case CatalogType::TABLE_ENTRY:
catalog_entry = make_uniq<PostgresTableEntry>(catalog, schema, pg_create_info->Cast<PostgresTableInfo>());
break;
case CatalogType::VIEW_ENTRY:
catalog_entry = make_uniq<PostgresViewEntry>(catalog, schema, pg_create_info->Cast<PostgresViewInfo>());
break;
default: {
throw InternalException("Unexpected CatalogType in CreateInfo: %s", CatalogTypeToString(create_info.type));
}
}
CreateEntry(std::move(catalog_entry));
}
}

Expand Down
Loading
Loading