-
Notifications
You must be signed in to change notification settings - Fork 2
DbLang
DbLang is the common ancestor for classes representing different dialects of SQL and, possibly, other database programming languages.
The base implementation mostly follows ANSI SQL.
An instance of DbLang or its descendant must be available as the .lang property of each DbPool and each DbModel.
| Name | Type | Description |
|---|---|---|
TP_SMALLINT |
DbTypeArithmeticInt | 2-byte signed interger |
TP_INT |
DbTypeArithmeticInt | 4-byte signed interger |
TP_BIGINT |
DbTypeArithmeticInt | 8-byte signed interger |
TP_REAL |
DbTypeArithmeticFloat | floating point REAL
|
TP_NUMERIC |
DbTypeArithmeticFixed | the base fixed point arithmetic type (also used for DECIMAL) |
TP_CHAR |
DbTypeCharacter | string type named CHAR
|
TP_VARCHAR |
DbTypeCharacter | string type named VARCHAR
|
| Name | Type | Description |
|---|---|---|
model |
DbModel | The related database model instance |
For given asIs and toBe DbColumns, returns an array of strings meaning the names of their differing properties, specifically:
-
nullableif.nullablevalues are not strictly equal; -
defaultifisEqualColumnDefault ()returnedfalse; -
typeDimifisAdequateColumnTypeDim ()returnedfalse. So, a non-empty result means thatasIsrequires someALTERstatement(s) to be applied to comply with thetoBedefinition.
For a given bag of options, detects the class to be instantiated with getDbObjectClass, calls its constructor with the same options and injects itself with setLang. Returns the instance created.
Implements the duck typing, like: "if it has columns and an SQL query source, it's a view". For a given plain Object o, returns a DbObject class descendant to be instantiated with o. In the base version:
- if
ohas thecolumnsproperty, returns a DbRelation descendant: - if
ohas thebodyproperty, returns a DbRoutine descendant:- either DbFunction (if the
returnsproperty is present) - or DbProcedure
- either DbFunction (if the
- otherwise, throws an Error.
Returns the list of DbObject subclasses that DbMigrationPlan must discover with its loadStructure method. In the default implementation, returns [DbTable].
For a given object DbObject o, returns [quoteName (schemaName) + '.' +] quoteName (localName).
For a given object DbColumn col, returns ${col.type}[(${col.size}[,${col.scale}])].
For a given pair of DbObjects asIs and toBe, returns:
-
'alter'ifasIscan be transformed totoBewith someALTER...statements; -
'migrate'ifasIscan be transformed totoBeby creating a copy ofasIs/ transferring data / droppingasIs/ renaming the copy; -
nullif no action is needed for such transformation.
For a given string type representing some name of data type acceptable by the database product, must return a DbType instance representing the type with that name: such one of DbLang.TP_... static properties.
For given asIs and toBe DbTypes, returns a Boolean showing whether asIs is good to be used in place of toBe without any modification.
The base implementation only allows DbTypeArithmeticInt with more bytes, i. e. BIGINT in place of INT.
For given asIs and toBe DbColumns, returns a Boolean showing whether asIs is good to be used in place of toBe without any modification.
The base implementation requires:
-
types to be the same or compatible in sense ofisAdequateColumnType; -
sizeandscaleto be same or greater, where appropriate.
For given asIs and toBe strings, returns a Boolean showing whether they mean the same expression used in a column DEFAULT clause.
The base implementation just compares the strings for strict equity.
For a given String, returns a Boolean meaning whether the incoming string is a unary operator, like IS NULL or IS NOT NULL.
For a given DbRelation name, and the data object representing a single record, returns an array or parameters followed by an INSERT INTO ... (f1, f2, ... fn) VALUES (?, ?,... ?) SQL string.
The field list is constructed based on relation's columns mentioned in data. All data properties not in columns are ignored. Properties with undefined values are ignored (but nulls are kept).
If the field list is empty (no known column is mentioned), DEFAULT VALUES is used instead of (...) VALUES (...) clause.
For a given DbRelation name, and the data object representing a single record, returns an array or parameters followed by an UPDATE ... SET f1=?, f2=?,... fn=? WHERE k1=? AND k2=? AND... kn=? SQL string.
The WHERE clause is constructed based on the primary key (the relation's pk option). For each pk element, there must be defined a non-null data property; otherwise, an error is thrown.
The SET clause is constructed based on all relation's columns not in pk. All data properties not in columns are ignored. Properties with undefined values are ignored. For not nullable columns, explicit null values are mapped to the DEFAULT keyword instead of a ? placeholder.
If the SET clause is empty (so the data contains only the primary key and, maybe, some properties unknown to the model), the returned value is null, meaning there is nothing to UPDATE but this is not an error.
For a given DbQueryTableColumnComparison filter, returns a string to be appended to filter.sql right to the operator: like, '?' for simple binary operators, '? AND ?' for BETWEEN, (?,?...?) for IN etc.
More specifically:
- by the time of calling
genComparisonRightPart,filter.sqlis the fully qualified name of the field; - if
genComparisonRightPartreturns a string, is is appendedfilter.sqlalong with theop; - if it returns
null, nothing is appended tofilter.sql, butgenComparisonRightPartmay have mutated it as a side effect.
In the default implementation, for a non-standard ILIKE operator, genComparisonRightPart sets filter.sql to UPPER(${table}.${columns}) LIKE UPPER(?).
For a given DbTable table and an integer n, returns a string to be used as the nth table's trigger name.
For a given DbRelation relation and a DbIndex index, returns a string to be used as the index localName, unless set explicitly.
This generator is called internally by DbMigrationPlan to produce the actual SQL (DDL) sequence.
Quotes the given name according to ANSI SQL-99 standard: with double quotes, escaping " as "".
Quotes the given string according to ANSI SQL-99 standard: with single quotes, escaping ' as ''.
Returns an ANSI SQL-99 literal representing the given value based on its type:
-
NULLfornullandundefined; -
TRUEorFALSEfor aBoolean; - .toString () for a
NumberorBigInt; -
.quoteStringLiteral ()for aString.
Otherwise (i. e. for any non-null Object, including Dates and Arrays), an error is thrown.
For a given DbColumn, this generator yields the sequence of strings to be concatenated by ' ' as the genColumnDefinition result.
For a given DbColumn, returns the corresponding data type part of the definition. In the base implementation, returns typeDef.
For a given DbColumn, this generator yields the tail of genColumnDefinitionParts following the type and default value. In the base implementation, yields ' NOT NULL', if appropriate.
For a given DbColumn, returns the corresponding definition.
For a given DbTable and options object, returns the corresponding CREATE TEMPORARY TABLE ... statement. If options.onlyIfMissing is set, IF NOT EXISTS is added.
For a given DbView hosting a DbQueue, returns the SQL fetching complete records in queue.order.
Given a given String sql, an Array of params, and a {sql, params} object called filter, this method pushes all filter.params into params and returns sql + filter.sql.
For a given DbQuery, returns an Array of parameters with the SQL text appended to the end of it. Does the DbQuery.toParamsSql's job. Not to be invoked directly.
For a given DbView, replaces its sql property value with SELECT ${columns} FROM (${sql}) t. Called by the setLang when wrap option is set.
For a given DbCall, normalizes its sql property. In the base implementation, only normalizes the whitespace for logging purposes. Depending on the DB product, may also interpolate params (if the driver doesn't support proper binding), strip comments etc.
For the given DbQuery, returns a new DbQueryColumn instance bound to it and representing this column.
With the given DbLang lang, calculates all properties specific to this language/dialect.
In the base implementation:
- sets
qNametolang.quoteName (this.name); - if
typeis defined (which is not the case withreference):- sets
typeDeftolang.getTypeDefinition (this.type); - resets
typetotypeDef.name(so it gets normalized); - sets
typeDimtolang.getDbColumnTypeDim (this).
- sets
Here, a tiny DSL is implemented to build DbColumn objects from formatted strings.
column ::= ( physical | reference ) nullable? ("=" default)? range? re? extra? ("//" comment )?
physical ::= type dimension?
dimension ::= "(" size ("," scale)? ")"
nullable ::= "?" | "!"
range ::= "[" min? ".." max? "]"
re ::= "/" pattern "/"
extra ::= "{" ...properties "}"
The extra part may contain diverse DBMS vendor specific column options. Its format is loose JSON, or just js object literal.
Where:
- for
reference, see DbReference; -
sizeandscale, if present, must be positive integer decimal numbers not starting with0; - when the
rangeis specified,minormaxmay be omitted, but not both -
default,minandmaxliterals are not delimited, so they must not contain any special characters used by delimiters by the DSL itself (e. g.maxcan't contain'}', but no ordinal type allow such constants, so it's not really a restriction). Round braces (and so, function calls, compound expressions etc.) are allowed indefault. - the
nullableavailability and meaning depends ondefault:
nullable |
deault |
example | The column is... |
|---|---|---|---|
| int | NULLABLE | ||
| defined | int = 0 | NOT NULL | |
! |
int! | NOT NULL | |
? |
defined | int ?= 0 | NULLABLE |
? |
n/a | ||
! |
defined | n/a |
Examples
columns: {
// scalar fields
dt_birth : 'date! // date of birth', // `!` means NOT NULL
dt_death : 'date // date of death', // this one is NULLABLE
ts_created : 'timestamp = now() // when created', // NOT NULL implied by DEFAULT
score : 'int ?= 1000 // social credit', // explicitly NULLABLE with `?`
f_name : 'varchar (50) /^[A-Z][a-z\-]*$/ // family name', // RegExp example
salary : 'decimal (7,2) ?= 0 [0..] // salary', // may be NULL, but never negative
ultimate : 'int=99 [9..999] /^9/ {gz: 9, ttl: 'DAY'} // ...', // just an illustration
// references
id_status : '(tb_status) = 'W' // status', // `tb_status` has a CHAR(1) PK
id_parent : '(-tb_same_entity) // parent record', // ON DELETE CASCADE
id_task : '(~tb_volatile_tasks) // in progress', // ON DELETE SET NULL
}Parses the string argument into a DbColumn constructor argument.
For a given options object, cuts options.comment off options.src, if found.
For a given options object, cuts options.pattern off options.src, if found.
For a given options object, cuts options.min and options.max off options.src, if found.
For a given options object, cuts options.default off options.src, if found.
For a given options object, sets the nullable and type properties based on options.src.
For a given options object, parses options.type into options.type per se, options.size and options.scale.