@lix-js/sdk 0.6.0-preview.2 → 0.6.0-preview.3
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.
- package/SKILL.md +4 -5
- package/dist/engine-wasm/wasm/lix_engine.js +1 -1
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/generated/builtin-schemas.d.ts +87 -162
- package/dist/generated/builtin-schemas.js +139 -236
- package/dist/open-lix.d.ts +1 -1
- package/dist-engine-src/src/binary_cas/types.rs +0 -6
- package/dist-engine-src/src/catalog/context.rs +412 -0
- package/dist-engine-src/src/catalog/mod.rs +10 -0
- package/dist-engine-src/src/catalog/schema.rs +4 -0
- package/dist-engine-src/src/catalog/snapshot.rs +1114 -0
- package/dist-engine-src/src/cel/mod.rs +1 -1
- package/dist-engine-src/src/cel/provider.rs +1 -1
- package/dist-engine-src/src/commit_graph/context.rs +328 -1015
- package/dist-engine-src/src/commit_graph/mod.rs +2 -3
- package/dist-engine-src/src/commit_graph/types.rs +7 -43
- package/dist-engine-src/src/commit_graph/walker.rs +57 -81
- package/dist-engine-src/src/commit_store/codec.rs +887 -0
- package/dist-engine-src/src/commit_store/context.rs +944 -0
- package/dist-engine-src/src/commit_store/materialization.rs +84 -0
- package/dist-engine-src/src/commit_store/mod.rs +16 -0
- package/dist-engine-src/src/commit_store/storage.rs +600 -0
- package/dist-engine-src/src/commit_store/types.rs +215 -0
- package/dist-engine-src/src/common/identity.rs +15 -5
- package/dist-engine-src/src/common/json_pointer.rs +67 -0
- package/dist-engine-src/src/common/metadata.rs +17 -12
- package/dist-engine-src/src/common/mod.rs +5 -5
- package/dist-engine-src/src/domain.rs +324 -0
- package/dist-engine-src/src/engine.rs +29 -43
- package/dist-engine-src/src/entity_identity.rs +238 -118
- package/dist-engine-src/src/functions/context.rs +17 -52
- package/dist-engine-src/src/functions/deterministic.rs +1 -1
- package/dist-engine-src/src/functions/mod.rs +1 -1
- package/dist-engine-src/src/functions/provider.rs +4 -4
- package/dist-engine-src/src/functions/state.rs +39 -66
- package/dist-engine-src/src/functions/types.rs +1 -1
- package/dist-engine-src/src/init.rs +204 -151
- package/dist-engine-src/src/json_store/context.rs +354 -60
- package/dist-engine-src/src/json_store/encoded.rs +6 -6
- package/dist-engine-src/src/json_store/mod.rs +4 -1
- package/dist-engine-src/src/json_store/store.rs +884 -11
- package/dist-engine-src/src/json_store/types.rs +166 -1
- package/dist-engine-src/src/lib.rs +10 -9
- package/dist-engine-src/src/live_state/context.rs +608 -830
- package/dist-engine-src/src/live_state/mod.rs +3 -3
- package/dist-engine-src/src/live_state/overlay.rs +7 -7
- package/dist-engine-src/src/live_state/reader.rs +5 -5
- package/dist-engine-src/src/live_state/types.rs +19 -36
- package/dist-engine-src/src/live_state/visibility.rs +19 -14
- package/dist-engine-src/src/plugin/archive.rs +3 -6
- package/dist-engine-src/src/plugin/install.rs +0 -18
- package/dist-engine-src/src/plugin/plugin_manifest.json +0 -1
- package/dist-engine-src/src/schema/annotations/defaults.rs +2 -7
- package/dist-engine-src/src/schema/builtin/lix_account.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_active_account.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_change.json +11 -10
- package/dist-engine-src/src/schema/builtin/lix_change_author.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_commit.json +8 -46
- package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +29 -22
- package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_key_value.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_label.json +10 -3
- package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
- package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +2 -8
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -1
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -1
- package/dist-engine-src/src/schema/builtin/mod.rs +10 -59
- package/dist-engine-src/src/schema/compatibility.rs +787 -0
- package/dist-engine-src/src/schema/definition.json +47 -17
- package/dist-engine-src/src/schema/definition.rs +202 -96
- package/dist-engine-src/src/schema/key.rs +9 -77
- package/dist-engine-src/src/schema/mod.rs +4 -4
- package/dist-engine-src/src/schema/tests.rs +133 -92
- package/dist-engine-src/src/session/context.rs +40 -42
- package/dist-engine-src/src/session/create_version.rs +22 -14
- package/dist-engine-src/src/session/execute.rs +45 -14
- package/dist-engine-src/src/session/merge/apply.rs +4 -4
- package/dist-engine-src/src/session/merge/conflicts.rs +3 -2
- package/dist-engine-src/src/session/merge/stats.rs +1 -1
- package/dist-engine-src/src/session/merge/version.rs +35 -45
- package/dist-engine-src/src/session/mod.rs +4 -2
- package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
- package/dist-engine-src/src/session/switch_version.rs +16 -28
- package/dist-engine-src/src/sql2/change_provider.rs +14 -20
- package/dist-engine-src/src/sql2/classify.rs +61 -26
- package/dist-engine-src/src/sql2/context.rs +22 -18
- package/dist-engine-src/src/sql2/directory_history_provider.rs +28 -20
- package/dist-engine-src/src/sql2/directory_provider.rs +131 -83
- package/dist-engine-src/src/sql2/entity_history_provider.rs +10 -14
- package/dist-engine-src/src/sql2/entity_provider.rs +680 -169
- package/dist-engine-src/src/sql2/error.rs +21 -1
- package/dist-engine-src/src/sql2/execute.rs +325 -264
- package/dist-engine-src/src/sql2/file_history_provider.rs +29 -21
- package/dist-engine-src/src/sql2/file_provider.rs +533 -108
- package/dist-engine-src/src/sql2/filesystem_planner.rs +58 -94
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +37 -23
- package/dist-engine-src/src/sql2/history_projection.rs +3 -27
- package/dist-engine-src/src/sql2/history_provider.rs +11 -17
- package/dist-engine-src/src/sql2/history_route.rs +22 -8
- package/dist-engine-src/src/sql2/lix_state_provider.rs +178 -96
- package/dist-engine-src/src/sql2/mod.rs +6 -3
- package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
- package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
- package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
- package/dist-engine-src/src/sql2/public_bind/dml.rs +166 -0
- package/dist-engine-src/src/sql2/public_bind/mod.rs +25 -0
- package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
- package/dist-engine-src/src/sql2/read_only.rs +10 -12
- package/dist-engine-src/src/sql2/session.rs +7 -10
- package/dist-engine-src/src/sql2/udfs/lix_timestamp.rs +76 -0
- package/dist-engine-src/src/sql2/udfs/mod.rs +8 -1
- package/dist-engine-src/src/sql2/udfs/public_call.rs +211 -0
- package/dist-engine-src/src/sql2/version_provider.rs +46 -31
- package/dist-engine-src/src/sql2/version_scope.rs +4 -4
- package/dist-engine-src/src/storage_bench.rs +1782 -325
- package/dist-engine-src/src/test_support.rs +183 -36
- package/dist-engine-src/src/tracked_state/by_file_index.rs +20 -24
- package/dist-engine-src/src/tracked_state/codec.rs +1519 -181
- package/dist-engine-src/src/tracked_state/context.rs +1155 -271
- package/dist-engine-src/src/tracked_state/diff.rs +249 -57
- package/dist-engine-src/src/tracked_state/materialization.rs +365 -103
- package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
- package/dist-engine-src/src/tracked_state/merge.rs +37 -19
- package/dist-engine-src/src/tracked_state/mod.rs +8 -7
- package/dist-engine-src/src/tracked_state/storage.rs +138 -6
- package/dist-engine-src/src/tracked_state/tree.rs +695 -252
- package/dist-engine-src/src/tracked_state/types.rs +176 -6
- package/dist-engine-src/src/transaction/commit.rs +695 -435
- package/dist-engine-src/src/transaction/context.rs +551 -310
- package/dist-engine-src/src/transaction/live_state_overlay.rs +9 -8
- package/dist-engine-src/src/transaction/mod.rs +2 -0
- package/dist-engine-src/src/transaction/normalization.rs +311 -447
- package/dist-engine-src/src/transaction/prep.rs +37 -0
- package/dist-engine-src/src/transaction/schema_resolver.rs +93 -71
- package/dist-engine-src/src/transaction/staging.rs +701 -406
- package/dist-engine-src/src/transaction/types.rs +231 -122
- package/dist-engine-src/src/transaction/validation.rs +2717 -1698
- package/dist-engine-src/src/untracked_state/codec.rs +40 -96
- package/dist-engine-src/src/untracked_state/context.rs +21 -5
- package/dist-engine-src/src/untracked_state/materialization.rs +10 -104
- package/dist-engine-src/src/untracked_state/mod.rs +3 -5
- package/dist-engine-src/src/untracked_state/storage.rs +105 -57
- package/dist-engine-src/src/untracked_state/types.rs +63 -13
- package/dist-engine-src/src/version/context.rs +1 -13
- package/dist-engine-src/src/version/lifecycle.rs +221 -0
- package/dist-engine-src/src/version/mod.rs +3 -2
- package/dist-engine-src/src/version/refs.rs +12 -103
- package/dist-engine-src/src/version/stage_rows.rs +15 -19
- package/package.json +1 -1
- package/dist-engine-src/src/changelog/codec.rs +0 -321
- package/dist-engine-src/src/changelog/context.rs +0 -92
- package/dist-engine-src/src/changelog/materialization.rs +0 -121
- package/dist-engine-src/src/changelog/mod.rs +0 -13
- package/dist-engine-src/src/changelog/reader.rs +0 -20
- package/dist-engine-src/src/changelog/storage.rs +0 -220
- package/dist-engine-src/src/changelog/types.rs +0 -38
- package/dist-engine-src/src/schema/builtin/lix_change_set.json +0 -18
- package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +0 -75
- package/dist-engine-src/src/schema/builtin/lix_entity_label.json +0 -63
- package/dist-engine-src/src/schema_registry.rs +0 -294
- package/dist-engine-src/src/sql2/commit_derived_provider.rs +0 -591
- package/dist-engine-src/src/tracked_state/rebuild.rs +0 -771
- package/dist-engine-src/src/tracked_state/tree_types.rs +0 -176
|
@@ -26,7 +26,7 @@ use futures_util::{stream, TryStreamExt};
|
|
|
26
26
|
use serde::Deserialize;
|
|
27
27
|
|
|
28
28
|
use crate::functions::FunctionProviderHandle;
|
|
29
|
-
use crate::live_state::
|
|
29
|
+
use crate::live_state::MaterializedLiveStateRow;
|
|
30
30
|
use crate::live_state::{
|
|
31
31
|
LiveStateFilter, LiveStateProjection, LiveStateReader, LiveStateScanRequest,
|
|
32
32
|
};
|
|
@@ -34,14 +34,18 @@ use crate::sql2::dml::{InsertExec, InsertSink};
|
|
|
34
34
|
use crate::sql2::filesystem_predicates::{
|
|
35
35
|
canonicalize_filesystem_path_filters, FilesystemPathKind,
|
|
36
36
|
};
|
|
37
|
+
use crate::sql2::predicate_typecheck::validate_json_predicate_filters;
|
|
37
38
|
use crate::sql2::version_scope::{
|
|
38
39
|
explicit_version_ids_from_dml_filters, resolve_provider_version_ids,
|
|
39
40
|
resolve_write_version_scope, VersionBinding,
|
|
40
41
|
};
|
|
41
42
|
use crate::sql2::write_normalization::{InsertCell, SqlCell, UpdateAssignmentValues};
|
|
42
|
-
use crate::transaction::types::{
|
|
43
|
+
use crate::transaction::types::{
|
|
44
|
+
LogicalPrimaryKey, TransactionJson, TransactionWriteOperation, TransactionWriteOrigin,
|
|
45
|
+
TransactionWriteRow,
|
|
46
|
+
};
|
|
43
47
|
use crate::version::VersionRefReader;
|
|
44
|
-
use crate::{
|
|
48
|
+
use crate::{parse_row_metadata_value, serialize_row_metadata, LixError};
|
|
45
49
|
|
|
46
50
|
use super::filesystem_planner::{
|
|
47
51
|
directory_descriptor_write_row, directory_path_resolvers_from_state_rows,
|
|
@@ -53,7 +57,7 @@ use super::result_metadata::json_field;
|
|
|
53
57
|
use crate::sql2::{
|
|
54
58
|
SqlWriteContext, WriteAccess, WriteContextLiveStateReader, WriteContextVersionRefReader,
|
|
55
59
|
};
|
|
56
|
-
use crate::transaction::types::{
|
|
60
|
+
use crate::transaction::types::{TransactionWrite, TransactionWriteMode};
|
|
57
61
|
|
|
58
62
|
const DIRECTORY_SCHEMA_KEY: &str = "lix_directory_descriptor";
|
|
59
63
|
const FILE_DESCRIPTOR_SCHEMA_KEY: &str = "lix_file_descriptor";
|
|
@@ -220,8 +224,11 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
220
224
|
) -> Result<Arc<dyn ExecutionPlan>> {
|
|
221
225
|
let projected_schema = projected_schema(&self.schema, projection)?;
|
|
222
226
|
let scan_limit = if filters.is_empty() { limit } else { None };
|
|
223
|
-
let mut request =
|
|
224
|
-
|
|
227
|
+
let mut request = lix_directory_scan_request(
|
|
228
|
+
self.version_binding.active_version_id(),
|
|
229
|
+
Some(projected_schema.as_ref()),
|
|
230
|
+
scan_limit,
|
|
231
|
+
);
|
|
225
232
|
if self.write_access.is_write() && matches!(self.version_binding, VersionBinding::Explicit)
|
|
226
233
|
{
|
|
227
234
|
request.filter.version_ids = explicit_version_ids_from_dml_filters(filters);
|
|
@@ -241,6 +248,7 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
241
248
|
.map_err(lix_error_to_datafusion_error)?;
|
|
242
249
|
let filters = canonicalize_filesystem_path_filters(filters, FilesystemPathKind::Directory)?;
|
|
243
250
|
let df_schema = DFSchema::try_from(Arc::clone(&self.schema))?;
|
|
251
|
+
validate_json_predicate_filters(self.schema.as_ref(), &filters)?;
|
|
244
252
|
let physical_filters = filters
|
|
245
253
|
.iter()
|
|
246
254
|
.map(|expr| create_physical_expr(expr, &df_schema, _state.execution_props()))
|
|
@@ -291,12 +299,13 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
291
299
|
let df_schema = DFSchema::try_from(Arc::clone(&self.schema))?;
|
|
292
300
|
let filters =
|
|
293
301
|
canonicalize_filesystem_path_filters(&filters, FilesystemPathKind::Directory)?;
|
|
302
|
+
validate_json_predicate_filters(self.schema.as_ref(), &filters)?;
|
|
294
303
|
let physical_filters = filters
|
|
295
304
|
.iter()
|
|
296
305
|
.map(|expr| create_physical_expr(expr, &df_schema, state.execution_props()))
|
|
297
306
|
.collect::<Result<Vec<_>>>()?;
|
|
298
307
|
let mut request =
|
|
299
|
-
lix_directory_scan_request(self.version_binding.active_version_id(), None);
|
|
308
|
+
lix_directory_scan_request(self.version_binding.active_version_id(), None, None);
|
|
300
309
|
if matches!(self.version_binding, VersionBinding::Explicit) {
|
|
301
310
|
request.filter.version_ids = explicit_version_ids_from_dml_filters(&filters);
|
|
302
311
|
if request.filter.version_ids.is_empty() {
|
|
@@ -338,11 +347,13 @@ impl TableProvider for LixDirectoryProvider {
|
|
|
338
347
|
.collect::<Result<Vec<_>>>()?;
|
|
339
348
|
let filters =
|
|
340
349
|
canonicalize_filesystem_path_filters(&filters, FilesystemPathKind::Directory)?;
|
|
350
|
+
validate_json_predicate_filters(self.schema.as_ref(), &filters)?;
|
|
341
351
|
let physical_filters = filters
|
|
342
352
|
.iter()
|
|
343
353
|
.map(|expr| create_physical_expr(expr, &df_schema, state.execution_props()))
|
|
344
354
|
.collect::<Result<Vec<_>>>()?;
|
|
345
|
-
let request =
|
|
355
|
+
let request =
|
|
356
|
+
lix_directory_scan_request(self.version_binding.active_version_id(), None, None);
|
|
346
357
|
|
|
347
358
|
Ok(Arc::new(LixDirectoryUpdateExec::new(
|
|
348
359
|
write_ctx.clone(),
|
|
@@ -449,8 +460,8 @@ impl InsertSink for LixDirectoryInsertSink {
|
|
|
449
460
|
}
|
|
450
461
|
|
|
451
462
|
self.write_ctx
|
|
452
|
-
.stage_write(
|
|
453
|
-
mode:
|
|
463
|
+
.stage_write(TransactionWrite::Rows {
|
|
464
|
+
mode: TransactionWriteMode::Insert,
|
|
454
465
|
rows,
|
|
455
466
|
})
|
|
456
467
|
.await
|
|
@@ -601,8 +612,8 @@ impl ExecutionPlan for LixDirectoryDeleteExec {
|
|
|
601
612
|
|
|
602
613
|
if count > 0 {
|
|
603
614
|
write_ctx
|
|
604
|
-
.stage_write(
|
|
605
|
-
mode:
|
|
615
|
+
.stage_write(TransactionWrite::Rows {
|
|
616
|
+
mode: TransactionWriteMode::Replace,
|
|
606
617
|
rows: write_rows,
|
|
607
618
|
})
|
|
608
619
|
.await
|
|
@@ -759,8 +770,8 @@ impl ExecutionPlan for LixDirectoryUpdateExec {
|
|
|
759
770
|
|
|
760
771
|
if count > 0 {
|
|
761
772
|
write_ctx
|
|
762
|
-
.stage_write(
|
|
763
|
-
mode:
|
|
773
|
+
.stage_write(TransactionWrite::Rows {
|
|
774
|
+
mode: TransactionWriteMode::Replace,
|
|
764
775
|
rows: write_rows,
|
|
765
776
|
})
|
|
766
777
|
.await
|
|
@@ -917,7 +928,7 @@ struct DirectoryDescriptorRecord {
|
|
|
917
928
|
parent_id: Option<String>,
|
|
918
929
|
name: String,
|
|
919
930
|
hidden: bool,
|
|
920
|
-
live:
|
|
931
|
+
live: MaterializedLiveStateRow,
|
|
921
932
|
}
|
|
922
933
|
|
|
923
934
|
#[derive(Debug, Deserialize)]
|
|
@@ -932,7 +943,7 @@ struct DirectoryDescriptorSnapshot {
|
|
|
932
943
|
fn lix_directory_write_rows_from_batch(
|
|
933
944
|
batch: &RecordBatch,
|
|
934
945
|
version_binding: Option<&str>,
|
|
935
|
-
) -> Result<Vec<
|
|
946
|
+
) -> Result<Vec<TransactionWriteRow>> {
|
|
936
947
|
lix_directory_write_rows_from_batch_with_options(batch, version_binding, "lix_directory", true)
|
|
937
948
|
}
|
|
938
949
|
|
|
@@ -942,7 +953,7 @@ fn lix_directory_write_rows_from_batch_with_path_resolvers(
|
|
|
942
953
|
surface_name: &str,
|
|
943
954
|
path_resolvers: &mut BTreeMap<String, DirectoryPathResolver>,
|
|
944
955
|
generate_directory_id: &mut dyn FnMut() -> String,
|
|
945
|
-
) -> Result<Vec<
|
|
956
|
+
) -> Result<Vec<TransactionWriteRow>> {
|
|
946
957
|
lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
947
958
|
batch,
|
|
948
959
|
version_binding,
|
|
@@ -958,7 +969,7 @@ fn lix_directory_update_write_rows_from_batch(
|
|
|
958
969
|
assignments: &[(String, Arc<dyn PhysicalExpr>)],
|
|
959
970
|
version_binding: Option<&str>,
|
|
960
971
|
path_resolvers: &mut BTreeMap<String, DirectoryPathResolver>,
|
|
961
|
-
) -> Result<Vec<
|
|
972
|
+
) -> Result<Vec<TransactionWriteRow>> {
|
|
962
973
|
let assignment_values = UpdateAssignmentValues::evaluate(batch, assignments)?;
|
|
963
974
|
let mut rows = Vec::new();
|
|
964
975
|
for row_index in 0..batch.num_rows() {
|
|
@@ -1010,7 +1021,7 @@ fn lix_directory_recursive_delete_rows_from_batch(
|
|
|
1010
1021
|
batch: &RecordBatch,
|
|
1011
1022
|
version_binding: Option<&str>,
|
|
1012
1023
|
visible_filesystems: &BTreeMap<String, VisibleFilesystem>,
|
|
1013
|
-
) -> Result<(Vec<
|
|
1024
|
+
) -> Result<(Vec<TransactionWriteRow>, u64)> {
|
|
1014
1025
|
let mut rows = Vec::new();
|
|
1015
1026
|
let mut seen = BTreeSet::new();
|
|
1016
1027
|
let mut count = 0u64;
|
|
@@ -1036,7 +1047,7 @@ fn lix_directory_recursive_delete_rows_from_batch(
|
|
|
1036
1047
|
}
|
|
1037
1048
|
|
|
1038
1049
|
fn append_deduped_delete_plan(
|
|
1039
|
-
rows: &mut Vec<
|
|
1050
|
+
rows: &mut Vec<TransactionWriteRow>,
|
|
1040
1051
|
seen: &mut BTreeSet<StateRowDedupeKey>,
|
|
1041
1052
|
plan: FilesystemDeletePlan,
|
|
1042
1053
|
count: &mut u64,
|
|
@@ -1051,7 +1062,7 @@ fn append_deduped_delete_plan(
|
|
|
1051
1062
|
}
|
|
1052
1063
|
}
|
|
1053
1064
|
|
|
1054
|
-
fn is_user_visible_filesystem_delete_row(row: &
|
|
1065
|
+
fn is_user_visible_filesystem_delete_row(row: &TransactionWriteRow) -> bool {
|
|
1055
1066
|
matches!(
|
|
1056
1067
|
row.schema_key.as_str(),
|
|
1057
1068
|
"lix_directory_descriptor" | "lix_file_descriptor"
|
|
@@ -1068,14 +1079,14 @@ struct StateRowDedupeKey {
|
|
|
1068
1079
|
untracked: bool,
|
|
1069
1080
|
}
|
|
1070
1081
|
|
|
1071
|
-
impl From<&
|
|
1072
|
-
fn from(row: &
|
|
1082
|
+
impl From<&TransactionWriteRow> for StateRowDedupeKey {
|
|
1083
|
+
fn from(row: &TransactionWriteRow) -> Self {
|
|
1073
1084
|
Self {
|
|
1074
1085
|
entity_id: row
|
|
1075
1086
|
.entity_id
|
|
1076
1087
|
.as_ref()
|
|
1077
1088
|
.expect("directory provider staged row should carry entity_id")
|
|
1078
|
-
.
|
|
1089
|
+
.as_single_string_owned()
|
|
1079
1090
|
.expect("directory provider staged row entity identity should project"),
|
|
1080
1091
|
schema_key: row.schema_key.clone(),
|
|
1081
1092
|
file_id: row.file_id.clone(),
|
|
@@ -1092,7 +1103,7 @@ fn lix_directory_write_rows_from_batch_with_options(
|
|
|
1092
1103
|
version_binding: Option<&str>,
|
|
1093
1104
|
surface_name: &str,
|
|
1094
1105
|
reject_read_only_fields: bool,
|
|
1095
|
-
) -> Result<Vec<
|
|
1106
|
+
) -> Result<Vec<TransactionWriteRow>> {
|
|
1096
1107
|
lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
1097
1108
|
batch,
|
|
1098
1109
|
version_binding,
|
|
@@ -1110,7 +1121,7 @@ fn lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
|
1110
1121
|
reject_read_only_fields: bool,
|
|
1111
1122
|
mut path_resolvers: Option<&mut BTreeMap<String, DirectoryPathResolver>>,
|
|
1112
1123
|
mut generate_directory_id: Option<&mut dyn FnMut() -> String>,
|
|
1113
|
-
) -> Result<Vec<
|
|
1124
|
+
) -> Result<Vec<TransactionWriteRow>> {
|
|
1114
1125
|
let mut rows = Vec::new();
|
|
1115
1126
|
for row_index in 0..batch.num_rows() {
|
|
1116
1127
|
if reject_read_only_fields {
|
|
@@ -1189,7 +1200,7 @@ fn lix_directory_write_rows_from_batch_with_options_and_path_resolvers(
|
|
|
1189
1200
|
}
|
|
1190
1201
|
|
|
1191
1202
|
fn attach_lix_directory_insert_origin(
|
|
1192
|
-
rows: &mut [
|
|
1203
|
+
rows: &mut [TransactionWriteRow],
|
|
1193
1204
|
surface_name: &str,
|
|
1194
1205
|
directory_id: &str,
|
|
1195
1206
|
) {
|
|
@@ -1201,7 +1212,7 @@ fn attach_lix_directory_insert_origin(
|
|
|
1201
1212
|
let Some(entity_id) = row
|
|
1202
1213
|
.entity_id
|
|
1203
1214
|
.as_ref()
|
|
1204
|
-
.and_then(|entity_id| entity_id.
|
|
1215
|
+
.and_then(|entity_id| entity_id.as_single_string_owned().ok())
|
|
1205
1216
|
else {
|
|
1206
1217
|
continue;
|
|
1207
1218
|
};
|
|
@@ -1211,10 +1222,10 @@ fn attach_lix_directory_insert_origin(
|
|
|
1211
1222
|
}
|
|
1212
1223
|
}
|
|
1213
1224
|
|
|
1214
|
-
fn lix_directory_insert_origin(surface_name: &str, directory_id: &str) ->
|
|
1215
|
-
|
|
1225
|
+
fn lix_directory_insert_origin(surface_name: &str, directory_id: &str) -> TransactionWriteOrigin {
|
|
1226
|
+
TransactionWriteOrigin {
|
|
1216
1227
|
surface: surface_name.to_string(),
|
|
1217
|
-
operation:
|
|
1228
|
+
operation: TransactionWriteOperation::Insert,
|
|
1218
1229
|
primary_key: Some(LogicalPrimaryKey {
|
|
1219
1230
|
columns: vec!["id".to_string()],
|
|
1220
1231
|
values: vec![directory_id.to_string()],
|
|
@@ -1313,7 +1324,7 @@ async fn directory_path_resolvers_from_live_state(
|
|
|
1313
1324
|
|
|
1314
1325
|
fn lix_directory_record_batch(
|
|
1315
1326
|
schema: &SchemaRef,
|
|
1316
|
-
rows: Vec<
|
|
1327
|
+
rows: Vec<MaterializedLiveStateRow>,
|
|
1317
1328
|
) -> Result<RecordBatch, LixError> {
|
|
1318
1329
|
let mut directory_rows = Vec::<DirectoryDescriptorRecord>::new();
|
|
1319
1330
|
|
|
@@ -1349,7 +1360,6 @@ fn lix_directory_record_batch(
|
|
|
1349
1360
|
let mut entity_ids = Vec::new();
|
|
1350
1361
|
let mut schema_keys = Vec::new();
|
|
1351
1362
|
let mut file_ids = Vec::new();
|
|
1352
|
-
let mut schema_versions = Vec::new();
|
|
1353
1363
|
let mut globals = Vec::new();
|
|
1354
1364
|
let mut change_ids = Vec::new();
|
|
1355
1365
|
let mut created_ats = Vec::new();
|
|
@@ -1369,10 +1379,9 @@ fn lix_directory_record_batch(
|
|
|
1369
1379
|
parent_ids.push(directory.parent_id);
|
|
1370
1380
|
names.push(Some(directory.name));
|
|
1371
1381
|
hiddens.push(Some(directory.hidden));
|
|
1372
|
-
entity_ids.push(Some(directory.live.entity_id.
|
|
1382
|
+
entity_ids.push(Some(directory.live.entity_id.as_json_array_text()?));
|
|
1373
1383
|
schema_keys.push(Some(directory.live.schema_key));
|
|
1374
1384
|
file_ids.push(directory.live.file_id);
|
|
1375
|
-
schema_versions.push(directory.live.schema_version);
|
|
1376
1385
|
globals.push(Some(directory.live.global));
|
|
1377
1386
|
change_ids.push(directory.live.change_id);
|
|
1378
1387
|
created_ats.push(directory.live.created_at);
|
|
@@ -1394,7 +1403,6 @@ fn lix_directory_record_batch(
|
|
|
1394
1403
|
"lixcol_entity_id" => Arc::new(StringArray::from(entity_ids.clone())),
|
|
1395
1404
|
"lixcol_schema_key" => Arc::new(StringArray::from(schema_keys.clone())),
|
|
1396
1405
|
"lixcol_file_id" => Arc::new(StringArray::from(file_ids.clone())),
|
|
1397
|
-
"lixcol_schema_version" => Arc::new(StringArray::from(schema_versions.clone())),
|
|
1398
1406
|
"lixcol_global" => Arc::new(BooleanArray::from(globals.clone())),
|
|
1399
1407
|
"lixcol_change_id" => Arc::new(StringArray::from(change_ids.clone())),
|
|
1400
1408
|
"lixcol_created_at" => Arc::new(StringArray::from(created_ats.clone())),
|
|
@@ -1513,6 +1521,7 @@ fn projected_schema(base_schema: &SchemaRef, projection: Option<&Vec<usize>>) ->
|
|
|
1513
1521
|
|
|
1514
1522
|
fn lix_directory_scan_request(
|
|
1515
1523
|
version_binding: Option<&str>,
|
|
1524
|
+
projected_schema: Option<&Schema>,
|
|
1516
1525
|
limit: Option<usize>,
|
|
1517
1526
|
) -> LiveStateScanRequest {
|
|
1518
1527
|
LiveStateScanRequest {
|
|
@@ -1523,11 +1532,33 @@ fn lix_directory_scan_request(
|
|
|
1523
1532
|
.unwrap_or_default(),
|
|
1524
1533
|
..LiveStateFilter::default()
|
|
1525
1534
|
},
|
|
1526
|
-
projection:
|
|
1535
|
+
projection: lix_directory_live_state_projection(projected_schema),
|
|
1527
1536
|
limit,
|
|
1528
1537
|
}
|
|
1529
1538
|
}
|
|
1530
1539
|
|
|
1540
|
+
fn lix_directory_live_state_projection(projected_schema: Option<&Schema>) -> LiveStateProjection {
|
|
1541
|
+
let Some(schema) = projected_schema else {
|
|
1542
|
+
return LiveStateProjection::default();
|
|
1543
|
+
};
|
|
1544
|
+
let mut columns = Vec::new();
|
|
1545
|
+
let needs_snapshot = schema
|
|
1546
|
+
.fields()
|
|
1547
|
+
.iter()
|
|
1548
|
+
.any(|field| matches!(field.name().as_str(), "parent_id" | "name" | "hidden"));
|
|
1549
|
+
if needs_snapshot {
|
|
1550
|
+
columns.push("snapshot_content".to_string());
|
|
1551
|
+
}
|
|
1552
|
+
if schema
|
|
1553
|
+
.fields()
|
|
1554
|
+
.iter()
|
|
1555
|
+
.any(|field| field.name() == "lixcol_metadata")
|
|
1556
|
+
{
|
|
1557
|
+
columns.push("metadata".to_string());
|
|
1558
|
+
}
|
|
1559
|
+
LiveStateProjection { columns }
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1531
1562
|
fn validate_lix_directory_update_assignments(
|
|
1532
1563
|
schema: &SchemaRef,
|
|
1533
1564
|
assignments: &[(String, Expr)],
|
|
@@ -1682,10 +1713,13 @@ fn update_optional_metadata_value(
|
|
|
1682
1713
|
row_index: usize,
|
|
1683
1714
|
column_name: &str,
|
|
1684
1715
|
context: &str,
|
|
1685
|
-
) -> Result<Option<
|
|
1716
|
+
) -> Result<Option<TransactionJson>> {
|
|
1686
1717
|
update_optional_string_value(batch, assignment_values, row_index, column_name)?
|
|
1687
1718
|
.map(|value| {
|
|
1688
|
-
|
|
1719
|
+
let metadata = parse_row_metadata_value(&value, context)
|
|
1720
|
+
.map_err(super::error::lix_error_to_datafusion_error)?;
|
|
1721
|
+
TransactionJson::from_value(metadata, &format!("{context} metadata"))
|
|
1722
|
+
.map_err(super::error::lix_error_to_datafusion_error)
|
|
1689
1723
|
})
|
|
1690
1724
|
.transpose()
|
|
1691
1725
|
}
|
|
@@ -1730,10 +1764,13 @@ fn optional_metadata_value(
|
|
|
1730
1764
|
row_index: usize,
|
|
1731
1765
|
column_name: &str,
|
|
1732
1766
|
context: &str,
|
|
1733
|
-
) -> Result<Option<
|
|
1767
|
+
) -> Result<Option<TransactionJson>> {
|
|
1734
1768
|
optional_string_value(batch, row_index, column_name)?
|
|
1735
1769
|
.map(|value| {
|
|
1736
|
-
|
|
1770
|
+
let metadata = parse_row_metadata_value(&value, context)
|
|
1771
|
+
.map_err(super::error::lix_error_to_datafusion_error)?;
|
|
1772
|
+
TransactionJson::from_value(metadata, &format!("{context} metadata"))
|
|
1773
|
+
.map_err(super::error::lix_error_to_datafusion_error)
|
|
1737
1774
|
})
|
|
1738
1775
|
.transpose()
|
|
1739
1776
|
}
|
|
@@ -1784,10 +1821,9 @@ fn lix_directory_schema() -> SchemaRef {
|
|
|
1784
1821
|
Field::new("parent_id", DataType::Utf8, true),
|
|
1785
1822
|
Field::new("name", DataType::Utf8, false),
|
|
1786
1823
|
Field::new("hidden", DataType::Boolean, true),
|
|
1787
|
-
|
|
1824
|
+
json_field("lixcol_entity_id", false),
|
|
1788
1825
|
Field::new("lixcol_schema_key", DataType::Utf8, false),
|
|
1789
1826
|
Field::new("lixcol_file_id", DataType::Utf8, true),
|
|
1790
|
-
Field::new("lixcol_schema_version", DataType::Utf8, false),
|
|
1791
1827
|
Field::new("lixcol_global", DataType::Boolean, true),
|
|
1792
1828
|
Field::new("lixcol_change_id", DataType::Utf8, true),
|
|
1793
1829
|
Field::new("lixcol_created_at", DataType::Utf8, true),
|
|
@@ -1833,11 +1869,14 @@ mod tests {
|
|
|
1833
1869
|
FunctionProvider, FunctionProviderHandle, SharedFunctionProvider, SystemFunctionProvider,
|
|
1834
1870
|
};
|
|
1835
1871
|
use crate::live_state::{
|
|
1836
|
-
LiveStateReader,
|
|
1872
|
+
LiveStateReader, LiveStateRowRequest, LiveStateScanRequest, MaterializedLiveStateRow,
|
|
1837
1873
|
};
|
|
1838
1874
|
use crate::sql2::dml::InsertSink;
|
|
1839
1875
|
use crate::sql2::{SqlWriteContext, SqlWriteExecutionContext};
|
|
1840
|
-
use crate::transaction::types::{
|
|
1876
|
+
use crate::transaction::types::{
|
|
1877
|
+
TransactionJson, TransactionWrite, TransactionWriteMode, TransactionWriteOutcome,
|
|
1878
|
+
TransactionWriteRow,
|
|
1879
|
+
};
|
|
1841
1880
|
use crate::LixError;
|
|
1842
1881
|
|
|
1843
1882
|
use super::{
|
|
@@ -1862,8 +1901,8 @@ mod tests {
|
|
|
1862
1901
|
|
|
1863
1902
|
#[derive(Default)]
|
|
1864
1903
|
struct CapturingWriteContext {
|
|
1865
|
-
rows: Vec<
|
|
1866
|
-
writes: Vec<
|
|
1904
|
+
rows: Vec<MaterializedLiveStateRow>,
|
|
1905
|
+
writes: Vec<TransactionWrite>,
|
|
1867
1906
|
}
|
|
1868
1907
|
|
|
1869
1908
|
#[async_trait]
|
|
@@ -1872,7 +1911,10 @@ mod tests {
|
|
|
1872
1911
|
&self,
|
|
1873
1912
|
hashes: &[crate::binary_cas::BlobHash],
|
|
1874
1913
|
) -> Result<crate::binary_cas::BlobBytesBatch, LixError> {
|
|
1875
|
-
Ok(crate::binary_cas::BlobBytesBatch::
|
|
1914
|
+
Ok(crate::binary_cas::BlobBytesBatch::new(vec![
|
|
1915
|
+
None;
|
|
1916
|
+
hashes.len()
|
|
1917
|
+
]))
|
|
1876
1918
|
}
|
|
1877
1919
|
}
|
|
1878
1920
|
|
|
@@ -1900,7 +1942,7 @@ mod tests {
|
|
|
1900
1942
|
async fn scan_live_state(
|
|
1901
1943
|
&mut self,
|
|
1902
1944
|
_request: &LiveStateScanRequest,
|
|
1903
|
-
) -> Result<Vec<
|
|
1945
|
+
) -> Result<Vec<MaterializedLiveStateRow>, LixError> {
|
|
1904
1946
|
Ok(self.rows.clone())
|
|
1905
1947
|
}
|
|
1906
1948
|
|
|
@@ -1914,16 +1956,19 @@ mod tests {
|
|
|
1914
1956
|
Ok(Some(format!("commit-{version_id}")))
|
|
1915
1957
|
}
|
|
1916
1958
|
|
|
1917
|
-
async fn stage_write(
|
|
1959
|
+
async fn stage_write(
|
|
1960
|
+
&mut self,
|
|
1961
|
+
write: TransactionWrite,
|
|
1962
|
+
) -> Result<TransactionWriteOutcome, LixError> {
|
|
1918
1963
|
self.writes.push(write);
|
|
1919
|
-
Ok(
|
|
1964
|
+
Ok(TransactionWriteOutcome { count: 0 })
|
|
1920
1965
|
}
|
|
1921
1966
|
}
|
|
1922
1967
|
|
|
1923
1968
|
#[derive(Default)]
|
|
1924
1969
|
#[allow(dead_code)]
|
|
1925
1970
|
struct RowsLiveStateReader {
|
|
1926
|
-
rows: Vec<
|
|
1971
|
+
rows: Vec<MaterializedLiveStateRow>,
|
|
1927
1972
|
}
|
|
1928
1973
|
|
|
1929
1974
|
#[async_trait]
|
|
@@ -1931,19 +1976,23 @@ mod tests {
|
|
|
1931
1976
|
async fn scan_rows(
|
|
1932
1977
|
&self,
|
|
1933
1978
|
_request: &LiveStateScanRequest,
|
|
1934
|
-
) -> Result<Vec<
|
|
1979
|
+
) -> Result<Vec<MaterializedLiveStateRow>, LixError> {
|
|
1935
1980
|
Ok(self.rows.clone())
|
|
1936
1981
|
}
|
|
1937
1982
|
|
|
1938
1983
|
async fn load_row(
|
|
1939
1984
|
&self,
|
|
1940
1985
|
_request: &LiveStateRowRequest,
|
|
1941
|
-
) -> Result<Option<
|
|
1986
|
+
) -> Result<Option<MaterializedLiveStateRow>, LixError> {
|
|
1942
1987
|
Ok(None)
|
|
1943
1988
|
}
|
|
1944
1989
|
}
|
|
1945
1990
|
|
|
1946
|
-
fn live_row(
|
|
1991
|
+
fn live_row(
|
|
1992
|
+
entity_id: &str,
|
|
1993
|
+
version_id: &str,
|
|
1994
|
+
snapshot_content: &str,
|
|
1995
|
+
) -> MaterializedLiveStateRow {
|
|
1947
1996
|
live_filesystem_row(
|
|
1948
1997
|
entity_id,
|
|
1949
1998
|
super::DIRECTORY_SCHEMA_KEY,
|
|
@@ -1959,15 +2008,14 @@ mod tests {
|
|
|
1959
2008
|
file_id: Option<&str>,
|
|
1960
2009
|
version_id: &str,
|
|
1961
2010
|
snapshot_content: &str,
|
|
1962
|
-
) ->
|
|
1963
|
-
|
|
1964
|
-
entity_id: crate::entity_identity::EntityIdentity::
|
|
1965
|
-
.expect("entity id should decode"),
|
|
2011
|
+
) -> MaterializedLiveStateRow {
|
|
2012
|
+
MaterializedLiveStateRow {
|
|
2013
|
+
entity_id: crate::entity_identity::EntityIdentity::single(entity_id),
|
|
1966
2014
|
schema_key: schema_key.to_string(),
|
|
1967
2015
|
file_id: file_id.map(ToOwned::to_owned),
|
|
1968
2016
|
snapshot_content: Some(snapshot_content.to_string()),
|
|
1969
|
-
metadata: Some(json!({"source": "test"})),
|
|
1970
|
-
|
|
2017
|
+
metadata: Some(json!({"source": "test"}).to_string()),
|
|
2018
|
+
deleted: false,
|
|
1971
2019
|
version_id: version_id.to_string(),
|
|
1972
2020
|
change_id: Some(format!("change-{entity_id}")),
|
|
1973
2021
|
commit_id: Some(format!("commit-{entity_id}")),
|
|
@@ -1978,7 +2026,7 @@ mod tests {
|
|
|
1978
2026
|
}
|
|
1979
2027
|
}
|
|
1980
2028
|
|
|
1981
|
-
fn filesystem_rows() -> Vec<
|
|
2029
|
+
fn filesystem_rows() -> Vec<MaterializedLiveStateRow> {
|
|
1982
2030
|
vec![
|
|
1983
2031
|
live_filesystem_row(
|
|
1984
2032
|
"dir-docs",
|
|
@@ -2169,17 +2217,17 @@ mod tests {
|
|
|
2169
2217
|
|
|
2170
2218
|
assert_eq!(
|
|
2171
2219
|
rows,
|
|
2172
|
-
vec![
|
|
2220
|
+
vec![TransactionWriteRow {
|
|
2173
2221
|
entity_id: Some(crate::entity_identity::EntityIdentity::single("dir-docs")),
|
|
2174
2222
|
schema_key: super::DIRECTORY_SCHEMA_KEY.to_string(),
|
|
2175
2223
|
file_id: None,
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2224
|
+
snapshot: Some(TransactionJson::from_value_for_test(
|
|
2225
|
+
json!({"hidden":false,"id":"dir-docs","name":"docs","parent_id":null})
|
|
2226
|
+
)),
|
|
2227
|
+
metadata: Some(TransactionJson::from_value_for_test(
|
|
2228
|
+
json!({"source": "directory"})
|
|
2229
|
+
)),
|
|
2181
2230
|
origin: Some(lix_directory_insert_origin("lix_directory", "dir-docs")),
|
|
2182
|
-
schema_version: "1".to_string(),
|
|
2183
2231
|
created_at: None,
|
|
2184
2232
|
updated_at: None,
|
|
2185
2233
|
global: false,
|
|
@@ -2247,8 +2295,7 @@ mod tests {
|
|
|
2247
2295
|
.expect("directory path batch should decode");
|
|
2248
2296
|
|
|
2249
2297
|
assert_eq!(rows.len(), 1);
|
|
2250
|
-
let snapshot
|
|
2251
|
-
serde_json::from_str(rows[0].snapshot_content.as_deref().unwrap()).unwrap();
|
|
2298
|
+
let snapshot = rows[0].snapshot.as_ref().unwrap();
|
|
2252
2299
|
assert_eq!(snapshot["id"], "dir-nested");
|
|
2253
2300
|
assert_eq!(snapshot["parent_id"], "dir-docs");
|
|
2254
2301
|
assert_eq!(snapshot["name"], "nested");
|
|
@@ -2277,7 +2324,7 @@ mod tests {
|
|
|
2277
2324
|
row.entity_id
|
|
2278
2325
|
.as_ref()
|
|
2279
2326
|
.expect("planned delete row should carry entity_id")
|
|
2280
|
-
.
|
|
2327
|
+
.as_single_string_owned()
|
|
2281
2328
|
.expect("planned delete row should project entity_id"),
|
|
2282
2329
|
)
|
|
2283
2330
|
})
|
|
@@ -2290,7 +2337,7 @@ mod tests {
|
|
|
2290
2337
|
("lix_directory_descriptor", "dir-docs".to_string()),
|
|
2291
2338
|
]
|
|
2292
2339
|
);
|
|
2293
|
-
assert!(rows.iter().all(|row| row.
|
|
2340
|
+
assert!(rows.iter().all(|row| row.snapshot.is_none()));
|
|
2294
2341
|
}
|
|
2295
2342
|
|
|
2296
2343
|
#[test]
|
|
@@ -2342,20 +2389,22 @@ mod tests {
|
|
|
2342
2389
|
assert_eq!(count, 1);
|
|
2343
2390
|
assert_eq!(
|
|
2344
2391
|
write_context.writes.as_slice(),
|
|
2345
|
-
&[
|
|
2392
|
+
&[TransactionWrite::Rows {
|
|
2393
|
+
mode: TransactionWriteMode::Insert,
|
|
2394
|
+
rows: vec![TransactionWriteRow {
|
|
2346
2395
|
entity_id: Some(crate::entity_identity::EntityIdentity::single("dir-docs")),
|
|
2347
2396
|
schema_key: super::DIRECTORY_SCHEMA_KEY.to_string(),
|
|
2348
2397
|
file_id: None,
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2398
|
+
snapshot: Some(TransactionJson::from_value_for_test(
|
|
2399
|
+
json!({"hidden":false,"id":"dir-docs","name":"docs","parent_id":null})
|
|
2400
|
+
)),
|
|
2401
|
+
metadata: Some(TransactionJson::from_value_for_test(
|
|
2402
|
+
json!({"source": "directory"})
|
|
2403
|
+
)),
|
|
2354
2404
|
origin: Some(lix_directory_insert_origin(
|
|
2355
2405
|
"lix_directory_by_version",
|
|
2356
2406
|
"dir-docs"
|
|
2357
2407
|
)),
|
|
2358
|
-
schema_version: "1".to_string(),
|
|
2359
2408
|
created_at: None,
|
|
2360
2409
|
updated_at: None,
|
|
2361
2410
|
global: false,
|
|
@@ -2392,12 +2441,11 @@ mod tests {
|
|
|
2392
2441
|
.expect("directory sink should stage path write");
|
|
2393
2442
|
|
|
2394
2443
|
assert_eq!(count, 1);
|
|
2395
|
-
let [
|
|
2444
|
+
let [TransactionWrite::Rows { rows, .. }] = write_context.writes.as_slice() else {
|
|
2396
2445
|
panic!("expected one directory staged write");
|
|
2397
2446
|
};
|
|
2398
2447
|
assert_eq!(rows.len(), 1);
|
|
2399
|
-
let snapshot
|
|
2400
|
-
serde_json::from_str(rows[0].snapshot_content.as_deref().unwrap()).unwrap();
|
|
2448
|
+
let snapshot = rows[0].snapshot.as_ref().unwrap();
|
|
2401
2449
|
assert_eq!(snapshot["id"], "dir-nested");
|
|
2402
2450
|
assert_eq!(snapshot["parent_id"], "dir-docs");
|
|
2403
2451
|
assert_eq!(snapshot["name"], "nested");
|