mod common;
use common::native_harness::{NativeTestServer, do_handshake, send_sql};
use nodedb_types::protocol::HelloFrame;
use nodedb_types::protocol::opcodes::ResponseStatus;
use nodedb_types::value::Value;
async fn assert_create_then_dml_visible(
create_sql: &str,
insert_sql: &str,
select_sql: &str,
expected_columns: &[&str],
expected_row: &[Value],
) {
let server = NativeTestServer::start().await;
let (mut stream, _ack) = do_handshake(server.addr, &HelloFrame::current())
.await
.expect("handshake");
let create_resp = send_sql(&mut stream, 1, create_sql).await;
assert_ne!(
create_resp.status,
ResponseStatus::Error,
"native CREATE must succeed: {create_resp:?}"
);
let insert_resp = send_sql(&mut stream, 2, insert_sql).await;
assert_ne!(
insert_resp.status,
ResponseStatus::Error,
"native INSERT immediately after native CREATE must succeed \
(collection must be visible to DML on the same connection), got: {insert_resp:?}"
);
let select_resp = send_sql(&mut stream, 3, select_sql).await;
server.shutdown().await;
assert_ne!(
select_resp.status,
ResponseStatus::Error,
"native SELECT after native CREATE+INSERT must succeed: {select_resp:?}"
);
let columns = select_resp.columns.expect("columns present");
assert_eq!(
columns,
expected_columns
.iter()
.map(|c| c.to_string())
.collect::<Vec<_>>(),
"SELECT must project the declared columns: got {columns:?}"
);
let rows = select_resp.rows.expect("rows present");
assert_eq!(rows.len(), 1, "exactly one row expected: {rows:?}");
assert_eq!(
rows[0], expected_row,
"row values must match what was inserted over native"
);
}
#[tokio::test]
async fn document_strict_create_then_insert_then_select_over_native() {
assert_create_then_dml_visible(
"CREATE COLLECTION c (id STRING PRIMARY KEY, name STRING) WITH (engine='document_strict')",
"INSERT INTO c (id, name) VALUES ('a', 'alice')",
"SELECT id, name FROM c WHERE id = 'a'",
&["id", "name"],
&[Value::String("a".into()), Value::String("alice".into())],
)
.await;
}
#[tokio::test]
async fn kv_create_then_insert_then_select_over_native() {
assert_create_then_dml_visible(
"CREATE COLLECTION c (id STRING PRIMARY KEY, name STRING) WITH (engine='kv')",
"INSERT INTO c (id, name) VALUES ('a', 'alice')",
"SELECT id, name FROM c WHERE id = 'a'",
&["id", "name"],
&[Value::String("a".into()), Value::String("alice".into())],
)
.await;
}
#[tokio::test]
async fn document_schemaless_create_then_insert_then_select_over_native() {
let server = NativeTestServer::start().await;
let (mut stream, _ack) = do_handshake(server.addr, &HelloFrame::current())
.await
.expect("handshake");
let create_resp = send_sql(
&mut stream,
1,
"CREATE COLLECTION c WITH (engine='document_schemaless')",
)
.await;
assert_ne!(
create_resp.status,
ResponseStatus::Error,
"native CREATE must succeed: {create_resp:?}"
);
let insert_resp = send_sql(&mut stream, 2, "INSERT INTO c { id: 'a', name: 'alice' }").await;
assert_ne!(
insert_resp.status,
ResponseStatus::Error,
"native INSERT immediately after native CREATE must succeed \
(collection must be visible to DML on the same connection), got: {insert_resp:?}"
);
let select_resp = send_sql(&mut stream, 3, "SELECT id, name FROM c WHERE id = 'a'").await;
server.shutdown().await;
assert_ne!(
select_resp.status,
ResponseStatus::Error,
"native SELECT after native CREATE+INSERT must succeed: {select_resp:?}"
);
let columns = select_resp.columns.expect("columns present");
assert_eq!(
columns,
vec!["id".to_string(), "name".to_string()],
"SELECT must project the declared columns: got {columns:?}"
);
let rows = select_resp.rows.expect("rows present");
assert_eq!(rows.len(), 1, "exactly one row expected: {rows:?}");
assert_eq!(rows[0][0], Value::String("a".into()), "id cell");
assert_eq!(rows[0][1], Value::String("alice".into()), "name cell");
}