Skip to content

Commit 2f7972d

Browse files
committed
test(insert-select): cover a kv-engine source through its own route
The test copies two kv rows into a document target with an expression cell and asserts both the row count and the evaluated cells. The kv arm also refuses a point-in-time or transactional read by name: the materialize-scan carries no snapshot fields, so the read had nothing to honor.
1 parent 8b8f15a commit 2f7972d

2 files changed

Lines changed: 51 additions & 0 deletions

File tree

‎nodedb/src/control/maintenance/clone_materializer/auto_source.rs‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,16 @@ pub(crate) async fn scan_source_page(
5252
.await
5353
}
5454
EngineType::KeyValue => {
55+
// The kv materialize-scan carries no snapshot fields, so a
56+
// point-in-time or transactional read has nothing to thread into.
57+
// Refusing by name beats copying rows the caller did not ask for.
58+
if system_as_of_ms.is_some() || txn_id.is_some() {
59+
return Err(crate::Error::PlanError {
60+
detail: "a point-in-time or transactional read is not supported \
61+
for an INSERT ... SELECT kv source"
62+
.to_string(),
63+
});
64+
}
5565
let (pairs, next) =
5666
kv::scan_source_page(state, tenant_id, database_id, source_qualified, cursor)
5767
.await?;

‎nodedb/tests/wire/cases/insert_select_cross_engine.rs‎

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,3 +307,44 @@ async fn insert_select_from_strict_source_normalizes_and_resolves() {
307307
"vector search must resolve the copied strict-source 'alpha'; got {near_e1:?}"
308308
);
309309
}
310+
311+
/// A kv-engine source keeps nothing in the document store, so the document
312+
/// materializer read zero rows and the statement reported `INSERT 0 0`. The
313+
/// route scans the kv source through its own engine, and the copied rows must
314+
/// carry expression cells with the same semantics as a document source.
315+
#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
316+
async fn insert_select_copies_a_kv_source_through_its_own_engine() {
317+
let server = TestServer::start().await;
318+
319+
server
320+
.exec("CREATE COLLECTION isk_src (id BIGINT PRIMARY KEY, v TEXT) WITH (engine = 'kv')")
321+
.await
322+
.unwrap();
323+
server
324+
.exec("INSERT INTO isk_src (id, v) VALUES (1, 'hello')")
325+
.await
326+
.unwrap();
327+
server
328+
.exec("INSERT INTO isk_src (id, v) VALUES (2, 'world')")
329+
.await
330+
.unwrap();
331+
332+
server.exec("CREATE COLLECTION isk_dst").await.unwrap();
333+
server
334+
.exec("INSERT INTO isk_dst (id, v) SELECT id, upper(v) FROM isk_src")
335+
.await
336+
.unwrap();
337+
338+
let rows = server
339+
.query_rows("SELECT id, v FROM isk_dst ORDER BY id")
340+
.await
341+
.unwrap();
342+
assert_eq!(
343+
rows,
344+
vec![
345+
vec!["1".to_string(), "HELLO".to_string()],
346+
vec!["2".to_string(), "WORLD".to_string()],
347+
],
348+
"both rows must copy, with expression cells evaluated: {rows:?}"
349+
);
350+
}

0 commit comments

Comments
 (0)