New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

dbay

Package Overview
Dependencies
Maintainers
1
Versions
70
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dbay - npm Package Compare versions

Comparing version 0.109.0 to 0.110.0

14

lib/ctx-mixin.js

@@ -40,3 +40,3 @@ (function() {

//-----------------------------------------------------------------------------------------------------------
this.Dbay_ctx = (clasz = Object) => {
this.DBay_ctx = (clasz = Object) => {
return class extends clasz {

@@ -108,11 +108,11 @@ //---------------------------------------------------------------------------------------------------------

begin_transaction() {
throw new E.Dbay_not_implemented('^dbay/ctx@1^', "tx_begin");
throw new E.DBay_not_implemented('^dbay/ctx@1^', "tx_begin");
}
commit_transaction() {
throw new E.Dbay_not_implemented('^dbay/ctx@2^', "tx_commit");
throw new E.DBay_not_implemented('^dbay/ctx@2^', "tx_commit");
}
rollback_transaction() {
throw new E.Dbay_not_implemented('^dbay/ctx@3^', "tx_rollback");
throw new E.DBay_not_implemented('^dbay/ctx@3^', "tx_rollback");
}

@@ -144,3 +144,3 @@

default:
throw new E.Dbay_wrong_arity('^dbay/ctx@4^', 'with_transaction()', 1, 2, arity);
throw new E.DBay_wrong_arity('^dbay/ctx@4^', 'with_transaction()', 1, 2, arity);
}

@@ -150,3 +150,3 @@ this.types.validate.dbay_with_transaction_cfg((cfg = {...this.constructor.C.defaults.dbay_with_transaction_cfg, ...cfg}));

if (this.sqlt1.inTransaction) {
throw new E.Dbay_no_nested_transactions('^dbay/ctx@5^');
throw new E.DBay_no_nested_transactions('^dbay/ctx@5^');
}

@@ -197,3 +197,3 @@ this.execute(SQL`begin ${cfg.mode} transaction;`);

if (this.sqlt1.inTransaction) {
throw new E.Dbay_no_deferred_fks_in_tx('^dbay/ctx@6^');
throw new E.DBay_no_deferred_fks_in_tx('^dbay/ctx@6^');
}

@@ -200,0 +200,0 @@ this.with_transaction(() => {

@@ -21,3 +21,3 @@ (function() {

//-----------------------------------------------------------------------------------------------------------
this.Dbay_error = class Dbay_error extends Error {
this.DBay_error = class DBay_error extends Error {
constructor(ref, message) {

@@ -33,3 +33,3 @@ super();

//-----------------------------------------------------------------------------------------------------------
this.Dbay_cfg_error = class Dbay_cfg_error extends this.Dbay_error {
this.DBay_cfg_error = class DBay_cfg_error extends this.DBay_error {
constructor(ref, message) {

@@ -41,3 +41,3 @@ super(ref, message);

this.Dbay_internal_error = class Dbay_internal_error extends this.Dbay_error {
this.DBay_internal_error = class DBay_internal_error extends this.DBay_error {
constructor(ref, message) {

@@ -49,3 +49,3 @@ super(ref, message);

this.Dbay_schema_exists = class Dbay_schema_exists extends this.Dbay_error {
this.DBay_schema_exists = class DBay_schema_exists extends this.DBay_error {
constructor(ref, schema) {

@@ -57,3 +57,3 @@ super(ref, `schema ${rpr(schema)} already exists`);

this.Dbay_schema_unknown = class Dbay_schema_unknown extends this.Dbay_error {
this.DBay_schema_unknown = class DBay_schema_unknown extends this.DBay_error {
constructor(ref, schema) {

@@ -65,3 +65,3 @@ super(ref, `schema ${rpr(schema)} does not exist`);

this.Dbay_object_unknown = class Dbay_object_unknown extends this.Dbay_error {
this.DBay_object_unknown = class DBay_object_unknown extends this.DBay_error {
constructor(ref, schema, name) {

@@ -73,3 +73,3 @@ super(ref, `object ${rpr(schema + '.' + name)} does not exist`);

this.Dbay_schema_nonempty = class Dbay_schema_nonempty extends this.Dbay_error {
this.DBay_schema_nonempty = class DBay_schema_nonempty extends this.DBay_error {
constructor(ref, schema) {

@@ -81,3 +81,3 @@ super(ref, `schema ${rpr(schema)} isn't empty`);

this.Dbay_schema_not_allowed = class Dbay_schema_not_allowed extends this.Dbay_error {
this.DBay_schema_not_allowed = class DBay_schema_not_allowed extends this.DBay_error {
constructor(ref, schema) {

@@ -89,3 +89,3 @@ super(ref, `schema ${rpr(schema)} not allowed here`);

this.Dbay_schema_repeated = class Dbay_schema_repeated extends this.Dbay_error {
this.DBay_schema_repeated = class DBay_schema_repeated extends this.DBay_error {
constructor(ref, schema) {

@@ -97,3 +97,3 @@ super(ref, `unable to copy schema to itself, got ${rpr(schema)}`);

this.Dbay_expected_single_row = class Dbay_expected_single_row extends this.Dbay_error {
this.DBay_expected_single_row = class DBay_expected_single_row extends this.DBay_error {
constructor(ref, row_count) {

@@ -105,3 +105,3 @@ super(ref, `expected 1 row, got ${row_count}`);

this.Dbay_expected_single_value = class Dbay_expected_single_value extends this.Dbay_error {
this.DBay_expected_single_value = class DBay_expected_single_value extends this.DBay_error {
constructor(ref, keys) {

@@ -113,3 +113,3 @@ super(ref, `expected row with single field, got fields ${rpr(keys)}`);

this.Dbay_extension_unknown = class Dbay_extension_unknown extends this.Dbay_error {
this.DBay_extension_unknown = class DBay_extension_unknown extends this.DBay_error {
constructor(ref, path) {

@@ -121,3 +121,3 @@ super(ref, `extension of path ${path} is not registered for any format`);

this.Dbay_not_implemented = class Dbay_not_implemented extends this.Dbay_error {
this.DBay_not_implemented = class DBay_not_implemented extends this.DBay_error {
constructor(ref, what) {

@@ -129,3 +129,3 @@ super(ref, `${what} isn't implemented (yet)`);

this.Dbay_deprecated = class Dbay_deprecated extends this.Dbay_error {
this.DBay_deprecated = class DBay_deprecated extends this.DBay_error {
constructor(ref, what) {

@@ -137,3 +137,3 @@ super(ref, `${what} has been deprecated`);

this.Dbay_unexpected_db_object_type = class Dbay_unexpected_db_object_type extends this.Dbay_error {
this.DBay_unexpected_db_object_type = class DBay_unexpected_db_object_type extends this.DBay_error {
constructor(ref, type, value) {

@@ -145,3 +145,3 @@ super(ref, `µ769 unknown type ${rpr(type)} of DB object ${d}`);

this.Dbay_sql_value_error = class Dbay_sql_value_error extends this.Dbay_error {
this.DBay_sql_value_error = class DBay_sql_value_error extends this.DBay_error {
constructor(ref, type, value) {

@@ -153,3 +153,3 @@ super(ref, `unable to express a ${type} as SQL literal, got ${rpr(value)}`);

this.Dbay_sql_not_a_list_error = class Dbay_sql_not_a_list_error extends this.Dbay_error {
this.DBay_sql_not_a_list_error = class DBay_sql_not_a_list_error extends this.DBay_error {
constructor(ref, type, value) {

@@ -161,3 +161,3 @@ super(ref, `expected a list, got a ${type}`);

this.Dbay_unexpected_sql = class Dbay_unexpected_sql extends this.Dbay_error {
this.DBay_unexpected_sql = class DBay_unexpected_sql extends this.DBay_error {
constructor(ref, sql) {

@@ -169,3 +169,3 @@ super(ref, `unexpected SQL string ${rpr(sql)}`);

this.Dbay_sqlite_too_many_dbs = class Dbay_sqlite_too_many_dbs extends this.Dbay_error {
this.DBay_sqlite_too_many_dbs = class DBay_sqlite_too_many_dbs extends this.DBay_error {
constructor(ref, schema) {

@@ -177,3 +177,3 @@ super(ref, `unable to attach schema ${rpr(schema)}: too many attached databases`);

this.Dbay_sqlite_error = class Dbay_sqlite_error extends this.Dbay_error {
this.DBay_sqlite_error = class DBay_sqlite_error extends this.DBay_error {
constructor(ref, error) {

@@ -186,3 +186,3 @@ var ref1;

this.Dbay_no_arguments_allowed = class Dbay_no_arguments_allowed extends this.Dbay_error {
this.DBay_no_arguments_allowed = class DBay_no_arguments_allowed extends this.DBay_error {
constructor(ref, name, arity) {

@@ -194,3 +194,3 @@ super(ref, `method ${name} doesn't take arguments, got ${arity}`);

this.Dbay_argument_not_allowed = class Dbay_argument_not_allowed extends this.Dbay_error {
this.DBay_argument_not_allowed = class DBay_argument_not_allowed extends this.DBay_error {
constructor(ref, name, value) {

@@ -202,3 +202,3 @@ super(ref, `argument ${name} not allowed, got ${rpr(value)}`);

this.Dbay_wrong_type = class Dbay_wrong_type extends this.Dbay_error {
this.DBay_wrong_type = class DBay_wrong_type extends this.DBay_error {
constructor(ref, types, type) {

@@ -210,3 +210,3 @@ super(ref, `expected ${types}, got a ${type}`);

this.Dbay_wrong_arity = class Dbay_wrong_arity extends this.Dbay_error {
this.DBay_wrong_arity = class DBay_wrong_arity extends this.DBay_error {
constructor(ref, name, min, max, found) {

@@ -218,3 +218,3 @@ super(ref, `${name} expected between ${min} and ${max} arguments, got ${found}`);

this.Dbay_empty_csv = class Dbay_empty_csv extends this.Dbay_error {
this.DBay_empty_csv = class DBay_empty_csv extends this.DBay_error {
constructor(ref, path) {

@@ -226,3 +226,3 @@ super(ref, `no CSV records found in file ${path}`);

this.Dbay_interpolation_format_unknown = class Dbay_interpolation_format_unknown extends this.Dbay_error {
this.DBay_interpolation_format_unknown = class DBay_interpolation_format_unknown extends this.DBay_error {
constructor(ref, format) {

@@ -234,3 +234,3 @@ super(ref, `unknown interpolation format ${rpr(format)}`);

this.Dbay_no_nested_transactions = class Dbay_no_nested_transactions extends this.Dbay_error {
this.DBay_no_nested_transactions = class DBay_no_nested_transactions extends this.DBay_error {
constructor(ref) {

@@ -242,3 +242,3 @@ super(ref, "cannot start a transaction within a transaction");

this.Dbay_no_deferred_fks_in_tx = class Dbay_no_deferred_fks_in_tx extends this.Dbay_error {
this.DBay_no_deferred_fks_in_tx = class DBay_no_deferred_fks_in_tx extends this.DBay_error {
constructor(ref) {

@@ -251,3 +251,3 @@ super(ref, "cannot defer foreign keys inside a transaction");

/* TAINT replace with more specific error, like below */
this.Dbay_format_unknown = class Dbay_format_unknown extends this.Dbay_error {
this.DBay_format_unknown = class DBay_format_unknown extends this.DBay_error {
constructor(ref, format) {

@@ -259,3 +259,3 @@ super(ref, `unknown DB format ${ref(format)}`);

this.Dbay_import_format_unknown = class Dbay_import_format_unknown extends this.Dbay_error {
this.DBay_import_format_unknown = class DBay_import_format_unknown extends this.DBay_error {
constructor(ref, format) {

@@ -262,0 +262,0 @@ var formats;

(function() {
'use strict';
var CND, Dbay_ctx, Dbay_openclose, Dbay_query, Dbay_random, Dbay_stdlib, Dbay_udf, E, FS, H, PATH, SQL, Sql, badge, debug, echo, guy, help, info, new_bsqlt3_connection, rpr, types, urge, warn, whisper;
var CND, DBay_ctx, DBay_openclose, DBay_query, DBay_random, DBay_stdlib, DBay_udf, E, FS, H, PATH, SQL, Sql, badge, debug, echo, guy, help, info, new_bsqlt3_connection, rpr, types, urge, warn, whisper;

@@ -44,13 +44,13 @@ //###########################################################################################################

({Dbay_query} = require('./query-mixin'));
({DBay_query} = require('./query-mixin'));
({Dbay_ctx} = require('./ctx-mixin'));
({DBay_ctx} = require('./ctx-mixin'));
({Dbay_openclose} = require('./open-close-mixin'));
({DBay_openclose} = require('./open-close-mixin'));
({Dbay_stdlib} = require('./stdlib-mixin'));
({DBay_stdlib} = require('./stdlib-mixin'));
({Dbay_random} = require('./random-mixin'));
({DBay_random} = require('./random-mixin'));
({Dbay_udf} = require('./udf-mixin'));
({DBay_udf} = require('./udf-mixin'));

@@ -60,4 +60,4 @@ ({Sql} = require('./sql'));

//===========================================================================================================
this.Dbay = (function() {
class Dbay extends Dbay_query(Dbay_ctx(Dbay_openclose(Dbay_stdlib(Dbay_random(Dbay_udf(Function)))))) {
this.DBay = (function() {
class DBay extends DBay_query(DBay_ctx(DBay_openclose(DBay_stdlib(DBay_random(DBay_udf(Function)))))) {
//---------------------------------------------------------------------------------------------------------

@@ -204,3 +204,3 @@ static cast_sqlt_cfg(me) {

//---------------------------------------------------------------------------------------------------------
Dbay.C = guy.lft.freeze({
DBay.C = guy.lft.freeze({
autolocation: H.autolocation,

@@ -263,3 +263,3 @@ symbols: {

return Dbay;
return DBay;

@@ -266,0 +266,0 @@ }).call(this);

@@ -22,3 +22,3 @@ (function() {

//===========================================================================================================
this.Dbay_openclose = (clasz = Object) => {
this.DBay_openclose = (clasz = Object) => {
return class extends clasz {

@@ -25,0 +25,0 @@ //---------------------------------------------------------------------------------------------------------

@@ -21,3 +21,3 @@ (function() {

//===========================================================================================================
this.Dbay_query = (clasz = Object) => {
this.DBay_query = (clasz = Object) => {
var _class;

@@ -59,3 +59,3 @@ return _class = class extends clasz {

}
throw new E.Dbay_wrong_type('^dbay/query@1^', 'a text, an object, or a function', type);
throw new E.DBay_wrong_type('^dbay/query@1^', 'a text, an object, or a function', type);
}

@@ -143,3 +143,3 @@

if ((rows = this.all_rows(sql, ...P)).length !== 1) {
throw new E.Dbay_expected_single_row('^dbay/query@2^', rows.length);
throw new E.DBay_expected_single_row('^dbay/query@2^', rows.length);
}

@@ -154,3 +154,3 @@ return rows[0];

if ((keys = Object.keys(row)).length !== 1) {
throw new E.Dbay_expected_single_value('^dbay/query@4^', keys);
throw new E.DBay_expected_single_value('^dbay/query@4^', keys);
}

@@ -163,3 +163,3 @@ return row[keys[0]];

if (P.length > 0) {
throw new E.Dbay_argument_not_allowed('^dbay/query@5^', "extra", rpr(P));
throw new E.DBay_argument_not_allowed('^dbay/query@5^', "extra", rpr(P));
}

@@ -166,0 +166,0 @@ this.sqlt1.exec(sql);

@@ -18,3 +18,3 @@ (function() {

//===========================================================================================================
this.Dbay_random = (clasz = Object) => {
this.DBay_random = (clasz = Object) => {
return (function() {

@@ -21,0 +21,0 @@ var _Class;

@@ -65,3 +65,3 @@ (function() {

// when 'list' then throw new Error "^dba@23^ use `X()` for lists"
throw new E.Dbay_sql_value_error('^dbay/sql@1^', type, x);
throw new E.DBay_sql_value_error('^dbay/sql@1^', type, x);
}

@@ -72,3 +72,3 @@

if ((type = type_of(x)) !== 'list') {
throw new E.Dbay_sql_not_a_list_error('^dbay/sql@2^', type, x);
throw new E.DBay_sql_not_a_list_error('^dbay/sql@2^', type, x);
}

@@ -110,3 +110,3 @@ return '( ' + (((function() {

}
throw new E.Dbay_interpolation_format_unknown('^dbay/sql@3^', format);
throw new E.DBay_interpolation_format_unknown('^dbay/sql@3^', format);
});

@@ -113,0 +113,0 @@ }

@@ -29,3 +29,3 @@ (function() {

//-----------------------------------------------------------------------------------------------------------
this.Dbay_stdlib = (clasz = Object) => {
this.DBay_stdlib = (clasz = Object) => {
return class extends clasz {

@@ -32,0 +32,0 @@ /* TAINT use `cfg` */

@@ -38,3 +38,3 @@ (function() {

//-----------------------------------------------------------------------------------------------------------
this.Dbay_udf = (clasz = Object) => {
this.DBay_udf = (clasz = Object) => {
return class extends clasz {

@@ -41,0 +41,0 @@ //---------------------------------------------------------------------------------------------------------

{
"name": "dbay",
"version": "0.109.0",
"version": "0.110.0",
"description": "In-Process, In-Memory & File-Based Relational Data Processing with SQLite, BetterSQLite3",

@@ -5,0 +5,0 @@ "main": "lib/main.js",

@@ -1,4 +0,6 @@

# DBay
# 𓆤DBay
<!-- START doctoc generated TOC please keep comment here to allow auto update -->

@@ -8,9 +10,27 @@ <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [Under Construction](#under-construction)
- [Introduction](#introduction)
- [Documentation](#documentation)
- [Note on Package Structure](#note-on-package-structure)
- [`better-sqlite3` an 'Unsaved' Dependency](#better-sqlite3-an-unsaved-dependency)
- [Use npm, Not pnpm](#use-npm-not-pnpm)
- [To Do](#to-do)
- [𓆤DBay](#%F0%93%86%A4dbay)
- [Introduction](#introduction)
- [Documentation](#documentation)
- [Main](#main)
- [Using Defaults](#using-defaults)
- [Automatic Location](#automatic-location)
- [Randomly Chosen Filename](#randomly-chosen-filename)
- [Using Parameters](#using-parameters)
- [Opening and Closing DBs](#opening-and-closing-dbs)
- [Opening / Attaching DBs](#opening--attaching-dbs)
- [Closing / Detaching DBs](#closing--detaching-dbs)
- [Transactions and Context Handlers](#transactions-and-context-handlers)
- [Query](#query)
- [Executing SQL](#executing-sql)
- [User-Defined Functions (UDFs)](#user-defined-functions-udfs)
- [Standard Library of SQL Functions (StdLib)](#standard-library-of-sql-functions-stdlib)
- [Safe Escaping for SQL Values and Identifiers](#safe-escaping-for-sql-values-and-identifiers)
- [Purpose](#purpose)
- [Escaping Identifiers, General Values, and List Values](#escaping-identifiers-general-values-and-list-values)
- [Statement Interpolation](#statement-interpolation)
- [Random](#random)
- [Note on Package Structure](#note-on-package-structure)
- [`better-sqlite3` an 'Unsaved' Dependency](#better-sqlite3-an-unsaved-dependency)
- [Use npm, Not pnpm](#use-npm-not-pnpm)
- [To Do](#to-do)

@@ -20,7 +40,14 @@ <!-- END doctoc generated TOC please keep comment here to allow auto update -->

## Under Construction
DBay is the successor to and a re-write of [icql-dba](https://github.com/loveencounterflow/icql-dba) which
you'll probably want to use for the time being until this package reaches MVP.
# 𓆤DBay
DBay is built on [`better-sqlite3`](https://github.com/JoshuaWise/better-sqlite3), which is a NodeJS adapter
for [SQLite](https://www.sqlite.org). It provides convenient access to in-process, on-file and in-memory
relational databases. <!-- The mascot of DBay is the -->
DBay is the successor to and a re-write of [ICQL-DBA](https://github.com/loveencounterflow/icql-dba). It is
under development and nearing feature-parity with its predecessor while already providing some significant
improvements in terms of ease of use and simplicity of implementation.
## Introduction

@@ -39,9 +66,242 @@

* **[`Dbay` object construction](./README-construction.md)**
* **[Benchmarks](./README-benchmarks.md)**
* **[Executing SQL and Queries](./README-query.md)**
* **[Opening and Closing DBs](./README-open-close.md)**
* **[SQL Processing Helpers](./README-sql.md)**
* **[API](./README-api.md)**
------------------------------------------------------------------------------------------------------------
### Main
#### Using Defaults
In order to construct (instantiate) a DBay object, you can call the constructor without any arguments:
```coffee
{ DBay } = require 'dbay'
db = new DBay()
```
The `db` object will then have two properties `db.sqlt1` and `db.sqlt2` that are `better-sqlite3`
connections to the same temporary DB in the ['automatic location'](#automatic-location).
#### Automatic Location
The so-called 'automatic location' is either
* the directory `/dev/shm` on Linux systems that support **SH**ared **M**emory (a.k.a a RAM disk)
* the OS's temporary directory as announced by `os.tmpdir()`
In either case, a [file with a random name](#randomly-chosen-filename) will be created in that location.
#### Randomly Chosen Filename
Format `dbay-NNNNNNNNNN.sqlite`, where `N` is a digit `[0-9]`.
#### Using Parameters
You can also call the constructor with a configuration object that may have one or more of the following
fields:
* **`cfg.path`** (`?non-empty text`): Specifies which file system path to save the DB to; if the path given
is relative, it will be resolved in reference to the current directory (`process.cwd()`). When not
specified, `cfg.path` will be derived from [`DBay.C.autolocation`](#automatic-location) and a [randomly
chosen filename](#randomly-chosen-filename).
* **`cfg.temporary`** (`?boolean`): Specifies whether DB file is to be removed when process exits or
`db.destry()` is called explicitly. `cfg.temporary` defaults to `false` if `cfg.path` is given, and `true`
otherwise (when a random filename is chosen).
------------------------------------------------------------------------------------------------------------
### Opening and Closing DBs
#### Opening / Attaching DBs
* **`db.open cfg`**: [Attach](https://www.sqlite.org/lang_attach.html) a new or existing DB to the `db`'s
connections (`db.sqlt1`, `db.sqlt1`).
* `cfg`:
* `schema` (non-empty string): Required property that specifies the name under which the newly attached
DB's objects can be accessed as; having attached a DB as, say, `db.open { schema: 'foo', path:
'path/to/my.db', }`, one can then run queries like `db "select * from foo.main;"` against it. Observe
that
* the DB opened at object creation time (`db = new DBay()`) always has the implicit name `main`, and
schema `temp` is reserved for temporary databases.
* `path` (string): FS path to existing or to-be-created DB file; for compatibility, this may also be set
[to one of the special values that indicates a in-memory
DB](./README-benchmarks.md#sqlite-is-not-fast-except-when-it-is), although that is not recommended.
* `temporary` (boolean): Defaults to `false` when a `path` is given, and to `true` otherwise.
* The custom SQLite library that is compiled when installing DBay has its `SQLITE_LIMIT_ATTACHED`
compilation parameter set to the maximum allowed value of 125 (instead of the default 10). This allows
developers to assemble a DB application from dozens of smaller pieces when desired.
#### Closing / Detaching DBs
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
------------------------------------------------------------------------------------------------------------
### Transactions and Context Handlers
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
------------------------------------------------------------------------------------------------------------
### Query
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
#### Executing SQL
One thing that sets DBay apart from other database adapters is the fact that the object returned from `new
DBay()` is both the representative of the database opened *and* a callable function. This makes executing
statements and running queries very concise. This is an excerpt from the [DBay test suite]():
```coffee
{ DBay } = require H.dbay_path
db = new DBay()
db ->
db SQL"drop table if exists texts;"
db SQL"create table texts ( nr integer not null primary key, text text );"
db SQL"insert into texts values ( 3, 'third' );"
db SQL"insert into texts values ( 1, 'first' );"
db SQL"insert into texts values ( ?, ? );", [ 2, 'second', ]
#.......................................................................................................
T?.throws /cannot start a transaction within a transaction/, ->
db ->
#.........................................................................................................
T?.throws /UNIQUE constraint failed: texts\.nr/, ->
db ->
db SQL"insert into texts values ( 3, 'third' );"
#.........................................................................................................
rows = db SQL"select * from texts order by nr;"
rows = [ rows..., ]
T?.eq rows, [ { nr: 1, text: 'first' }, { nr: 2, text: 'second' }, { nr: 3, text: 'third' } ]
```
> **Note** In the above `SQL` has been set to `String.raw` and has no further effect on the string it
> precedes; it is just used as a syntax marker (cool because then you can have nested syntax hiliting).
As shown by [benchmarks](./README-benchmarks.md), a crucial factor for getting maximum performance out of
using SQLite is strategically placed transactions. SQLite will not ever execute a DB query *outside* of a
transaction; when no transaction has been explicitly opened with `begin transaction`, the DB engine will
precede each query implicitly with (the equivalent of) `begin transaction` and follow it with either
`commit` or `rollback`. This means when a thousand `insert` statements are run, a thousand transactions will
be started and committed, leavin performance pretty much in the dust.
To avoid that performance hit, users are advised to always start and commit transactions when doing many
consecutive queries. DBay's callable `db` object makes that easy: just write `db -> many; inserts; here;`
(JS: `db( () -> { many; inserts; here; })`), i.e. pass a function as the sole argument to `db`, and DBay
will wrap that function with a transaction. In case an error should occur, DBay guarantees to call
`rollback` (in a `try ... finally ...` clause). Those who like to make things more explicit can also use
`db.with_transaction ->`. Both formats allow to pass in a configuration object with an attribute `mode` that
may be set to [one of `'deferred'`, `'immediate'`, or
`'exclusive'`](https://www.sqlite.org/lang_transaction.html), the default being `'deferred'`.
Another slight performance hit may be caused by the logic DBay uses to (look up an SQL text in a cache or)
prepare a statement and then decide whether to call `better-sqlite3`'s' `Database::execute()`,
`Statement::run()` or `Statement::iterate()`; in order to circumvent that extra work, users may choose to
fall back on to `better-sqlite3` explicitly:
```coffee
insert = db.prepare SQL"insert into texts values ( ?, ? );" # returns a `better-sqlite3` `Statement` instance
db ->
insert [ 2, 'second', ]
```
------------------------------------------------------------------------------------------------------------
### User-Defined Functions (UDFs)
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
------------------------------------------------------------------------------------------------------------
### Standard Library of SQL Functions (StdLib)
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
------------------------------------------------------------------------------------------------------------
### Safe Escaping for SQL Values and Identifiers
#### Purpose
* Facilitate the creation of securely escaped SQL literals.
* In general not thought of as a replacement for the value interpolation offered by `DBay::prepare()`,
`DBay::query()` and so, except when
* one wants to parametrize DB object names (e.g. use table or column names like variables),
* one wants to interpolate an SQL `values` list, as in `select employee from employees where department in
( 'sales', 'HR' );`.
#### Escaping Identifiers, General Values, and List Values
* **`db.sql.I: ( name ): ->`**: returns a properly quoted and escaped SQL **I**dentifier.
* **`db.sql.L: ( x ): ->`**: returns a properly quoted and escaped SQL **V**alue. Note that booleans
(`true`, `false`) will be converted to `1` and `0`, respectively.
* **`db.sql.V: ( x ): ->`**: returns a bracketed SQL list of values (using `db.sql.V()` for each list
element).
#### Statement Interpolation
**`db.interpolate( sql, values ): ->`** accepts a template (a string with placeholder formulas) and a list
or object of values. It returns a string with the placeholder formulas replaced with the escaped values.
```coffee
# using named placeholders
sql = SQL"select $:col_a, $:col_b where $:col_b in $V:choices"
d = { col_a: 'foo', col_b: 'bar', choices: [ 1, 2, 3, ], }
result = db.sql.interpolate sql, d
# > """select "foo", "bar" where "bar" in ( 1, 2, 3 )"""
```
```coffee
# using positional placeholders
sql = SQL"select ?:, ?: where ?: in ?V:"
d = [ 'foo', 'bar', 'bar', [ 1, 2, 3, ], ]
result = db.sql.interpolate sql, d
# > """select "foo", "bar" where "bar" in ( 1, 2, 3 )"""
```
```coffee
# using an unknown format
sql = SQL"select ?:, ?X: where ?: in ?V:"
d = [ 'foo', 'bar', 'bar', [ 1, 2, 3, ], ]
result = db.sql.interpolate sql, d
# throws "unknown interpolation format 'X'"
```
------------------------------------------------------------------------------------------------------------
### Random
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊▌▊
------------------------------------------------------------------------------------------------------------
## Note on Package Structure

@@ -91,15 +351,15 @@

* **[–]** implement context handler for discardable / temporary file
* **[+]** implement `Dbay::do()` as a method that unifies all of `better-sqlite3`'s `Statement::run()`,
* **[+]** implement `DBay::do()` as a method that unifies all of `better-sqlite3`'s `Statement::run()`,
`Statement::iterate()`, and `Database::execute()`.
* **[+]** allow to call `Dbay::do -> ...` with a synchronous function with the same semantics as
`Dbay::with_transaction -> ...`.
* **[+]** allow to call `Dbay::do { mode: 'deferred', }, -> ...`.
* **[–]** allow to call `Dbay::do -> ...` with an asynchronous function
* **[+]** make `db = new Dbay()` an instance of `Function` that, when called, runs `Dbay::do()`
* **[+]** allow to call `DBay::do -> ...` with a synchronous function with the same semantics as
`DBay::with_transaction -> ...`.
* **[+]** allow to call `DBay::do { mode: 'deferred', }, -> ...`.
* **[–]** allow to call `DBay::do -> ...` with an asynchronous function
* **[+]** make `db = new DBay()` an instance of `Function` that, when called, runs `DBay::do()`
`Database::execute()`.
* **[–]** implement `Dbay::insert_into.<table> [ 'field1', 'field2', ..., ], { field1, field2, ..., }` and
`statement = Dbay::prepare.insert_into.<table> [ 'field1', 'field2', ..., ]`
* **[–]** change classname(s) from `Dbay` to `DBay` to avoid spelling variant proliferation
* **[–]** implement `Dbay::open()`, `Dbay::close()`
* **[–]** implement `DBay::insert_into.<table> [ 'field1', 'field2', ..., ], { field1, field2, ..., }` and
`statement = DBay::prepare.insert_into.<table> [ 'field1', 'field2', ..., ]`
* **[–]** change classname(s) from `DBay` to `DBay` to avoid spelling variant proliferation
* **[–]** implement `DBay::open()`, `DBay::close()`
* **[–]** ensure how cross-schema foreign keys work when re-attaching DBs / schemas one by one
* **[–]** demote `random` from a mixin to functions in `helpers`.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc