ladybug 0.20.2.dev20260907__tar.gz → 0.20.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sdist/PKG-INFO +1 -1
- sdist/ladybug-source/CMakeLists.txt +2 -2
- sdist/ladybug-source/docs/multi_parent_lifetime.md +0 -12
- sdist/ladybug-source/scripts/antlr4/Cypher.g4 +1 -1
- sdist/ladybug-source/scripts/antlr4/hash.md5 +1 -1
- sdist/ladybug-source/scripts/pip-package/setup.py +2 -13
- sdist/ladybug-source/src/antlr4/Cypher.g4 +1 -1
- sdist/ladybug-source/src/binder/bind/bind_export_database.cpp +27 -107
- sdist/ladybug-source/src/binder/bind/bind_import_database.cpp +1 -100
- sdist/ladybug-source/src/binder/query/query_graph.cpp +8 -15
- sdist/ladybug-source/src/c_api/version.cpp +1 -1
- sdist/ladybug-source/src/catalog/catalog_entry/node_table_catalog_entry.cpp +0 -3
- sdist/ladybug-source/src/catalog/catalog_entry/rel_group_catalog_entry.cpp +1 -5
- sdist/ladybug-source/src/function/export/CMakeLists.txt +1 -2
- sdist/ladybug-source/src/function/export/export_parquet_function.cpp +2 -18
- sdist/ladybug-source/src/include/binder/bound_export_database.h +0 -3
- sdist/ladybug-source/src/include/common/constants.h +0 -5
- sdist/ladybug-source/src/include/common/data_chunk/data_chunk_state.h +54 -34
- sdist/ladybug-source/src/include/function/export/export_function.h +0 -8
- sdist/ladybug-source/src/include/function/hash/hash_functions.h +1 -6
- sdist/ladybug-source/src/include/main/client_config.h +0 -26
- sdist/ladybug-source/src/include/main/client_context.h +0 -3
- sdist/ladybug-source/src/include/main/settings.h +0 -10
- sdist/ladybug-source/src/include/optimizer/count_rel_table_optimizer.h +0 -12
- sdist/ladybug-source/src/include/parser/port_db.h +0 -3
- sdist/ladybug-source/src/include/planner/operator/logical_operator.h +0 -2
- sdist/ladybug-source/src/include/processor/operator/persistent/writer/parquet/parquet_writer.h +1 -3
- sdist/ladybug-source/src/include/processor/operator/physical_operator.h +0 -2
- sdist/ladybug-source/src/include/processor/operator/scan/scan_node_table.h +1 -16
- sdist/ladybug-source/src/include/processor/operator/scan/scan_rel_table.h +9 -21
- sdist/ladybug-source/src/include/processor/plan_mapper.h +0 -4
- sdist/ladybug-source/src/include/storage/storage_version_info.h +2 -1
- sdist/ladybug-source/src/include/storage/table/arrow_node_table.h +6 -1
- sdist/ladybug-source/src/include/storage/table/arrow_rel_table.h +4 -4
- sdist/ladybug-source/src/include/storage/table/arrow_table_support.h +18 -5
- sdist/ladybug-source/src/include/storage/table/csr_node_group.h +0 -8
- sdist/ladybug-source/src/include/storage/table/rel_table.h +0 -33
- sdist/ladybug-source/src/include/storage/table/table.h +0 -6
- sdist/ladybug-source/src/main/client_context.cpp +0 -15
- sdist/ladybug-source/src/main/db_config.cpp +1 -2
- sdist/ladybug-source/src/main/settings.cpp +0 -46
- sdist/ladybug-source/src/optimizer/CMakeLists.txt +0 -1
- sdist/ladybug-source/src/optimizer/count_rel_table_optimizer.cpp +0 -675
- sdist/ladybug-source/src/optimizer/filter_push_down_optimizer.cpp +1 -6
- sdist/ladybug-source/src/optimizer/optimizer.cpp +0 -95
- sdist/ladybug-source/src/parser/transform/transform_port_db.cpp +1 -5
- sdist/ladybug-source/src/planner/operator/logical_operator.cpp +0 -2
- sdist/ladybug-source/src/planner/operator/scan/CMakeLists.txt +0 -2
- sdist/ladybug-source/src/planner/plan/plan_join_order.cpp +24 -54
- sdist/ladybug-source/src/planner/plan/plan_port_db.cpp +1 -6
- sdist/ladybug-source/src/processor/map/CMakeLists.txt +0 -2
- sdist/ladybug-source/src/processor/map/map_aggregate.cpp +1 -11
- sdist/ladybug-source/src/processor/map/plan_mapper.cpp +0 -6
- sdist/ladybug-source/src/processor/operator/aggregate/packed_filtered_count.cpp +6 -44
- sdist/ladybug-source/src/processor/operator/persistent/writer/parquet/parquet_writer.cpp +2 -7
- sdist/ladybug-source/src/processor/operator/physical_operator.cpp +0 -4
- sdist/ladybug-source/src/processor/operator/scan/CMakeLists.txt +0 -2
- sdist/ladybug-source/src/processor/operator/scan/scan_node_table.cpp +4 -71
- sdist/ladybug-source/src/processor/operator/scan/scan_rel_table.cpp +35 -22
- sdist/ladybug-source/src/processor/operator/simple/export_db.cpp +101 -30
- sdist/ladybug-source/src/processor/result/factorized_table.cpp +2 -7
- sdist/ladybug-source/src/storage/local_storage/local_node_table.cpp +12 -1
- sdist/ladybug-source/src/storage/storage_manager.cpp +12 -31
- sdist/ladybug-source/src/storage/table/arrow_node_table.cpp +13 -3
- sdist/ladybug-source/src/storage/table/arrow_rel_table.cpp +20 -7
- sdist/ladybug-source/src/storage/table/arrow_table_support.cpp +24 -20
- sdist/ladybug-source/src/storage/table/csr_node_group.cpp +1 -93
- sdist/ladybug-source/src/storage/table/ice_disk_node_table.cpp +2 -26
- sdist/ladybug-source/src/storage/table/node_group.cpp +8 -18
- sdist/ladybug-source/src/storage/table/node_table.cpp +29 -1
- sdist/ladybug-source/src/storage/table/rel_table.cpp +15 -118
- sdist/ladybug-source/third_party/antlr4_cypher/cypher_parser.cpp +3272 -3323
- sdist/ladybug-source/third_party/antlr4_cypher/include/cypher_parser.h +0 -1
- sdist/ladybug-source/tools/python_api/CMakeLists.txt +0 -81
- sdist/ladybug.egg-info/PKG-INFO +1 -1
- sdist/pyproject.toml +1 -1
- sdist/setup.py +2 -13
- sdist/ladybug-source/scripts/pip-package/split_debug_symbols.py +0 -262
- sdist/ladybug-source/src/function/export/export_indptr_function.cpp +0 -171
- sdist/ladybug-source/src/include/optimizer/group_key_predicate_push_down_optimizer.h +0 -49
- sdist/ladybug-source/src/include/planner/operator/scan/logical_count_anti_edge_chain.h +0 -116
- sdist/ladybug-source/src/include/planner/operator/scan/logical_count_extend_chain.h +0 -108
- sdist/ladybug-source/src/include/processor/operator/scan/count_anti_edge_chain.h +0 -114
- sdist/ladybug-source/src/include/processor/operator/scan/count_extend_chain.h +0 -109
- sdist/ladybug-source/src/optimizer/group_key_predicate_push_down_optimizer.cpp +0 -204
- sdist/ladybug-source/src/planner/operator/scan/logical_count_anti_edge_chain.cpp +0 -20
- sdist/ladybug-source/src/planner/operator/scan/logical_count_extend_chain.cpp +0 -21
- sdist/ladybug-source/src/processor/map/map_count_anti_edge_chain.cpp +0 -52
- sdist/ladybug-source/src/processor/map/map_count_extend_chain.cpp +0 -52
- sdist/ladybug-source/src/processor/operator/scan/count_anti_edge_chain.cpp +0 -349
- sdist/ladybug-source/src/processor/operator/scan/count_extend_chain.cpp +0 -193
sdist/PKG-INFO
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
cmake_minimum_required(VERSION 3.15)
|
|
2
2
|
|
|
3
|
-
project(Lbug VERSION 0.20.
|
|
3
|
+
project(Lbug VERSION 0.20.3 LANGUAGES CXX C)
|
|
4
4
|
|
|
5
5
|
option(SINGLE_THREADED "Single-threaded mode" FALSE)
|
|
6
6
|
if(SINGLE_THREADED)
|
|
@@ -522,7 +522,7 @@ unset(LBUG_LINK_LIBRARIES)
|
|
|
522
522
|
|
|
523
523
|
add_definitions(-DLBUG_ROOT_DIRECTORY="${PROJECT_SOURCE_DIR}")
|
|
524
524
|
add_definitions(-DLBUG_CMAKE_VERSION="${CMAKE_PROJECT_VERSION}")
|
|
525
|
-
add_definitions(-DLBUG_EXTENSION_VERSION="
|
|
525
|
+
add_definitions(-DLBUG_EXTENSION_VERSION="0.20.0")
|
|
526
526
|
|
|
527
527
|
if(BUILD_LBUG OR LBUG_API_USE_PRECOMPILED_LIB)
|
|
528
528
|
include_directories(
|
|
@@ -1,17 +1,5 @@
|
|
|
1
1
|
# Multi-parent packed child slices: lifetime & representation
|
|
2
2
|
|
|
3
|
-
> **Status update (multi-parent scan implemented):** the deferred change described below has
|
|
4
|
-
> been implemented. `PackedChildSlices` now holds a `shared_ptr<SelectionVector>` aliasing the
|
|
5
|
-
> bound (parent) chunk state's selection vector plus a prefix-sum `offsets` over ALL served
|
|
6
|
-
> parents (zeros allowed, zero-length ranges skipped by consumers). The CSR scan packs children
|
|
7
|
-
> of multiple parents per output batch in `CSRNodeGroupScanState::tryScanCachedTuplesPacked`
|
|
8
|
-
> (persistent with-cache path only). Multi-parent batches are enabled per-consumer:
|
|
9
|
-
> `ScanRelTable::setMultiParentPackedScanEnabled(true)` is set by the plan mapper only when the
|
|
10
|
-
> packed-aware `PackedFilteredCount` consumes the scan output directly. Plans that materialize
|
|
11
|
-
> the scan output across a `FactorizedTable` (e.g. when the filter predicate touches an nbr
|
|
12
|
-
> node property, which routes the property fetch through a hash join) keep the
|
|
13
|
-
> one-parent-per-batch contract — exactly the materialization hazard described below.
|
|
14
|
-
|
|
15
3
|
Context: the `enable_packed_path_extend` path reuses the adjacency-list (CSR)
|
|
16
4
|
rel scan to implement a physical packed extend. `ScanRelTable` attaches a
|
|
17
5
|
`PackedChildSlices` descriptor to the **output** `DataChunkState`
|
|
@@ -326,7 +326,7 @@ iC_ExportDatabase
|
|
|
326
326
|
: EXPORT SP DATABASE SP StringLiteral ( SP? '(' SP? iC_Options SP? ')' )? ;
|
|
327
327
|
|
|
328
328
|
iC_ImportDatabase
|
|
329
|
-
: IMPORT SP DATABASE SP StringLiteral
|
|
329
|
+
: IMPORT SP DATABASE SP StringLiteral;
|
|
330
330
|
|
|
331
331
|
iC_AttachDatabase
|
|
332
332
|
: ATTACH SP StringLiteral (SP AS SP oC_SchemaName)? SP '(' SP? DBTYPE SP oC_SymbolicName (SP? ',' SP? iC_Options)? SP? ')' ;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
c6ef6ea298ca84a5c080bae09a29c9db
|
|
@@ -91,27 +91,16 @@ class CMakeBuild(build_ext):
|
|
|
91
91
|
if os.path.exists(flags_file):
|
|
92
92
|
with open(flags_file) as f:
|
|
93
93
|
extra_cmake_flags = f.read().strip()
|
|
94
|
-
# Wheel builds must not split symbols at build time: raw .debug/dSYM
|
|
95
|
-
# artifacts packaged inside the wheel break auditwheel/delocate
|
|
96
|
-
# repair. The split happens on the final repaired wheel instead (see
|
|
97
|
-
# split_debug_symbols.py), which needs the debug info to still be
|
|
98
|
-
# present in the shipped binary.
|
|
99
|
-
no_split_flag = '-DLBUG_SPLIT_DEBUG_SYMBOLS=OFF'
|
|
100
94
|
if precompiled_lib_path:
|
|
101
95
|
self.announce("Using precompiled liblbug from %s." % precompiled_lib_path)
|
|
102
96
|
flags = (
|
|
103
|
-
'EXTRA_CMAKE_FLAGS
|
|
97
|
+
'EXTRA_CMAKE_FLAGS=-DBUILD_LBUG=FALSE -DBUILD_SHELL=FALSE '
|
|
104
98
|
'-DLBUG_API_USE_PRECOMPILED_LIB=TRUE '
|
|
105
|
-
'-DLBUG_API_PRECOMPILED_LIB_PATH=%s' %
|
|
99
|
+
'-DLBUG_API_PRECOMPILED_LIB_PATH=%s' % precompiled_lib_path
|
|
106
100
|
)
|
|
107
101
|
if extra_cmake_flags:
|
|
108
102
|
flags += ' ' + extra_cmake_flags
|
|
109
103
|
full_cmd.append(flags)
|
|
110
|
-
else:
|
|
111
|
-
flags = 'EXTRA_CMAKE_FLAGS=%s' % no_split_flag
|
|
112
|
-
if extra_cmake_flags:
|
|
113
|
-
flags += ' ' + extra_cmake_flags
|
|
114
|
-
full_cmd.append(flags)
|
|
115
104
|
subprocess.run(full_cmd, cwd=build_dir, check=True, env=env_vars)
|
|
116
105
|
self.announce("Done building native extension.")
|
|
117
106
|
self.announce("Copying native extension...")
|
|
@@ -57,7 +57,7 @@ iC_ExportDatabase
|
|
|
57
57
|
: EXPORT SP DATABASE SP StringLiteral ( SP? '(' SP? iC_Options SP? ')' )? ;
|
|
58
58
|
|
|
59
59
|
iC_ImportDatabase
|
|
60
|
-
: IMPORT SP DATABASE SP StringLiteral
|
|
60
|
+
: IMPORT SP DATABASE SP StringLiteral;
|
|
61
61
|
|
|
62
62
|
iC_AttachDatabase
|
|
63
63
|
: ATTACH SP StringLiteral (SP AS SP oC_SchemaName)? SP '(' SP? DBTYPE SP oC_SymbolicName (SP? ',' SP? iC_Options)? SP? ')' ;
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
#include "parser/parser.h"
|
|
12
12
|
#include "parser/port_db.h"
|
|
13
13
|
#include "parser/query/regular_query.h"
|
|
14
|
-
#include "storage/table/ice_disk_constants.h"
|
|
15
14
|
#include "transaction/transaction.h"
|
|
16
15
|
#include <format>
|
|
17
16
|
|
|
@@ -36,10 +35,6 @@ FileTypeInfo getFileType(case_insensitive_map_t<Value>& options) {
|
|
|
36
35
|
auto valueStr = value.getValue<std::string>();
|
|
37
36
|
StringUtils::toUpper(valueStr);
|
|
38
37
|
fileTypeInfo = FileTypeInfo{FileTypeUtils::fromString(valueStr), valueStr};
|
|
39
|
-
if (fileTypeInfo.fileType != FileType::PARQUET) {
|
|
40
|
-
throw BinderException(
|
|
41
|
-
"Export database only supports the parquet (icebug-disk CSR) format.");
|
|
42
|
-
}
|
|
43
38
|
options.erase(PortDBConstants::EXPORT_FORMAT_OPTION);
|
|
44
39
|
}
|
|
45
40
|
return fileTypeInfo;
|
|
@@ -62,134 +57,66 @@ void bindExportTableData(ExportedTableData& tableData, const std::string& query,
|
|
|
62
57
|
tableData.regularQuery = std::move(boundQuery);
|
|
63
58
|
}
|
|
64
59
|
|
|
65
|
-
static std::string getPropertyReturnList(const TableCatalogEntry& entry, const std::string& var) {
|
|
66
|
-
std::string props;
|
|
67
|
-
for (auto& property : entry.getProperties()) {
|
|
68
|
-
if (property.getType() == LogicalType::INTERNAL_ID()) {
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
props += std::format(",{}.{} as {}", var, StringUtils::quoteIdentifier(property.getName()),
|
|
72
|
-
StringUtils::quoteIdentifier(property.getName()));
|
|
73
|
-
}
|
|
74
|
-
return props;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
60
|
static std::string getExportNodeTableDataQuery(const TableCatalogEntry& entry) {
|
|
78
|
-
|
|
79
|
-
// with dense offset i, matching the CSR target/ptr values in the rel tables.
|
|
80
|
-
// Properties are aliased explicitly so parquet columns carry clean names.
|
|
81
|
-
auto props = getPropertyReturnList(entry, "a");
|
|
82
|
-
auto returns = props.empty() ? "a.*" : props.substr(1);
|
|
83
|
-
return std::format("match (a:{}) return {} order by offset(id(a))",
|
|
84
|
-
StringUtils::quoteIdentifier(entry.getName()), returns);
|
|
61
|
+
return std::format("match (a:{}) return a.*", StringUtils::quoteIdentifier(entry.getName()));
|
|
85
62
|
}
|
|
86
63
|
|
|
87
|
-
static std::string
|
|
64
|
+
static std::string getExportRelTableDataQuery(const TableCatalogEntry& relGroupEntry,
|
|
88
65
|
const NodeTableCatalogEntry& srcEntry, const NodeTableCatalogEntry& dstEntry) {
|
|
89
|
-
|
|
90
|
-
// (source offset, target offset). The source offset is encoded by indptr.
|
|
91
|
-
return std::format("match (a:{})-[r:{}]->(b:{}) return offset(id(b)) as target{} "
|
|
92
|
-
"order by offset(id(a)), offset(id(b));",
|
|
66
|
+
return std::format("match (a:{})-[r:{}]->(b:{}) return a.{},b.{},r.*;",
|
|
93
67
|
StringUtils::quoteIdentifier(srcEntry.getName()),
|
|
94
68
|
StringUtils::quoteIdentifier(relGroupEntry.getName()),
|
|
95
69
|
StringUtils::quoteIdentifier(dstEntry.getName()),
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
static std::string getExportRelIndptrQuery(const TableCatalogEntry& relGroupEntry,
|
|
100
|
-
const NodeTableCatalogEntry& srcEntry, const NodeTableCatalogEntry& dstEntry) {
|
|
101
|
-
// One row per source node (OPTIONAL MATCH keeps zero-degree nodes), consumed by
|
|
102
|
-
// the indptr export function which sorts by src and prefix-sums the degrees.
|
|
103
|
-
return std::format(
|
|
104
|
-
"match (a:{}) optional match (a)-[r:{}]->(b:{}) return offset(id(a)) as src, "
|
|
105
|
-
"count(r) as degree;",
|
|
106
|
-
StringUtils::quoteIdentifier(srcEntry.getName()),
|
|
107
|
-
StringUtils::quoteIdentifier(relGroupEntry.getName()),
|
|
108
|
-
StringUtils::quoteIdentifier(dstEntry.getName()));
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
static std::string getExportRelFlatQuery(const TableCatalogEntry& relGroupEntry,
|
|
112
|
-
const NodeTableCatalogEntry& srcEntry, const NodeTableCatalogEntry& dstEntry) {
|
|
113
|
-
// Flat relationship file for native re-import: source/target primary-key values
|
|
114
|
-
// (COPY FROM resolves them back to node offsets) followed by edge properties.
|
|
115
|
-
return std::format("match (a:{})-[r:{}]->(b:{}) return {}.{} as {}, {}.{} as {}{};",
|
|
116
|
-
StringUtils::quoteIdentifier(srcEntry.getName()),
|
|
117
|
-
StringUtils::quoteIdentifier(relGroupEntry.getName()),
|
|
118
|
-
StringUtils::quoteIdentifier(dstEntry.getName()), "a",
|
|
119
|
-
StringUtils::quoteIdentifier(srcEntry.getPrimaryKeyDefinition().getName()),
|
|
120
|
-
StringUtils::quoteIdentifier("from"), "b",
|
|
121
|
-
StringUtils::quoteIdentifier(dstEntry.getPrimaryKeyDefinition().getName()),
|
|
122
|
-
StringUtils::quoteIdentifier("to"), getPropertyReturnList(relGroupEntry, "r"));
|
|
70
|
+
StringUtils::quoteIdentifier(srcEntry.getPrimaryKeyName()),
|
|
71
|
+
StringUtils::quoteIdentifier(dstEntry.getPrimaryKeyName()));
|
|
123
72
|
}
|
|
124
73
|
|
|
125
74
|
static std::vector<ExportedTableData> getExportInfo(const Catalog& catalog,
|
|
126
|
-
main::ClientContext* context, Binder* binder,
|
|
75
|
+
main::ClientContext* context, Binder* binder, FileTypeInfo& fileTypeInfo) {
|
|
127
76
|
auto transaction = Transaction::Get(*context);
|
|
128
77
|
std::vector<ExportedTableData> exportData;
|
|
129
78
|
for (auto entry : catalog.getNodeTableEntries(transaction, false /*useInternal*/)) {
|
|
130
79
|
ExportedTableData tableData;
|
|
131
80
|
tableData.tableName = entry->getName();
|
|
132
|
-
tableData.fileName =
|
|
81
|
+
tableData.fileName =
|
|
82
|
+
entry->getName() + "." + StringUtils::getLower(fileTypeInfo.fileTypeStr);
|
|
133
83
|
auto query = getExportNodeTableDataQuery(*entry);
|
|
134
84
|
bindExportTableData(tableData, query, context, binder);
|
|
135
85
|
exportData.push_back(std::move(tableData));
|
|
136
86
|
}
|
|
137
87
|
for (auto entry : catalog.getRelGroupEntries(transaction, false /* useInternal */)) {
|
|
138
88
|
auto& relGroupEntry = entry->constCast<RelGroupCatalogEntry>();
|
|
139
|
-
if (relGroupEntry.getRelEntryInfos().size() != 1) {
|
|
140
|
-
throw BinderException(std::format(
|
|
141
|
-
"Export database: rel table {} connects multiple node pairs, which is not "
|
|
142
|
-
"supported for icebug-disk CSR export yet.",
|
|
143
|
-
relGroupEntry.getName()));
|
|
144
|
-
}
|
|
145
89
|
for (auto& info : relGroupEntry.getRelEntryInfos()) {
|
|
90
|
+
ExportedTableData tableData;
|
|
146
91
|
auto srcTableID = info.nodePair.srcTableID;
|
|
147
92
|
auto dstTableID = info.nodePair.dstTableID;
|
|
148
93
|
auto& srcEntry = catalog.getTableCatalogEntry(transaction, srcTableID)
|
|
149
94
|
->constCast<NodeTableCatalogEntry>();
|
|
150
95
|
auto& dstEntry = catalog.getTableCatalogEntry(transaction, dstTableID)
|
|
151
96
|
->constCast<NodeTableCatalogEntry>();
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
indptrData.tableName = entry->getName();
|
|
160
|
-
indptrData.fileName = std::format("indptr_{}.parquet", relGroupEntry.getName());
|
|
161
|
-
indptrData.isIndptr = true;
|
|
162
|
-
bindExportTableData(indptrData,
|
|
163
|
-
getExportRelIndptrQuery(relGroupEntry, srcEntry, dstEntry), context, binder);
|
|
164
|
-
exportData.push_back(std::move(indptrData));
|
|
165
|
-
// Flat relationship file (from/to primary-key values + properties), used by
|
|
166
|
-
// IMPORT DATABASE to ingest the relationship table into native storage. It is
|
|
167
|
-
// ignored when the export is mounted as icebug-disk (which uses the CSR files).
|
|
168
|
-
ExportedTableData flatRelData;
|
|
169
|
-
flatRelData.tableName = entry->getName();
|
|
170
|
-
flatRelData.fileName = std::format("rels_{}.parquet", relGroupEntry.getName());
|
|
171
|
-
bindExportTableData(flatRelData,
|
|
172
|
-
getExportRelFlatQuery(relGroupEntry, srcEntry, dstEntry), context, binder);
|
|
173
|
-
exportData.push_back(std::move(flatRelData));
|
|
97
|
+
tableData.tableName = entry->getName();
|
|
98
|
+
tableData.fileName =
|
|
99
|
+
std::format("{}_{}_{}.{}", relGroupEntry.getName(), srcEntry.getName(),
|
|
100
|
+
dstEntry.getName(), StringUtils::getLower(fileTypeInfo.fileTypeStr));
|
|
101
|
+
auto query = getExportRelTableDataQuery(relGroupEntry, srcEntry, dstEntry);
|
|
102
|
+
bindExportTableData(tableData, query, context, binder);
|
|
103
|
+
exportData.push_back(std::move(tableData));
|
|
174
104
|
}
|
|
175
105
|
}
|
|
176
106
|
|
|
177
|
-
// Index aux tables (e.g. the FTS internal stopwords table) are not part of the CSR
|
|
178
|
-
// layout, but index.cypher needs them on import when the original stopwords source
|
|
179
|
-
// table no longer exists. Export them as <tableName>.parquet; the FTS index's
|
|
180
|
-
// toCypher references the file path in that case.
|
|
181
107
|
for (auto indexEntry : catalog.getIndexEntries(transaction)) {
|
|
182
|
-
|
|
183
|
-
|
|
108
|
+
// Export
|
|
109
|
+
ExportedTableData tableData;
|
|
110
|
+
auto entry = indexEntry->getTableEntryToExport(context);
|
|
111
|
+
if (entry == nullptr) {
|
|
184
112
|
continue;
|
|
185
113
|
}
|
|
186
|
-
|
|
187
|
-
tableData.tableName =
|
|
188
|
-
tableData.fileName =
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
context, binder);
|
|
114
|
+
DASSERT(entry->getTableType() == TableType::NODE);
|
|
115
|
+
tableData.tableName = entry->getName();
|
|
116
|
+
tableData.fileName =
|
|
117
|
+
entry->getName() + "." + StringUtils::getLower(fileTypeInfo.fileTypeStr);
|
|
118
|
+
auto query = getExportNodeTableDataQuery(*entry);
|
|
119
|
+
bindExportTableData(tableData, query, context, binder);
|
|
193
120
|
exportData.push_back(std::move(tableData));
|
|
194
121
|
}
|
|
195
122
|
return exportData;
|
|
@@ -231,17 +158,10 @@ std::unique_ptr<BoundStatement> Binder::bindExportDatabaseClause(const Statement
|
|
|
231
158
|
}
|
|
232
159
|
auto exportSchemaOnly = schemaOnly(parsedOptions, exportDB);
|
|
233
160
|
if (!exportSchemaOnly && fileTypeInfo.fileType != FileType::CSV && parsedOptions.size() != 0) {
|
|
234
|
-
throw BinderException{"
|
|
235
|
-
"(icebug-disk CSR) format."};
|
|
161
|
+
throw BinderException{"Only export to csv can have options."};
|
|
236
162
|
}
|
|
237
163
|
auto exportData =
|
|
238
164
|
getExportInfo(*Catalog::Get(*clientContext), clientContext, this, fileTypeInfo);
|
|
239
|
-
// Stamp every exported parquet file with the icebug-disk format version so that
|
|
240
|
-
// IceDiskUtils::checkVersionCompatibility can validate it when the export is mounted.
|
|
241
|
-
if (fileTypeInfo.fileType == FileType::PARQUET && !exportSchemaOnly) {
|
|
242
|
-
parsedOptions.insert_or_assign(PortDBConstants::ICEBUG_DISK_VERSION_OPTION,
|
|
243
|
-
Value{std::string{storage::IceDiskConstants::CURRENT_VERSION}});
|
|
244
|
-
}
|
|
245
165
|
auto boundFilePath = VirtualFileSystem::GetUnsafe(*clientContext)
|
|
246
166
|
->expandPath(clientContext, exportDB.getFilePath());
|
|
247
167
|
return std::make_unique<BoundExportDatabase>(boundFilePath, fileTypeInfo, std::move(exportData),
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
#include "common/string_utils.h"
|
|
7
7
|
#include "main/client_context.h"
|
|
8
8
|
#include "parser/copy.h"
|
|
9
|
-
#include "parser/ddl/create_table.h"
|
|
10
9
|
#include "parser/parser.h"
|
|
11
10
|
#include "parser/port_db.h"
|
|
12
11
|
#include <format>
|
|
@@ -84,73 +83,6 @@ static std::string getCopyFilePath(const std::string& boundFilePath, const std::
|
|
|
84
83
|
return path;
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
// Removes the `WITH (storage = '<dir>', format = 'icebug-disk')` clauses that EXPORT DATABASE
|
|
88
|
-
// attaches to CREATE TABLE statements in schema.cypher, so that IMPORT DATABASE (without an
|
|
89
|
-
// explicit `storage_format = 'icebug-disk'` override) creates native tables instead of mounting
|
|
90
|
-
// the exported parquet files in place.
|
|
91
|
-
static std::string stripIcebugStorageClauses(const std::string& schema) {
|
|
92
|
-
std::string result = schema;
|
|
93
|
-
size_t searchFrom = 0;
|
|
94
|
-
size_t pos;
|
|
95
|
-
while ((pos = result.find(" WITH (", searchFrom)) != std::string::npos) {
|
|
96
|
-
auto end = result.find(')', pos);
|
|
97
|
-
if (end == std::string::npos) {
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
auto clause = result.substr(pos, end - pos);
|
|
101
|
-
if (clause.find("format = 'icebug-disk'") != std::string::npos &&
|
|
102
|
-
clause.find("storage = '") != std::string::npos) {
|
|
103
|
-
result.erase(pos, end - pos + 1);
|
|
104
|
-
searchFrom = pos;
|
|
105
|
-
} else {
|
|
106
|
-
searchFrom = end;
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return result;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Generates COPY statements that ingest the exported parquet data files into the native
|
|
113
|
-
// tables created by the (stripped) schema.cypher statements. The exported layout is
|
|
114
|
-
// nodes_<table>.parquet for node tables and rels_<rel>.parquet (from/to primary-key
|
|
115
|
-
// columns + edge properties) for relationship tables.
|
|
116
|
-
static std::string getNativeCopyStatements(VirtualFileSystem* vfs, const std::string& boundFilePath,
|
|
117
|
-
const std::string& schemaQuery, main::ClientContext* context) {
|
|
118
|
-
std::string copies;
|
|
119
|
-
if (schemaQuery.empty()) {
|
|
120
|
-
return copies;
|
|
121
|
-
}
|
|
122
|
-
for (auto& parsedStatement : Parser::parseQuery(schemaQuery)) {
|
|
123
|
-
if (parsedStatement->getStatementType() != StatementType::CREATE_TABLE) {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
auto& createTable = parsedStatement->constCast<CreateTable>();
|
|
127
|
-
const auto& info = *createTable.getInfo();
|
|
128
|
-
auto isRel = info.type == TableType::REL;
|
|
129
|
-
auto dataFile = isRel ? std::format("rels_{}.parquet", info.tableName) :
|
|
130
|
-
std::format("nodes_{}.parquet", info.tableName);
|
|
131
|
-
auto filePath = getCopyFilePath(boundFilePath, dataFile);
|
|
132
|
-
if (!vfs->fileOrPathExists(vfs->joinPath(boundFilePath, dataFile), context)) {
|
|
133
|
-
continue;
|
|
134
|
-
}
|
|
135
|
-
// Explicit column list for node tables (covers SERIAL pk values, which COPY FROM
|
|
136
|
-
// would otherwise auto-generate). Rel tables rely on positional binding: the flat
|
|
137
|
-
// file already stores from/to key columns followed by properties in schema order.
|
|
138
|
-
std::string columns;
|
|
139
|
-
if (!isRel) {
|
|
140
|
-
std::vector<std::string> columnList;
|
|
141
|
-
for (auto& property : info.propertyDefinitions) {
|
|
142
|
-
columnList.push_back(StringUtils::quoteIdentifier(property.getName()));
|
|
143
|
-
}
|
|
144
|
-
if (!columnList.empty()) {
|
|
145
|
-
columns = std::format(" ({})", StringUtils::join(columnList, ", "));
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
copies += std::format("COPY {}{} FROM \"{}\";\n",
|
|
149
|
-
StringUtils::quoteIdentifier(info.tableName), columns, filePath);
|
|
150
|
-
}
|
|
151
|
-
return copies;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
86
|
std::unique_ptr<BoundStatement> Binder::bindImportDatabaseClause(const Statement& statement) {
|
|
155
87
|
auto& importDB = statement.constCast<ImportDB>();
|
|
156
88
|
auto fs = VirtualFileSystem::GetUnsafe(*clientContext);
|
|
@@ -158,40 +90,9 @@ std::unique_ptr<BoundStatement> Binder::bindImportDatabaseClause(const Statement
|
|
|
158
90
|
if (!fs->fileOrPathExists(boundFilePath, clientContext)) {
|
|
159
91
|
throw BinderException(std::format("Directory {} does not exist.", boundFilePath));
|
|
160
92
|
}
|
|
161
|
-
// By default the exported icebug-disk data files are ingested into native tables.
|
|
162
|
-
// An explicit `storage_format = 'icebug-disk'` override mounts the parquet files in
|
|
163
|
-
// place (i.e. the database is opened directly against the exported directory).
|
|
164
|
-
bool mountIcebug = false;
|
|
165
|
-
auto parsingOptions = bindParsingOptions(importDB.getParsingOptionsRef());
|
|
166
|
-
if (parsingOptions.contains(PortDBConstants::IMPORT_STORAGE_FORMAT_OPTION)) {
|
|
167
|
-
auto& value = parsingOptions.at(PortDBConstants::IMPORT_STORAGE_FORMAT_OPTION);
|
|
168
|
-
if (value.getDataType().getLogicalTypeID() != LogicalTypeID::STRING) {
|
|
169
|
-
throw BinderException("The type of storage_format option must be a string.");
|
|
170
|
-
}
|
|
171
|
-
auto valueStr = StringUtils::getUpper(value.getValue<std::string>());
|
|
172
|
-
if (valueStr != "ICEBUG-DISK") {
|
|
173
|
-
throw BinderException(std::format(
|
|
174
|
-
"Unsupported import database storage format '{}'. Valid options are: icebug-disk.",
|
|
175
|
-
value.getValue<std::string>()));
|
|
176
|
-
}
|
|
177
|
-
mountIcebug = true;
|
|
178
|
-
parsingOptions.erase(PortDBConstants::IMPORT_STORAGE_FORMAT_OPTION);
|
|
179
|
-
}
|
|
180
|
-
if (!parsingOptions.empty()) {
|
|
181
|
-
throw BinderException(
|
|
182
|
-
std::format("Unrecognized import database option: {}.", parsingOptions.begin()->first));
|
|
183
|
-
}
|
|
184
93
|
std::string finalQueryStatements;
|
|
185
|
-
|
|
94
|
+
finalQueryStatements +=
|
|
186
95
|
getQueryFromFile(fs, boundFilePath, PortDBConstants::SCHEMA_FILE_NAME, clientContext);
|
|
187
|
-
if (!mountIcebug) {
|
|
188
|
-
schemaQuery = stripIcebugStorageClauses(schemaQuery);
|
|
189
|
-
finalQueryStatements += schemaQuery;
|
|
190
|
-
finalQueryStatements +=
|
|
191
|
-
getNativeCopyStatements(fs, boundFilePath, schemaQuery, clientContext);
|
|
192
|
-
} else {
|
|
193
|
-
finalQueryStatements += schemaQuery;
|
|
194
|
-
}
|
|
195
96
|
// replace the path in copy from statements with the bound path
|
|
196
97
|
auto copyQuery =
|
|
197
98
|
getQueryFromFile(fs, boundFilePath, PortDBConstants::COPY_FILE_NAME, clientContext);
|
|
@@ -47,13 +47,6 @@ std::unordered_set<uint32_t> SubqueryGraph::getNodeNbrPositions() const {
|
|
|
47
47
|
|
|
48
48
|
std::unordered_set<uint32_t> SubqueryGraph::getRelNbrPositions() const {
|
|
49
49
|
std::unordered_set<uint32_t> result;
|
|
50
|
-
// Nodes in the subgraph: explicitly selected nodes plus endpoints of selected rels
|
|
51
|
-
// (rel-implied nodes). A neighboring rel is any unselected rel touching any of them.
|
|
52
|
-
// Considering rel-implied nodes allows the join enumerator to attach a rel to a
|
|
53
|
-
// subgraph through the node bound by a previous extend (e.g. planning
|
|
54
|
-
// (a)-[e1]->(b)-[e2]->(c) as scan(a) -> extend(e1) -> extend(e2)), instead of
|
|
55
|
-
// requiring an explicit node-table scan join first.
|
|
56
|
-
const auto nodePosSet = getNodePositionsIgnoringNodeSelector();
|
|
57
50
|
for (auto relPos = 0u; relPos < queryGraph.getNumQueryRels(); ++relPos) {
|
|
58
51
|
if (queryRelsSelector[relPos]) { // rel already in subgraph, cannot be rel neighbour
|
|
59
52
|
continue;
|
|
@@ -61,7 +54,7 @@ std::unordered_set<uint32_t> SubqueryGraph::getRelNbrPositions() const {
|
|
|
61
54
|
auto rel = queryGraph.getQueryRel(relPos);
|
|
62
55
|
auto srcNodePos = queryGraph.getQueryNodeIdx(*rel->getSrcNode());
|
|
63
56
|
auto dstNodePos = queryGraph.getQueryNodeIdx(*rel->getDstNode());
|
|
64
|
-
if (
|
|
57
|
+
if (queryNodesSelector[srcNodePos] || queryNodesSelector[dstNodePos]) {
|
|
65
58
|
result.insert(relPos);
|
|
66
59
|
}
|
|
67
60
|
}
|
|
@@ -84,13 +77,13 @@ subquery_graph_set_t SubqueryGraph::getNbrSubgraphs(uint32_t size) const {
|
|
|
84
77
|
|
|
85
78
|
std::vector<uint32_t> SubqueryGraph::getConnectedNodePos(const SubqueryGraph& nbr) const {
|
|
86
79
|
std::vector<uint32_t> result;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
for (auto& nodePos :
|
|
93
|
-
if (
|
|
80
|
+
for (auto& nodePos : getNodeNbrPositions()) {
|
|
81
|
+
if (nbr.queryNodesSelector[nodePos]) {
|
|
82
|
+
result.push_back(nodePos);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
for (auto& nodePos : nbr.getNodeNbrPositions()) {
|
|
86
|
+
if (queryNodesSelector[nodePos]) {
|
|
94
87
|
result.push_back(nodePos);
|
|
95
88
|
}
|
|
96
89
|
}
|
|
@@ -7,7 +7,7 @@ char* lbug_get_version() {
|
|
|
7
7
|
LBUG_C_API_GUARD_BEGIN
|
|
8
8
|
auto version = lbug::main::Version::getVersion();
|
|
9
9
|
if (version == nullptr || version[0] == '\0') {
|
|
10
|
-
version = "0.20.
|
|
10
|
+
version = "0.20.3";
|
|
11
11
|
}
|
|
12
12
|
return convertToOwnedCString(version);
|
|
13
13
|
LBUG_C_API_GUARD_END(nullptr)
|
|
@@ -202,9 +202,6 @@ std::string NodeTableCatalogEntry::toCypher(const ToCypherInfo& /*info*/) const
|
|
|
202
202
|
base += std::format(" PARTITION BY {}({}) PARTITIONS {}", method,
|
|
203
203
|
common::StringUtils::quoteIdentifier(partitionColumnName), numPartitions);
|
|
204
204
|
}
|
|
205
|
-
if (storageFormat == common::StorageFormat::ICEBUG_DISK) {
|
|
206
|
-
base += std::format(" WITH (storage = '{}', format = 'icebug-disk')", storage);
|
|
207
|
-
}
|
|
208
205
|
return base + ";";
|
|
209
206
|
}
|
|
210
207
|
|
|
@@ -248,11 +248,7 @@ std::string RelGroupCatalogEntry::toCypher(const ToCypherInfo& info) const {
|
|
|
248
248
|
}
|
|
249
249
|
}
|
|
250
250
|
ss << ", " << propertyCollection.toCypher()
|
|
251
|
-
<< getMultiplicityStr(srcMultiplicity, dstMultiplicity);
|
|
252
|
-
if (storageFormat == common::StorageFormat::ICEBUG_DISK) {
|
|
253
|
-
ss << std::format(" WITH (storage = '{}', format = 'icebug-disk')", storage);
|
|
254
|
-
}
|
|
255
|
-
ss << ");";
|
|
251
|
+
<< getMultiplicityStr(srcMultiplicity, dstMultiplicity) << ");";
|
|
256
252
|
return ss.str();
|
|
257
253
|
}
|
|
258
254
|
|
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
#include "processor/operator/persistent/writer/parquet/parquet_writer.h"
|
|
8
8
|
#include "processor/result/factorized_table.h"
|
|
9
9
|
#include "storage/buffer_manager/memory_manager.h"
|
|
10
|
-
#include "storage/table/ice_disk_constants.h"
|
|
11
10
|
#include <format>
|
|
12
11
|
|
|
13
12
|
namespace lbug {
|
|
@@ -19,14 +18,11 @@ using namespace processor;
|
|
|
19
18
|
struct ParquetOptions {
|
|
20
19
|
lbug_parquet::format::CompressionCodec::type codec =
|
|
21
20
|
lbug_parquet::format::CompressionCodec::SNAPPY;
|
|
22
|
-
std::vector<lbug_parquet::format::KeyValue> keyValueMetadata;
|
|
23
21
|
|
|
24
22
|
explicit ParquetOptions(case_insensitive_map_t<common::Value> parsingOptions) {
|
|
25
23
|
for (auto& [name, value] : parsingOptions) {
|
|
26
24
|
if (name == "COMPRESSION") {
|
|
27
25
|
setCompression(value);
|
|
28
|
-
} else if (name == storage::IceDiskConstants::VERSION_METADATA_KEY) {
|
|
29
|
-
setVersionMetadata(value);
|
|
30
26
|
} else {
|
|
31
27
|
throw common::RuntimeException{
|
|
32
28
|
std::format("Unrecognized parquet option: {}.", name)};
|
|
@@ -34,18 +30,6 @@ struct ParquetOptions {
|
|
|
34
30
|
}
|
|
35
31
|
}
|
|
36
32
|
|
|
37
|
-
void setVersionMetadata(common::Value& value) {
|
|
38
|
-
if (value.getDataType().getLogicalTypeID() != LogicalTypeID::STRING) {
|
|
39
|
-
throw common::RuntimeException{std::format(
|
|
40
|
-
"Parquet {} option expects a string value, got: {}.",
|
|
41
|
-
storage::IceDiskConstants::VERSION_METADATA_KEY, value.getDataType().toString())};
|
|
42
|
-
}
|
|
43
|
-
lbug_parquet::format::KeyValue kv;
|
|
44
|
-
kv.__set_key(std::string(storage::IceDiskConstants::VERSION_METADATA_KEY));
|
|
45
|
-
kv.__set_value(value.getValue<std::string>());
|
|
46
|
-
keyValueMetadata.push_back(std::move(kv));
|
|
47
|
-
}
|
|
48
|
-
|
|
49
33
|
void setCompression(common::Value& value) {
|
|
50
34
|
if (value.getDataType().getLogicalTypeID() != LogicalTypeID::STRING) {
|
|
51
35
|
throw common::RuntimeException{
|
|
@@ -117,8 +101,8 @@ struct ExportParquetSharedState : public ExportFuncSharedState {
|
|
|
117
101
|
auto& exportParquetBindData = bindData.constCast<ExportParquetBindData>();
|
|
118
102
|
writer = std::make_unique<ParquetWriter>(exportParquetBindData.fileName,
|
|
119
103
|
common::LogicalType::copy(exportParquetBindData.types),
|
|
120
|
-
exportParquetBindData.columnNames, exportParquetBindData.parquetOptions.codec,
|
|
121
|
-
|
|
104
|
+
exportParquetBindData.columnNames, exportParquetBindData.parquetOptions.codec,
|
|
105
|
+
&context);
|
|
122
106
|
}
|
|
123
107
|
};
|
|
124
108
|
|
|
@@ -10,9 +10,6 @@ namespace binder {
|
|
|
10
10
|
struct ExportedTableData {
|
|
11
11
|
std::string tableName;
|
|
12
12
|
std::string fileName;
|
|
13
|
-
// True for CSR indptr tables, which are computed (prefix-summed) rather than
|
|
14
|
-
// plain-copied, and need the dedicated indptr export function in the planner.
|
|
15
|
-
bool isIndptr = false;
|
|
16
13
|
std::unique_ptr<BoundRegularQuery> regularQuery;
|
|
17
14
|
std::vector<std::string> columnNames;
|
|
18
15
|
std::vector<common::LogicalType> columnTypes;
|
|
@@ -213,11 +213,6 @@ struct PortDBConstants {
|
|
|
213
213
|
static constexpr const char* SCHEMA_ONLY_OPTION = "SCHEMA_ONLY";
|
|
214
214
|
static constexpr const char* EXPORT_FORMAT_OPTION = "FORMAT";
|
|
215
215
|
static constexpr const char* DEFAULT_EXPORT_FORMAT_OPTION = "PARQUET";
|
|
216
|
-
// IMPORT DATABASE option: when set to 'icebug-disk', the exported icedisk files are
|
|
217
|
-
// mounted in place instead of being ingested into native tables (the default).
|
|
218
|
-
static constexpr const char* IMPORT_STORAGE_FORMAT_OPTION = "STORAGE_FORMAT";
|
|
219
|
-
// Parquet key-value metadata key written on every EXPORT DATABASE data file.
|
|
220
|
-
static constexpr const char* ICEBUG_DISK_VERSION_OPTION = "icebug_disk_version";
|
|
221
216
|
};
|
|
222
217
|
|
|
223
218
|
struct WarningConstants {
|