icql-dba
Version:
An SQLite DB Adapter built with BetterSQLite3
474 lines (428 loc) • 25.6 kB
text/coffeescript
'use strict'
############################################################################################################
CND = require 'cnd'
rpr = CND.rpr
badge = 'MKTS-PARSER/TYPES'
debug = CND.get_logger 'debug', badge
alert = CND.get_logger 'alert', badge
whisper = CND.get_logger 'whisper', badge
warn = CND.get_logger 'warn', badge
help = CND.get_logger 'help', badge
urge = CND.get_logger 'urge', badge
info = CND.get_logger 'info', badge
jr = JSON.stringify
Intertype = ( require 'intertype' ).Intertype
intertype = new Intertype module.exports
Dba = null
#-----------------------------------------------------------------------------------------------------------
@declare 'icql_settings',
tests:
"x is a object": ( x ) -> @isa.object x
# "x has key 'db_path'": ( x ) -> @has_key x, 'db_path'
# "x has key 'icql_path'": ( x ) -> @has_key x, 'icql_path'
"x.db_path is a nonempty text": ( x ) -> @isa.nonempty_text x.db_path
"x.icql_path is a nonempty text": ( x ) -> @isa.nonempty_text x.icql_path
"x.echo? is a boolean": ( x ) -> @isa_optional.boolean x.echo
#-----------------------------------------------------------------------------------------------------------
@declare 'ic_entry_type',
tests:
"x is a text": ( x ) -> @isa.text x
"x is in 'procedure', 'query', 'fragment'": ( x ) -> x in [ 'procedure', 'query', 'fragment', ]
#-----------------------------------------------------------------------------------------------------------
@declare 'ic_schema', ( x ) ->
### NOTE to keep things simple, only allow lower case ASCII letters, digits, underscores in schemas ###
return false unless @isa.text x
return ( /^[a-z_][a-z0-9_]*$/ ).test x
#-----------------------------------------------------------------------------------------------------------
@declare 'ic_not_temp_schema', ( x ) -> ( @isa.ic_schema x ) and ( x isnt 'temp' )
@declare 'ic_path', ( x ) -> @isa.text x
@declare 'ic_name', ( x ) -> @isa.nonempty_text x
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_ram_path', ( x ) -> x in [ null, '', ':memory:', ]
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_constructor_cfg', tests:
"x is an object": ( x ) -> @isa.object x
"x._temp_prefix is a ic_schema": ( x ) -> @isa.ic_schema x._temp_prefix
"@isa.boolean x.readonly": ( x ) -> @isa.boolean x.readonly
"@isa.boolean x.create": ( x ) -> @isa.boolean x.create
"@isa.boolean x.overwrite": ( x ) -> @isa.boolean x.overwrite
### TAINT possibly `timout: 0` could be valid ###
"@isa.positive_float x.timeout": ( x ) -> @isa.positive_float x.timeout
# "@isa.ic_not_temp_schema x.schema": ( x ) -> @isa.ic_not_temp_schema x.schema
"@isa_optional.ic_path x.path": ( x ) -> @isa_optional.ic_path x.path
"@isa.boolean x.ram": ( x ) -> @isa.boolean x.ram
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_open_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_not_temp_schema x.schema": ( x ) -> @isa.ic_not_temp_schema x.schema
"@isa_optional.ic_path x.path": ( x ) -> @isa_optional.ic_path x.path
"@isa.boolean x.ram": ( x ) -> @isa.boolean x.ram
# "@isa.boolean x.overwrite": ( x ) -> @isa.boolean x.overwrite
# "@isa.boolean x.create": ( x ) -> @isa.boolean x.create
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_create_function_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.nonempty_text x.name": ( x ) -> @isa.nonempty_text x.name
"@isa.function x.call": ( x ) -> @isa.function x.call
"@isa.boolean x.deterministic": ( x ) -> @isa.boolean x.deterministic
"@isa.boolean x.varargs": ( x ) -> @isa.boolean x.varargs
"@isa.boolean x.directOnly": ( x ) -> @isa.boolean x.directOnly
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_create_aggregate_function_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.nonempty_text x.name": ( x ) -> @isa.nonempty_text x.name
# "@isa.any x.start": ( x ) -> @isa.any x.start
"@isa.function x.step": ( x ) -> @isa.function x.step
"@isa.boolean x.deterministic": ( x ) -> @isa.boolean x.deterministic
"@isa.boolean x.varargs": ( x ) -> @isa.boolean x.varargs
"@isa.boolean x.directOnly": ( x ) -> @isa.boolean x.directOnly
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_create_window_function_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.nonempty_text x.name": ( x ) -> @isa.nonempty_text x.name
# "@isa.any x.start": ( x ) -> @isa.any x.start
"@isa.function x.step": ( x ) -> @isa.function x.step
"@isa.function x.inverse": ( x ) -> @isa.function x.inverse
"@isa_optional.function x.result": ( x ) -> @isa_optional.function x.result
"@isa.boolean x.deterministic": ( x ) -> @isa.boolean x.deterministic
"@isa.boolean x.varargs": ( x ) -> @isa.boolean x.varargs
"@isa.boolean x.directOnly": ( x ) -> @isa.boolean x.directOnly
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_create_table_function_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.nonempty_text x.name": ( x ) -> @isa.nonempty_text x.name
"@isa_optional.list x.columns": ( x ) -> @isa_optional.list x.columns
"@isa_optional.list x.parameters": ( x ) -> @isa_optional.list x.parameters
"@isa.generatorfunction x.rows": ( x ) -> @isa.generatorfunction x.rows
"@isa.boolean x.deterministic": ( x ) -> @isa.boolean x.deterministic
"@isa.boolean x.varargs": ( x ) -> @isa.boolean x.varargs
"@isa.boolean x.directOnly": ( x ) -> @isa.boolean x.directOnly
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_create_virtual_table_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.nonempty_text x.name": ( x ) -> @isa.nonempty_text x.name
"@isa.function x.create": ( x ) -> @isa.function x.create
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_import_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_not_temp_schema x.schema": ( x ) -> @isa.ic_not_temp_schema x.schema
"@isa.ic_path x.path": ( x ) -> @isa.ic_path x.path
"@isa_optional.dba_format x.format": ( x ) -> @isa_optional.dba_format x.format
"x.method in [ 'single', 'batch', ]": ( x ) -> x.method in [ 'single', 'batch', ]
"@isa_optional.positive_integer x.batch_size": ( x ) -> @isa_optional.positive_integer x.batch_size
# "x.overwrite is a boolean": ( x ) -> @isa.boolean x.overwrite
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_import_cfg_csv', tests:
"@isa.dba_import_cfg x": ( x ) -> @isa.dba_import_cfg x
"@isa.ic_name x.table_name": ( x ) -> @isa.ic_name x.table_name
### NOTE see `_import_csv()`; for now only RAM DBs allowed for imported CSV ###
"@isa.true x.ram": ( x ) -> @isa.true x.ram
# "@isa.boolean x.skip_first": ( x ) -> @isa.boolean x.skip_first
# "@isa.boolean x.skip_empty": ( x ) -> @isa.boolean x.skip_empty
# "@isa.boolean x.skip_blank": ( x ) -> @isa.boolean x.skip_blank
"@isa.boolean x.skip_any_null": ( x ) -> @isa.boolean x.skip_any_null
"@isa.boolean x.skip_all_null": ( x ) -> @isa.boolean x.skip_all_null
"@isa.boolean x.trim": ( x ) -> @isa.boolean x.trim
"@isa.any x.default_value": ( x ) -> true
"@isa_optional.object x._extra": ( x ) -> @isa_optional.object x._extra
"x.table is deprecated": ( x ) -> x.table is undefined
"x.columns is deprecated": ( x ) -> x.columns is undefined
"x.transform is a function (sync or async)": ( x ) ->
return true if ( not x.transform? )
return true if @isa.asyncfunction x.transform
return true if @isa.function x.transform
return false
"x.skip_comments is a boolean or a nonempty_text": ( x ) ->
( @isa.boolean x.skip_comments ) or ( @isa.nonempty_text x.skip_comments )
"optional input_columns isa nonempty list of nonempty text": ( x ) ->
{ input_columns: d, } = x
return true if not d?
return true if d is true
return false unless @isa.list d
return false unless d.length > 0
return false unless @isa_list_of.nonempty_text d
return true
"optional table_columns isa nonempty list of nonempty text": ( x ) ->
{ table_columns: d, } = x
return true if not d?
switch @type_of d
when 'list'
return false unless d.length > 0
return false unless @isa_list_of.nonempty_text d
when 'object'
k = ( k for k, v of d )
return false unless k.length > 0
return false unless @isa_list_of.nonempty_text k
v = ( v for k, v of d )
return false unless v.length > 0
return false unless @isa_list_of.nonempty_text v
else
return false
return true
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_import_cfg_csv_extra', tests:
### see https://csv.js.org/parse/options/ ###
### relying on `csv-parse` to do the right thing ###
"@isa_optional.object x": ( x ) -> @isa_optional.object x
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_save_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_not_temp_schema x.schema": ( x ) -> @isa.ic_not_temp_schema x.schema
"@isa_optional.ic_path x.path": ( x ) -> @isa_optional.ic_path x.path
"@isa_optional.dba_format x.format": ( x ) -> @isa_optional.dba_format x.format
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_vacuum_atomically', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_not_temp_schema x.schema": ( x ) -> @isa.ic_not_temp_schema x.schema
"@isa_optional.ic_path x.path": ( x ) -> @isa_optional.ic_path x.path
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_export_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_not_temp_schema x.schema": ( x ) -> @isa.ic_not_temp_schema x.schema
"@isa.ic_path x.path": ( x ) -> @isa.ic_path x.path
"@isa_optional.dba_format x.format": ( x ) -> @isa_optional.dba_format x.format
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_attach_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_not_temp_schema x.schema": ( x ) -> @isa.ic_not_temp_schema x.schema
"@isa.ic_path x.path": ( x ) -> @isa.ic_path x.path
"( x.saveas is null ) or @isa.ic_path x.saveas": ( x ) -> ( x.saveas is null ) or @isa.ic_path x.saveas
#-----------------------------------------------------------------------------------------------------------
@declare 'copy_or_move_schema_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_not_temp_schema x.from_schema": ( x ) -> @isa.ic_not_temp_schema x.from_schema
"@isa.ic_not_temp_schema x.to_schema": ( x ) -> @isa.ic_not_temp_schema x.to_schema
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_is_ram_db_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_detach_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_has_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_is_empty_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
"@isa.nonempty_text x.name": ( x ) -> @isa_optional.ic_name x.name
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_clear_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_walk_objects_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
"x._ordering is optionally 'drop'": ( x ) -> ( not x._ordering? ) or ( x._ordering is 'drop' )
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_type_of_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
"@isa.nonempty_text x.name": ( x ) -> @isa_optional.ic_name x.name
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_fields_of_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
"@isa.nonempty_text x.name": ( x ) -> @isa_optional.ic_name x.name
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_field_names_of_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
"@isa.nonempty_text x.name": ( x ) -> @isa_optional.ic_name x.name
#-----------------------------------------------------------------------------------------------------------
@declare 'sql_limit', ( x ) ->
return true unless x?
return true if @isa.nonempty_text x
return true if @isa.cardinal x
return false
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_dump_relation_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.schema": ( x ) -> @isa.ic_schema x.schema
"@isa.nonempty_text x.name": ( x ) -> @isa_optional.ic_name x.name
"@isa.nonempty_text x.order_by": ( x ) -> @isa.nonempty_text x.order_by
"@isa.sql_limit x.limit": ( x ) -> @isa.sql_limit x.limit
#-----------------------------------------------------------------------------------------------------------
@declare 'dba', tests:
"x instanceof Dba": ( x ) -> x instanceof ( Dba ?= ( require './main' ).Dba )
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_with_transaction_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"x.mode in [ 'deferred', 'immediate', 'exclusive', ]": \
( x ) -> x.mode in [ 'deferred', 'immediate', 'exclusive', ]
#-----------------------------------------------------------------------------------------------------------
@declare 'dba_create_stdlib_cfg', tests:
"@isa.object x": ( x ) -> @isa.object x
"@isa.ic_schema x.prefix": ( x ) -> @isa.ic_schema x.prefix
#-----------------------------------------------------------------------------------------------------------
@defaults =
#.........................................................................................................
dba_constructor_cfg:
_temp_prefix: '_dba_temp_'
readonly: false
create: true
overwrite: false
timeout: 5000
# schema: 'main'
path: null
ram: false
#.........................................................................................................
dba_attach_cfg:
schema: null
path: ''
saveas: null
#.........................................................................................................
dba_detach_cfg:
schema: null
#.........................................................................................................
dba_has_cfg:
schema: null
#.........................................................................................................
dba_open_cfg:
schema: 'main'
path: null
ram: false
# overwrite: false
# create: true
#.........................................................................................................
dba_export_cfg:
schema: null
path: null
format: null
#.........................................................................................................
dba_save_cfg:
schema: null
path: null
format: null
#.........................................................................................................
dba_create_function_cfg:
deterministic: true
varargs: false
directOnly: false
#.........................................................................................................
dba_create_aggregate_function_cfg:
deterministic: true
varargs: false
directOnly: false
start: null
#.........................................................................................................
dba_create_window_function_cfg:
deterministic: true
varargs: false
directOnly: false
start: null
#.........................................................................................................
dba_create_table_function_cfg:
deterministic: true
varargs: false
directOnly: false
#.........................................................................................................
dba_create_virtual_table_cfg: {}
#.........................................................................................................
dba_vacuum_atomically:
schema: null
path: null
#.........................................................................................................
dba_import_cfg:
schema: null
path: null
format: null
method: 'single'
batch_size: 1000
#.........................................................................................................
dba_import_cfg_csv:
table_name: 'main'
transform: null
_extra: null
skip_any_null: false
skip_all_null: false
skip_comments: false
trim: true
default_value: null
# skip_first: false
# skip_empty: true
# skip_blank: true
#.........................................................................................................
dba_import_cfg_csv_extra:
### see https://github.com/mafintosh/csv-parser#options ###
headers: false # Array[String] | Boolean
escape: '"' # String, default: "
# mapHeaders: null # Function
# mapValues: null # Function (not used as it calls for each cell instead of for each row)
newline: '\n' # String, default: '\n'
quote: '"' # String, default: '"'
raw: false # Boolean, default: false
separator: ',' # String, Default: ','
skipComments: false # Boolean | String, default: false
skipLines: 0 # Number, default: 0
maxRowBytes: Infinity # Number, Default: Number.MAX_SAFE_INTEGER
strict: false # Boolean, default: false
#.........................................................................................................
dba_import_cfg_tsv_extra:
### see https://github.com/mafintosh/csv-parser#options ###
headers: false # Array[String] | Boolean
escape: '' # String, default: "
# mapHeaders: null # Function
# mapValues: null # Function (not used as it calls for each cell instead of for each row)
newline: '\n' # String, default: '\n'
quote: '' # String, default: '"'
raw: false # Boolean, default: false
separator: '\t' # String, Default: ','
skipComments: false # Boolean | String, default: false
skipLines: 0 # Number, default: 0
maxRowBytes: Infinity # Number, Default: Number.MAX_SAFE_INTEGER
strict: false # Boolean, default: false
#.........................................................................................................
copy_or_move_schema_cfg:
from_schema: null
to_schema: null
#.........................................................................................................
dba_is_ram_db_cfg:
schema: null
#.........................................................................................................
dba_clear_cfg:
schema: null
#.........................................................................................................
dba_walk_objects_cfg:
schema: null
_ordering: null
#.........................................................................................................
extensions_and_formats:
db: 'sqlite'
sqlite: 'sqlite'
sqlitedb: 'sqlite'
sql: 'sql'
txt: 'tsv'
tsv: 'tsv'
csv: 'csv'
#.........................................................................................................
dba_type_of_cfg:
schema: null
name: null
#.........................................................................................................
dba_fields_of_cfg:
schema: null
name: null
#.........................................................................................................
dba_field_names_of_cfg:
schema: null
name: null
#.........................................................................................................
dba_dump_relation_cfg:
schema: null
name: null
order_by: 'random()'
limit: 10
#.........................................................................................................
dba_with_transaction_cfg:
mode: 'deferred'
#.........................................................................................................
dba_create_stdlib_cfg:
prefix: 'std_'
#-----------------------------------------------------------------------------------------------------------
@_import_formats = _import_formats = new Set Object.keys @defaults.extensions_and_formats
@declare 'dba_format', ( x ) -> _import_formats.has x