|
7 | 7 | #include "duckdb/parser/parsed_data/create_view_info.hpp"
|
8 | 8 | #include "duckdb/catalog/catalog_entry/index_catalog_entry.hpp"
|
9 | 9 | #include "duckdb/catalog/catalog_entry/view_catalog_entry.hpp"
|
| 10 | +#include "duckdb/parser/parser.hpp" |
| 11 | +#include "duckdb/parser/statement/create_statement.hpp" |
| 12 | +#include "duckdb/parser/parsed_expression_iterator.hpp" |
| 13 | +#include "duckdb/parser/expression/columnref_expression.hpp" |
10 | 14 |
|
11 | 15 | namespace duckdb {
|
12 | 16 |
|
@@ -44,6 +48,45 @@ SQLiteTransaction &SQLiteTransaction::Get(ClientContext &context, Catalog &catal
|
44 | 48 | return Transaction::Get(context, catalog).Cast<SQLiteTransaction>();
|
45 | 49 | }
|
46 | 50 |
|
| 51 | +void ExtractColumnIds(const ParsedExpression &expr, TableCatalogEntry &table, CreateIndexInfo &info) { |
| 52 | + if (expr.GetExpressionType() == ExpressionType::COLUMN_REF) { |
| 53 | + auto &colref = expr.Cast<ColumnRefExpression>(); |
| 54 | + auto &colname = colref.GetColumnName(); |
| 55 | + auto &column_def = table.GetColumn(colname); |
| 56 | + auto index = column_def.Oid(); |
| 57 | + if (std::find(info.column_ids.begin(), info.column_ids.end(), index) == info.column_ids.end()) { |
| 58 | + info.column_ids.push_back(index); |
| 59 | + } |
| 60 | + return; |
| 61 | + } |
| 62 | + ParsedExpressionIterator::EnumerateChildren(expr, [&](const ParsedExpression &child) { |
| 63 | + ExtractColumnIds(child, table, info); |
| 64 | + }); |
| 65 | +} |
| 66 | + |
| 67 | +unique_ptr<CreateIndexInfo> FromCreateIndex(ClientContext &context, TableCatalogEntry &table, string sql) { |
| 68 | + // parse the SQL statement |
| 69 | + Parser parser; |
| 70 | + parser.ParseQuery(sql); |
| 71 | + |
| 72 | + if (parser.statements.size() != 1 || parser.statements[0]->type != StatementType::CREATE_STATEMENT) { |
| 73 | + throw BinderException( |
| 74 | + "Failed to create index from SQL string - \"%s\" - statement did not contain a single CREATE INDEX statement", |
| 75 | + sql); |
| 76 | + } |
| 77 | + auto &create_statement = parser.statements[0]->Cast<CreateStatement>(); |
| 78 | + if (create_statement.info->type != CatalogType::INDEX_ENTRY) { |
| 79 | + throw BinderException( |
| 80 | + "Failed to create view from SQL string - \"%s\" - view did not contain a CREATE INDEX statement", sql); |
| 81 | + } |
| 82 | + auto info = unique_ptr_cast<CreateInfo, CreateIndexInfo>(std::move(create_statement.info)); |
| 83 | + info->sql = std::move(sql); |
| 84 | + for(auto &expr : info->expressions) { |
| 85 | + ExtractColumnIds(*expr, table, *info); |
| 86 | + } |
| 87 | + return info; |
| 88 | +} |
| 89 | + |
47 | 90 | optional_ptr<CatalogEntry> SQLiteTransaction::GetCatalogEntry(const string &entry_name) {
|
48 | 91 | auto entry = catalog_entries.find(entry_name);
|
49 | 92 | if (entry != catalog_entries.end()) {
|
@@ -80,17 +123,18 @@ optional_ptr<CatalogEntry> SQLiteTransaction::GetCatalogEntry(const string &entr
|
80 | 123 | break;
|
81 | 124 | }
|
82 | 125 | case CatalogType::INDEX_ENTRY: {
|
83 |
| - CreateIndexInfo info; |
84 |
| - info.index_name = entry_name; |
85 |
| - info.constraint_type = IndexConstraintType::NONE; |
86 |
| - |
87 | 126 | string table_name;
|
88 | 127 | string sql;
|
89 | 128 | db->GetIndexInfo(entry_name, sql, table_name);
|
| 129 | + if (sql.empty()) { |
| 130 | + throw InternalException("SQL is empty"); |
| 131 | + } |
| 132 | + auto &table = GetCatalogEntry(table_name)->Cast<TableCatalogEntry>(); |
| 133 | + auto index_info = FromCreateIndex(*context.lock(), table, std::move(sql)); |
| 134 | + index_info->catalog = sqlite_catalog.GetName(); |
90 | 135 |
|
91 | 136 | auto index_entry =
|
92 |
| - make_uniq<SQLiteIndexEntry>(sqlite_catalog, sqlite_catalog.GetMainSchema(), info, std::move(table_name)); |
93 |
| - index_entry->sql = std::move(sql); |
| 137 | + make_uniq<SQLiteIndexEntry>(sqlite_catalog, sqlite_catalog.GetMainSchema(), *index_info, std::move(table_name)); |
94 | 138 | result = std::move(index_entry);
|
95 | 139 | break;
|
96 | 140 | }
|
|
0 commit comments