2016-03-02 17:07:05 +01:00
// SQLite3 Query Builder & Compiler
var inherits = require ( 'inherits' )
var QueryCompiler = require ( '../../../query/compiler' )
2016-05-11 21:01:56 +03:00
import { assign , isEmpty , isString , reduce , each } from 'lodash'
2016-03-02 17:07:05 +01:00
function QueryCompiler _SQLite3 ( client , builder ) {
QueryCompiler . call ( this , client , builder )
}
inherits ( QueryCompiler _SQLite3 , QueryCompiler )
assign ( QueryCompiler _SQLite3 . prototype , {
// The locks are not applicable in SQLite3
forShare : emptyStr ,
forUpdate : emptyStr ,
// SQLite requires us to build the multi-row insert as a listing of select with
// unions joining them together. So we'll build out this list of columns and
// then join them all together with select unions to complete the queries.
insert : function ( ) {
var insertValues = this . single . insert || [ ]
var sql = 'insert into ' + this . tableName + ' '
if ( Array . isArray ( insertValues ) ) {
if ( insertValues . length === 0 ) {
return ''
}
else if ( insertValues . length === 1 && insertValues [ 0 ] && isEmpty ( insertValues [ 0 ] ) ) {
return sql + this . _emptyInsertValue
}
} else if ( typeof insertValues === 'object' && isEmpty ( insertValues ) ) {
return sql + this . _emptyInsertValue
}
var insertData = this . _prepInsert ( insertValues )
if ( isString ( insertData ) ) {
return sql + insertData
}
if ( insertData . columns . length === 0 ) {
return '' ;
}
sql += '(' + this . formatter . columnize ( insertData . columns ) + ')'
2016-05-11 21:01:56 +03:00
// backwards compatible error
each ( insertData . values , bindings => {
each ( bindings , binding => {
if ( binding === undefined && this . client . valueForUndefined !== null ) {
throw new TypeError ( "`sqlite` does not support inserting default values. Specify values explicitly or use the `useNullAsDefault` config flag. (see docs http://knexjs.org/#Builder-insert)." ) ;
}
} ) ;
} ) ;
2016-03-02 17:07:05 +01:00
if ( insertData . values . length === 1 ) {
2016-05-11 21:01:56 +03:00
return sql + ' values (' + this . formatter . parameterize ( insertData . values [ 0 ] , this . client . valueForUndefined ) + ')'
2016-03-02 17:07:05 +01:00
}
var blocks = [ ]
var i = - 1
while ( ++ i < insertData . values . length ) {
var i2 = - 1 , block = blocks [ i ] = [ ]
var current = insertData . values [ i ]
2016-05-11 21:01:56 +03:00
current = current === undefined ? this . client . valueForUndefined : current
2016-03-02 17:07:05 +01:00
while ( ++ i2 < insertData . columns . length ) {
block . push ( this . formatter . alias (
this . formatter . parameter ( current [ i2 ] ) ,
this . formatter . wrap ( insertData . columns [ i2 ] )
) )
}
blocks [ i ] = block . join ( ', ' )
}
return sql + ' select ' + blocks . join ( ' union all select ' )
} ,
// Compile a truncate table statement into SQL.
truncate : function ( ) {
var table = this . tableName
return {
sql : 'delete from ' + table ,
output : function ( ) {
return this . query ( { sql : 'delete from sqlite_sequence where name = ' + table } ) . catch ( function ( ) { } )
}
}
} ,
// Compiles a `columnInfo` query
columnInfo : function ( ) {
var column = this . single . columnInfo
return {
sql : 'PRAGMA table_info(' + this . single . table + ')' ,
output : function ( resp ) {
var maxLengthRegex = /.*\((\d+)\)/
var out = reduce ( resp , function ( columns , val ) {
var type = val . type
var maxLength = ( maxLength = type . match ( maxLengthRegex ) ) && maxLength [ 1 ]
type = maxLength ? type . split ( '(' ) [ 0 ] : type
columns [ val . name ] = {
type : type . toLowerCase ( ) ,
maxLength : maxLength ,
nullable : ! val . notnull ,
defaultValue : val . dflt _value
}
return columns
} , { } )
return column && out [ column ] || out
}
}
} ,
limit : function ( ) {
var noLimit = ! this . single . limit && this . single . limit !== 0
if ( noLimit && ! this . single . offset ) return ''
// Workaround for offset only,
// see http://stackoverflow.com/questions/10491492/sqllite-with-skip-offset-only-not-limit
return 'limit ' + this . formatter . parameter ( noLimit ? - 1 : this . single . limit )
}
} )
function emptyStr ( ) {
return ''
}
module . exports = QueryCompiler _SQLite3