dirsql 0.1.4__tar.gz → 0.1.6__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.
- {dirsql-0.1.4 → dirsql-0.1.6}/PKG-INFO +1 -1
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/src/db.rs +69 -2
- {dirsql-0.1.4 → dirsql-0.1.6}/pyproject.toml +1 -1
- {dirsql-0.1.4 → dirsql-0.1.6}/Cargo.lock +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/Cargo.toml +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/README.md +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/Cargo.toml +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/README.md +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/src/lib.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/integration/test_async_dirsql.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/integration/test_binding.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/integration/test_dirsql.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/integration/test_docs_examples.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/integration/test_docs_gaps.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/python/tests/integration/test_from_config.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/README.md +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/src/config.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/src/lib.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/src/parser.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/tests/async_sdk.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/tests/docs_examples.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/tests/docs_gaps.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/tests/from_config.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/packages/rust/tests/sdk.rs +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/python/dirsql/__init__.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/python/dirsql/_async.py +0 -0
- {dirsql-0.1.4 → dirsql-0.1.6}/python/dirsql/test_async.py +0 -0
|
@@ -133,7 +133,11 @@ impl Db {
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
/// Query the database, returning rows as a list of column-name -> value maps.
|
|
136
|
-
///
|
|
136
|
+
///
|
|
137
|
+
/// Internal tracking columns (`_dirsql_*`) are excluded from `SELECT *`
|
|
138
|
+
/// results so they don't leak. But if the user names one explicitly in the
|
|
139
|
+
/// projection (e.g. `SELECT _dirsql_file_path FROM t`), it's returned —
|
|
140
|
+
/// users opt into the tracking surface by typing the column name.
|
|
137
141
|
pub fn query(&self, sql: &str) -> Result<Vec<HashMap<String, Value>>> {
|
|
138
142
|
let mut stmt = self.conn.prepare(sql)?;
|
|
139
143
|
let column_names: Vec<String> = stmt.column_names().iter().map(|s| s.to_string()).collect();
|
|
@@ -141,7 +145,7 @@ impl Db {
|
|
|
141
145
|
let rows = stmt.query_map([], |row| {
|
|
142
146
|
let mut map = HashMap::new();
|
|
143
147
|
for (i, name) in column_names.iter().enumerate() {
|
|
144
|
-
if name.starts_with("_dirsql_") {
|
|
148
|
+
if name.starts_with("_dirsql_") && !sql.contains(name) {
|
|
145
149
|
continue;
|
|
146
150
|
}
|
|
147
151
|
let val: rusqlite::types::Value = row.get(i)?;
|
|
@@ -635,6 +639,69 @@ mod tests {
|
|
|
635
639
|
assert!(results[0].contains_key("id"));
|
|
636
640
|
}
|
|
637
641
|
|
|
642
|
+
#[test]
|
|
643
|
+
fn query_honors_explicit_dirsql_file_path() {
|
|
644
|
+
let db = Db::new().unwrap();
|
|
645
|
+
db.create_table("CREATE TABLE t (id TEXT)").unwrap();
|
|
646
|
+
let row = HashMap::from([("id".into(), Value::Text("1".into()))]);
|
|
647
|
+
db.insert_row("t", &row, "file.json", 0).unwrap();
|
|
648
|
+
|
|
649
|
+
let results = db.query("SELECT _dirsql_file_path FROM t").unwrap();
|
|
650
|
+
assert_eq!(results.len(), 1);
|
|
651
|
+
assert_eq!(
|
|
652
|
+
results[0].get("_dirsql_file_path"),
|
|
653
|
+
Some(&Value::Text("file.json".into())),
|
|
654
|
+
);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
#[test]
|
|
658
|
+
fn query_honors_explicit_dirsql_alongside_user_columns() {
|
|
659
|
+
let db = Db::new().unwrap();
|
|
660
|
+
db.create_table("CREATE TABLE posts (title TEXT)").unwrap();
|
|
661
|
+
let row = HashMap::from([("title".into(), Value::Text("Hello".into()))]);
|
|
662
|
+
db.insert_row("posts", &row, "posts/hello.json", 0).unwrap();
|
|
663
|
+
|
|
664
|
+
let results = db
|
|
665
|
+
.query("SELECT title, _dirsql_file_path FROM posts")
|
|
666
|
+
.unwrap();
|
|
667
|
+
assert_eq!(results.len(), 1);
|
|
668
|
+
assert_eq!(results[0]["title"], Value::Text("Hello".into()));
|
|
669
|
+
assert_eq!(
|
|
670
|
+
results[0]["_dirsql_file_path"],
|
|
671
|
+
Value::Text("posts/hello.json".into()),
|
|
672
|
+
);
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
#[test]
|
|
676
|
+
fn query_honors_explicit_dirsql_row_index() {
|
|
677
|
+
let db = Db::new().unwrap();
|
|
678
|
+
db.create_table("CREATE TABLE t (id TEXT)").unwrap();
|
|
679
|
+
let row = HashMap::from([("id".into(), Value::Text("a".into()))]);
|
|
680
|
+
db.insert_row("t", &row, "f.jsonl", 7).unwrap();
|
|
681
|
+
|
|
682
|
+
let results = db.query("SELECT _dirsql_row_index FROM t").unwrap();
|
|
683
|
+
assert_eq!(results.len(), 1);
|
|
684
|
+
assert_eq!(results[0]["_dirsql_row_index"], Value::Integer(7));
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
#[test]
|
|
688
|
+
fn query_keeps_dirsql_when_filter_references_it_with_star_projection() {
|
|
689
|
+
// Naming `_dirsql_file_path` anywhere in the SQL is treated as
|
|
690
|
+
// "the user is aware of this tracking column", so `SELECT *` with
|
|
691
|
+
// a `_dirsql_*` reference in WHERE returns it.
|
|
692
|
+
let db = Db::new().unwrap();
|
|
693
|
+
db.create_table("CREATE TABLE t (id TEXT)").unwrap();
|
|
694
|
+
let row = HashMap::from([("id".into(), Value::Text("1".into()))]);
|
|
695
|
+
db.insert_row("t", &row, "file.json", 0).unwrap();
|
|
696
|
+
|
|
697
|
+
let results = db
|
|
698
|
+
.query("SELECT * FROM t WHERE _dirsql_file_path = 'file.json'")
|
|
699
|
+
.unwrap();
|
|
700
|
+
assert_eq!(results.len(), 1);
|
|
701
|
+
assert!(results[0].contains_key("id"));
|
|
702
|
+
assert!(results[0].contains_key("_dirsql_file_path"));
|
|
703
|
+
}
|
|
704
|
+
|
|
638
705
|
// --- Error path: query with invalid SQL ---
|
|
639
706
|
|
|
640
707
|
#[test]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|