@@ -156,6 +156,12 @@ class DSSqlAdapter {
156156 constructor ( options ) {
157157 this . defaults = { }
158158 options = options || { }
159+
160+ if ( options . queryOperators ) {
161+ this . queryOperators = options . queryOperators ;
162+ delete options . queryOperators ;
163+ }
164+
159165 if ( options . __knex__ ) {
160166 this . query = options
161167 } else {
@@ -347,107 +353,113 @@ class DSSqlAdapter {
347353 }
348354
349355 forOwn ( criteria , ( v , op ) => {
350- if ( op === '==' || op === '===' ) {
351- if ( v === null ) {
352- query = query . whereNull ( field )
353- } else {
354- query = query . where ( field , v )
355- }
356- } else if ( op === '!=' || op === '!==' ) {
357- if ( v === null ) {
358- query = query . whereNotNull ( field )
359- } else {
360- query = query . where ( field , '!=' , v )
361- }
362- } else if ( op === '>' ) {
363- query = query . where ( field , '>' , v )
364- } else if ( op === '>=' ) {
365- query = query . where ( field , '>=' , v )
366- } else if ( op === '<' ) {
367- query = query . where ( field , '<' , v )
368- } else if ( op === '<=' ) {
369- query = query . where ( field , '<=' , v )
370- // } else if (op === 'isectEmpty') {
371- // subQuery = subQuery ? subQuery.and(row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)
372- // } else if (op === 'isectNotEmpty') {
373- // subQuery = subQuery ? subQuery.and(row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)
374- } else if ( op === 'in' ) {
375- query = query . where ( field , 'in' , v )
376- } else if ( op === 'notIn' ) {
377- query = query . whereNotIn ( field , v )
378- } else if ( op === 'near' ) {
379- const milesRegex = / ( \d + ( \. \d + ) ? ) \s * ( m | M ) i l e s $ /
380- const kilometersRegex = / ( \d + ( \. \d + ) ? ) \s * ( k | K ) $ /
381-
382- let radius
383- let unitsPerDegree
384- if ( typeof v . radius === 'number' || milesRegex . test ( v . radius ) ) {
385- radius = typeof v . radius === 'number' ? v . radius : v . radius . match ( milesRegex ) [ 1 ]
386- unitsPerDegree = 69.0 // miles per degree
387- } else if ( kilometersRegex . test ( v . radius ) ) {
388- radius = v . radius . match ( kilometersRegex ) [ 1 ]
389- unitsPerDegree = 111.045 // kilometers per degree;
390- } else {
391- throw new Error ( 'Unknown radius distance units' )
392- }
356+ if ( op in ( this . queryOperators || { } ) ) {
357+ // Custom or overridden operator
358+ query = this . queryOperators [ op ] ( query , field , v )
359+ } else {
360+ // Builtin operators
361+ if ( op === '==' || op === '===' ) {
362+ if ( v === null ) {
363+ query = query . whereNull ( field )
364+ } else {
365+ query . where ( field , v )
366+ }
367+ } else if ( op === '!=' || op === '!==' ) {
368+ if ( v === null ) {
369+ query = query . whereNotNull ( field )
370+ } else {
371+ query = query . where ( field , '!=' , v )
372+ }
373+ } else if ( op === '>' ) {
374+ query = query . where ( field , '>' , v )
375+ } else if ( op === '>=' ) {
376+ query = query . where ( field , '>=' , v )
377+ } else if ( op === '<' ) {
378+ query = query . where ( field , '<' , v )
379+ } else if ( op === '<=' ) {
380+ query = query . where ( field , '<=' , v )
381+ // } else if (op === 'isectEmpty') {
382+ // subQuery = subQuery ? subQuery.and(row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)
383+ // } else if (op === 'isectNotEmpty') {
384+ // subQuery = subQuery ? subQuery.and(row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)
385+ } else if ( op === 'in' ) {
386+ query = query . where ( field , 'in' , v )
387+ } else if ( op === 'notIn' ) {
388+ query = query . whereNotIn ( field , v )
389+ } else if ( op === 'near' ) {
390+ const milesRegex = / ( \d + ( \. \d + ) ? ) \s * ( m | M ) i l e s $ /
391+ const kilometersRegex = / ( \d + ( \. \d + ) ? ) \s * ( k | K ) $ /
392+
393+ let radius
394+ let unitsPerDegree
395+ if ( typeof v . radius === 'number' || milesRegex . test ( v . radius ) ) {
396+ radius = typeof v . radius === 'number' ? v . radius : v . radius . match ( milesRegex ) [ 1 ]
397+ unitsPerDegree = 69.0 // miles per degree
398+ } else if ( kilometersRegex . test ( v . radius ) ) {
399+ radius = v . radius . match ( kilometersRegex ) [ 1 ]
400+ unitsPerDegree = 111.045 // kilometers per degree;
401+ } else {
402+ throw new Error ( 'Unknown radius distance units' )
403+ }
393404
394- let [ latitudeColumn , longitudeColumn ] = field . split ( ',' ) . map ( c => c . trim ( ) )
395- let [ latitude , longitude ] = v . center
396-
397- // Uses indexes on `latitudeColumn` / `longitudeColumn` if available
398- query = query
399- . whereBetween ( latitudeColumn , [
400- latitude - ( radius / unitsPerDegree ) ,
401- latitude + ( radius / unitsPerDegree )
402- ] )
403- . whereBetween ( longitudeColumn , [
404- longitude - ( radius / ( unitsPerDegree * Math . cos ( latitude * ( Math . PI / 180 ) ) ) ) ,
405- longitude + ( radius / ( unitsPerDegree * Math . cos ( latitude * ( Math . PI / 180 ) ) ) )
406- ] )
407-
408- if ( v . calculateDistance ) {
409- let distanceColumn = ( typeof v . calculateDistance === 'string' ) ? v . calculateDistance : 'distance'
410- query = query . select ( knex . raw ( `
411- ${ unitsPerDegree } * DEGREES(ACOS(
412- COS(RADIANS(?)) * COS(RADIANS(${ latitudeColumn } )) *
413- COS(RADIANS(${ longitudeColumn } ) - RADIANS(?)) +
414- SIN(RADIANS(?)) * SIN(RADIANS(${ latitudeColumn } ))
415- )) AS ${ distanceColumn } ` , [ latitude , longitude , latitude ] ) )
416- }
417- } else if ( op === 'like' ) {
418- query = query . where ( field , 'like' , v )
419- } else if ( op === '|like' ) {
420- query = query . orWhere ( field , 'like' , v )
421- } else if ( op === '|==' || op === '|===' ) {
422- if ( v === null ) {
423- query = query . orWhereNull ( field )
424- } else {
425- query = query . orWhere ( field , v )
426- }
427- } else if ( op === '|!=' || op === '|!==' ) {
428- if ( v === null ) {
429- query = query . orWhereNotNull ( field )
405+ let [ latitudeColumn , longitudeColumn ] = field . split ( ',' ) . map ( c => c . trim ( ) )
406+ let [ latitude , longitude ] = v . center
407+
408+ // Uses indexes on `latitudeColumn` / `longitudeColumn` if available
409+ query = query
410+ . whereBetween ( latitudeColumn , [
411+ latitude - ( radius / unitsPerDegree ) ,
412+ latitude + ( radius / unitsPerDegree )
413+ ] )
414+ . whereBetween ( longitudeColumn , [
415+ longitude - ( radius / ( unitsPerDegree * Math . cos ( latitude * ( Math . PI / 180 ) ) ) ) ,
416+ longitude + ( radius / ( unitsPerDegree * Math . cos ( latitude * ( Math . PI / 180 ) ) ) )
417+ ] )
418+
419+ if ( v . calculateDistance ) {
420+ let distanceColumn = ( typeof v . calculateDistance === 'string' ) ? v . calculateDistance : 'distance'
421+ query = query . select ( knex . raw ( `
422+ ${ unitsPerDegree } * DEGREES(ACOS(
423+ COS(RADIANS(?)) * COS(RADIANS(${ latitudeColumn } )) *
424+ COS(RADIANS(${ longitudeColumn } ) - RADIANS(?)) +
425+ SIN(RADIANS(?)) * SIN(RADIANS(${ latitudeColumn } ))
426+ )) AS ${ distanceColumn } ` , [ latitude , longitude , latitude ] ) )
427+ }
428+ } else if ( op === 'like' ) {
429+ query = query . where ( field , 'like' , v )
430+ } else if ( op === '|like' ) {
431+ query = query . orWhere ( field , 'like' , v )
432+ } else if ( op === '|==' || op === '|===' ) {
433+ if ( v === null ) {
434+ query = query . orWhereNull ( field )
435+ } else {
436+ query = query . orWhere ( field , v )
437+ }
438+ } else if ( op === '|!=' || op === '|!==' ) {
439+ if ( v === null ) {
440+ query = query . orWhereNotNull ( field )
441+ } else {
442+ query = query . orWhere ( field , '!=' , v )
443+ }
444+ } else if ( op === '|>' ) {
445+ query = query . orWhere ( field , '>' , v )
446+ } else if ( op === '|>=' ) {
447+ query = query . orWhere ( field , '>=' , v )
448+ } else if ( op === '|<' ) {
449+ query = query . orWhere ( field , '<' , v )
450+ } else if ( op === '|<=' ) {
451+ query = query . orWhere ( field , '<=' , v )
452+ // } else if (op === '|isectEmpty') {
453+ // subQuery = subQuery ? subQuery.or(row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)
454+ // } else if (op === '|isectNotEmpty') {
455+ // subQuery = subQuery ? subQuery.or(row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)
456+ } else if ( op === '|in' ) {
457+ query = query . orWhere ( field , 'in' , v )
458+ } else if ( op === '|notIn' ) {
459+ query = query . orWhereNotIn ( field , v )
430460 } else {
431- query = query . orWhere ( field , '!=' , v )
461+ throw new Error ( 'Operator not found' )
432462 }
433- } else if ( op === '|>' ) {
434- query = query . orWhere ( field , '>' , v )
435- } else if ( op === '|>=' ) {
436- query = query . orWhere ( field , '>=' , v )
437- } else if ( op === '|<' ) {
438- query = query . orWhere ( field , '<' , v )
439- } else if ( op === '|<=' ) {
440- query = query . orWhere ( field , '<=' , v )
441- // } else if (op === '|isectEmpty') {
442- // subQuery = subQuery ? subQuery.or(row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().eq(0)
443- // } else if (op === '|isectNotEmpty') {
444- // subQuery = subQuery ? subQuery.or(row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)) : row(field).default([]).setIntersection(r.expr(v).default([])).count().ne(0)
445- } else if ( op === '|in' ) {
446- query = query . orWhere ( field , 'in' , v )
447- } else if ( op === '|notIn' ) {
448- query = query . orWhereNotIn ( field , v )
449- } else {
450- throw new Error ( 'Operator not found' )
451463 }
452464 } )
453465 } )
0 commit comments