dirsql 0.3.78__tar.gz → 0.3.80__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.3.78 → dirsql-0.3.80}/Cargo.lock +1 -1
- {dirsql-0.3.78 → dirsql-0.3.80}/PKG-INFO +1 -1
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/Cargo.toml +1 -1
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/e2e-attestation.json +2 -2
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/db.rs +85 -6
- {dirsql-0.3.78 → dirsql-0.3.80}/Cargo.toml +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/README.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/__init__.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/_async.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/_dirsql.pyi +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/cli/__init__.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/cli/binary_path.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/cli/is_windows.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/cli/main.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/cli/resolve_config_extensions.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/py.typed +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/resolve_config_extensions.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/dirsql/resolve_extension.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/AGENTS.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/explanation.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/getting-started.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/define-tables.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/embed.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/persist.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/index.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/migrations.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/package.json +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/playwright.config.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/reference/cli.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/reference/columns.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/reference/config.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/reference/hooks.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/reference/http-api.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/reference/sdk.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/docs/vitest.config.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/README.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/conftest.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/.claude/CLAUDE.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/.vitepress/config.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/.vitepress/theme/index.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/.vitepress/theme/lang.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/AGENTS.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/explanation.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/getting-started.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/define-tables.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/embed.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/persist.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/index.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/migrations.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/package.json +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/playwright.config.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/pnpm-lock.yaml +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/pnpm-workspace.yaml +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/reference/cli.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/reference/columns.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/reference/config.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/reference/hooks.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/reference/http-api.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/reference/sdk.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/tests/integration/home.spec.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/tests/integration/language-flag.spec.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/tests/integration/sidebar.spec.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/tests/unit/config.test.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/tests/unit/lang.test.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/vitest.config.ts +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/src/lib.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/tests/__init__.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/tests/binding/__init__.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/tests/conftest.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/tests/e2e/__init__.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/tests/integration/__init__.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/python/tests/smoke/__init__.py +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/Cargo.toml +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/README.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/benches/db_bench.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/benches/differ_bench.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/benches/matcher_bench.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/benches/scanner_bench.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/explanation.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/getting-started.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/columns-from-paths.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/define-tables.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/embed.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/extract-from-contents.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/load-extension.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/persist.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/react-to-changes.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/search-by-meaning.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/howto/skip-files.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/index.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/migrations.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/reference/cli.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/reference/columns.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/reference/config.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/reference/hooks.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/reference/http-api.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/docs/reference/sdk.md +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/bin/dirsql.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/cli/execute.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/cli/init.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/cli/mod.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/cli/router.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/cli/serialize.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/cli/server.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/command.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/config.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/default_config.toml +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/differ.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/lib.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/matcher.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/persist.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/scanner.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/packages/rust/src/watcher.rs +0 -0
- {dirsql-0.3.78 → dirsql-0.3.80}/pyproject.toml +0 -0
|
@@ -4,7 +4,7 @@ name = "dirsql-py-ext"
|
|
|
4
4
|
# pypi/maturin handler can rewrite it via `write-version` before
|
|
5
5
|
# `maturin build`. `pyproject.toml` declares `dynamic = ["version"]`
|
|
6
6
|
# and maturin reads this field. Mirrors `packages/rust/Cargo.toml`.
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.80"
|
|
8
8
|
edition.workspace = true
|
|
9
9
|
publish = false
|
|
10
10
|
readme = "README.md"
|
|
@@ -37,6 +37,13 @@ const INTERNAL_TABLE_PREFIX: &str = "_dirsql_";
|
|
|
37
37
|
const INTERNAL_TABLE_DENIED_MSG: &str = "not authorized: dirsql's internal bookkeeping tables (the `_dirsql_*` namespace) \
|
|
38
38
|
are not readable through query()";
|
|
39
39
|
|
|
40
|
+
/// The message carried by [`DbError::Unauthorized`] when `query()` rejects an
|
|
41
|
+
/// `ATTACH`/`DETACH`. SQLite classifies both as read-only, so the `readonly()`
|
|
42
|
+
/// gate lets them through; they are effectful (ATTACH creates/opens an
|
|
43
|
+
/// arbitrary database file) and denied at prepare time instead.
|
|
44
|
+
const ATTACH_DENIED_MSG: &str = "not authorized: query() does not permit ATTACH or DETACH; \
|
|
45
|
+
attaching external databases is disabled on this surface";
|
|
46
|
+
|
|
40
47
|
fn is_internal_table(name: &str) -> bool {
|
|
41
48
|
name.starts_with(INTERNAL_TABLE_PREFIX)
|
|
42
49
|
}
|
|
@@ -273,14 +280,14 @@ impl Db {
|
|
|
273
280
|
// `_dirsql_internal_rows`, keyed on the row's rowid. A column-less row
|
|
274
281
|
// (SQLite requires ≥1 declared column, so this is only reachable
|
|
275
282
|
// defensively) uses `DEFAULT VALUES`.
|
|
276
|
-
let columns: Vec<String> = row.keys().
|
|
283
|
+
let columns: Vec<String> = row.keys().map(|c| format!("\"{c}\"")).collect();
|
|
277
284
|
let sql = if columns.is_empty() {
|
|
278
|
-
format!("INSERT INTO {} DEFAULT VALUES"
|
|
285
|
+
format!("INSERT INTO \"{table}\" DEFAULT VALUES")
|
|
279
286
|
} else {
|
|
280
287
|
let placeholders: Vec<String> =
|
|
281
288
|
(1..=columns.len()).map(|i| format!("?{}", i)).collect();
|
|
282
289
|
format!(
|
|
283
|
-
"INSERT INTO {} ({}) VALUES ({})",
|
|
290
|
+
"INSERT INTO \"{}\" ({}) VALUES ({})",
|
|
284
291
|
table,
|
|
285
292
|
columns.join(", "),
|
|
286
293
|
placeholders.join(", "),
|
|
@@ -402,16 +409,33 @@ impl Db {
|
|
|
402
409
|
/// through `query()`, are unaffected.
|
|
403
410
|
pub fn query(&self, sql: &str) -> Result<Vec<HashMap<String, Value>>> {
|
|
404
411
|
use rusqlite::hooks::{AuthAction, AuthContext, Authorization};
|
|
412
|
+
use std::sync::{Arc, Mutex};
|
|
405
413
|
|
|
414
|
+
// The authorizer runs at prepare time and may deny for two distinct
|
|
415
|
+
// reasons; it records which one here so the caught error can carry the
|
|
416
|
+
// matching message (the closure must be `'static`, so it owns a clone).
|
|
417
|
+
let denial: Arc<Mutex<Option<&'static str>>> = Arc::new(Mutex::new(None));
|
|
418
|
+
let denial_cb = Arc::clone(&denial);
|
|
406
419
|
self.conn
|
|
407
|
-
.authorizer(Some(|ctx: AuthContext<'_>| match ctx.action {
|
|
420
|
+
.authorizer(Some(move |ctx: AuthContext<'_>| match ctx.action {
|
|
408
421
|
AuthAction::Read { table_name, .. } if is_internal_table(table_name) => {
|
|
422
|
+
*denial_cb.lock().unwrap() = Some(INTERNAL_TABLE_DENIED_MSG);
|
|
409
423
|
Authorization::Deny
|
|
410
424
|
}
|
|
411
425
|
AuthAction::Pragma {
|
|
412
426
|
pragma_value: Some(value),
|
|
413
427
|
..
|
|
414
|
-
} if is_internal_table(value) =>
|
|
428
|
+
} if is_internal_table(value) => {
|
|
429
|
+
*denial_cb.lock().unwrap() = Some(INTERNAL_TABLE_DENIED_MSG);
|
|
430
|
+
Authorization::Deny
|
|
431
|
+
}
|
|
432
|
+
// ATTACH/DETACH are the only effectful actions SQLite classifies
|
|
433
|
+
// as read-only, so the `readonly()` gate below can't catch them;
|
|
434
|
+
// deny here before the file is ever created or opened.
|
|
435
|
+
AuthAction::Attach { .. } | AuthAction::Detach { .. } => {
|
|
436
|
+
*denial_cb.lock().unwrap() = Some(ATTACH_DENIED_MSG);
|
|
437
|
+
Authorization::Deny
|
|
438
|
+
}
|
|
415
439
|
_ => Authorization::Allow,
|
|
416
440
|
}));
|
|
417
441
|
let prepared = self.conn.prepare(sql);
|
|
@@ -426,7 +450,8 @@ impl Db {
|
|
|
426
450
|
if e.sqlite_error_code()
|
|
427
451
|
== Some(rusqlite::ErrorCode::AuthorizationForStatementDenied) =>
|
|
428
452
|
{
|
|
429
|
-
|
|
453
|
+
let msg = denial.lock().unwrap().unwrap_or(INTERNAL_TABLE_DENIED_MSG);
|
|
454
|
+
return Err(DbError::Unauthorized(msg.to_string()));
|
|
430
455
|
}
|
|
431
456
|
Err(e) => return Err(DbError::Sqlite(e)),
|
|
432
457
|
};
|
|
@@ -1057,6 +1082,44 @@ mod tests {
|
|
|
1057
1082
|
assert!(INTERNAL_TABLE_DENIED_MSG.contains("_dirsql_"));
|
|
1058
1083
|
}
|
|
1059
1084
|
|
|
1085
|
+
#[test]
|
|
1086
|
+
fn query_denies_attach() {
|
|
1087
|
+
let db = Db::new().unwrap();
|
|
1088
|
+
let err = db
|
|
1089
|
+
.query("ATTACH 'file:should-not-open?mode=ro' AS ext")
|
|
1090
|
+
.unwrap_err();
|
|
1091
|
+
assert!(matches!(err, DbError::Unauthorized(_)), "got: {err}");
|
|
1092
|
+
let msg = err.to_string();
|
|
1093
|
+
assert!(msg.contains("not authorized"), "got: {msg}");
|
|
1094
|
+
assert!(msg.contains("ATTACH"), "got: {msg}");
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
#[test]
|
|
1098
|
+
fn query_denies_detach() {
|
|
1099
|
+
let db = Db::new().unwrap();
|
|
1100
|
+
let err = db.query("DETACH ext").unwrap_err();
|
|
1101
|
+
assert!(matches!(err, DbError::Unauthorized(_)), "got: {err}");
|
|
1102
|
+
assert!(err.to_string().contains("not authorized"), "got: {err}");
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
#[test]
|
|
1106
|
+
fn attach_denied_message_mentions_attach_and_detach() {
|
|
1107
|
+
assert!(ATTACH_DENIED_MSG.contains("not authorized"));
|
|
1108
|
+
assert!(ATTACH_DENIED_MSG.contains("ATTACH"));
|
|
1109
|
+
assert!(ATTACH_DENIED_MSG.contains("DETACH"));
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
#[test]
|
|
1113
|
+
fn query_still_allows_select_after_attach_denial() {
|
|
1114
|
+
// The authorizer is cleared after each query, so a denied ATTACH must
|
|
1115
|
+
// not poison the next normal read.
|
|
1116
|
+
let db = Db::new().unwrap();
|
|
1117
|
+
db.create_table("CREATE TABLE t (id TEXT)").unwrap();
|
|
1118
|
+
let _ = db.query("ATTACH 'x.db' AS ext").unwrap_err();
|
|
1119
|
+
let rows = db.query("SELECT * FROM t").unwrap();
|
|
1120
|
+
assert_eq!(rows.len(), 0);
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1060
1123
|
#[test]
|
|
1061
1124
|
fn query_invalid_sql_returns_error() {
|
|
1062
1125
|
let db = Db::new().unwrap();
|
|
@@ -1260,6 +1323,22 @@ mod tests {
|
|
|
1260
1323
|
assert!(matches!(err, DbError::InvalidIdentifier(_)), "got: {err:?}");
|
|
1261
1324
|
}
|
|
1262
1325
|
|
|
1326
|
+
#[test]
|
|
1327
|
+
fn insert_row_round_trips_reserved_word_column() {
|
|
1328
|
+
let db = Db::new().unwrap();
|
|
1329
|
+
db.create_table("CREATE TABLE t (path TEXT, \"order\" INTEGER)")
|
|
1330
|
+
.unwrap();
|
|
1331
|
+
let row = HashMap::from([
|
|
1332
|
+
("path".into(), Value::Text("a".into())),
|
|
1333
|
+
("order".into(), Value::Integer(7)),
|
|
1334
|
+
]);
|
|
1335
|
+
db.insert_row("t", &row, "f.json", 0).unwrap();
|
|
1336
|
+
|
|
1337
|
+
let rows = db.get_rows_by_file("t", "f.json").unwrap();
|
|
1338
|
+
assert_eq!(rows.len(), 1);
|
|
1339
|
+
assert_eq!(rows[0]["order"], Value::Integer(7));
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1263
1342
|
#[test]
|
|
1264
1343
|
fn load_extension_missing_file_errors() {
|
|
1265
1344
|
let db = Db::new().unwrap();
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{dirsql-0.3.78 → dirsql-0.3.80}/packages/python/docs/tests/integration/language-flag.spec.ts
RENAMED
|
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
|
|
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
|