2021-06-03 17:31:24 +02:00
const Sql = require ( "../base/sql" )
2022-07-21 11:28:54 +02:00
const { SqlClients } = require ( "../utils" )
2021-06-03 17:31:24 +02:00
const TABLE _NAME = "test"
function endpoint ( table , operation ) {
return {
datasourceId : "Postgres" ,
operation : operation ,
entityId : table || TABLE _NAME ,
}
}
function generateReadJson ( { table , fields , filters , sort , paginate } = { } ) {
return {
endpoint : endpoint ( table || TABLE _NAME , "READ" ) ,
resource : {
fields : fields || [ ] ,
} ,
filters : filters || { } ,
sort : sort || { } ,
paginate : paginate || { } ,
}
}
function generateCreateJson ( table = TABLE _NAME , body = { } ) {
return {
endpoint : endpoint ( table , "CREATE" ) ,
body ,
}
}
function generateUpdateJson ( table = TABLE _NAME , body = { } , filters = { } ) {
return {
endpoint : endpoint ( table , "UPDATE" ) ,
filters ,
body ,
}
}
function generateDeleteJson ( table = TABLE _NAME , filters = { } ) {
return {
endpoint : endpoint ( table , "DELETE" ) ,
filters ,
}
}
describe ( "SQL query builder" , ( ) => {
const limit = 500
2022-07-21 11:28:54 +02:00
const client = SqlClients . POSTGRES
2021-06-03 17:31:24 +02:00
let sql
beforeEach ( ( ) => {
sql = new Sql ( client , limit )
} )
it ( "should test a basic read" , ( ) => {
2021-06-03 18:45:19 +02:00
const query = sql . _query ( generateReadJson ( ) )
expect ( query ) . toEqual ( {
bindings : [ limit ] ,
2021-09-23 17:56:13 +02:00
sql : ` select * from (select * from " ${ TABLE _NAME } " limit $ 1) as " ${ TABLE _NAME } " `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:31:24 +02:00
} )
it ( "should test a read with specific columns" , ( ) => {
2021-08-06 13:33:04 +02:00
const nameProp = ` ${ TABLE _NAME } .name ` , ageProp = ` ${ TABLE _NAME } .age `
2021-06-03 18:45:19 +02:00
const query = sql . _query ( generateReadJson ( {
2021-08-06 13:33:04 +02:00
fields : [ nameProp , ageProp ]
2021-06-03 17:31:24 +02:00
} ) )
2021-06-03 18:45:19 +02:00
expect ( query ) . toEqual ( {
bindings : [ limit ] ,
2021-09-23 17:56:13 +02:00
sql : ` select " ${ TABLE _NAME } "."name" as " ${ nameProp } ", " ${ TABLE _NAME } "."age" as " ${ ageProp } " from (select * from " ${ TABLE _NAME } " limit $ 1) as " ${ TABLE _NAME } " `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:31:24 +02:00
} )
it ( "should test a where string starts with read" , ( ) => {
2021-06-03 18:45:19 +02:00
const query = sql . _query ( generateReadJson ( {
2021-06-03 17:31:24 +02:00
filters : {
string : {
name : "John" ,
}
}
} ) )
2021-06-03 18:45:19 +02:00
expect ( query ) . toEqual ( {
bindings : [ "John%" , limit ] ,
2021-09-23 17:56:13 +02:00
sql : ` select * from (select * from " ${ TABLE _NAME } " where " ${ TABLE _NAME } "."name" ilike $ 1 limit $ 2) as " ${ TABLE _NAME } " `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:31:24 +02:00
} )
it ( "should test a where range read" , ( ) => {
2021-06-03 18:45:19 +02:00
const query = sql . _query ( generateReadJson ( {
2021-06-03 17:31:24 +02:00
filters : {
range : {
age : {
low : 2 ,
high : 10 ,
}
}
}
} ) )
2021-06-03 18:45:19 +02:00
expect ( query ) . toEqual ( {
bindings : [ 2 , 10 , limit ] ,
2021-09-23 17:56:13 +02:00
sql : ` select * from (select * from " ${ TABLE _NAME } " where " ${ TABLE _NAME } "."age" between $ 1 and $ 2 limit $ 3) as " ${ TABLE _NAME } " `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:31:24 +02:00
} )
2021-06-15 14:03:55 +02:00
it ( "should test for multiple IDs with OR" , ( ) => {
const query = sql . _query ( generateReadJson ( {
filters : {
equal : {
age : 10 ,
name : "John" ,
} ,
allOr : true ,
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ 10 , "John" , limit ] ,
2021-09-23 17:56:13 +02:00
sql : ` select * from (select * from " ${ TABLE _NAME } " where (" ${ TABLE _NAME } "."age" = $ 1) or (" ${ TABLE _NAME } "."name" = $ 2) limit $ 3) as " ${ TABLE _NAME } " `
2021-06-15 14:03:55 +02:00
} )
} )
2022-01-17 19:20:37 +01:00
it ( "should allow filtering on a related field" , ( ) => {
const query = sql . _query ( generateReadJson ( {
filters : {
equal : {
age : 10 ,
"task.name" : "task 1" ,
} ,
} ,
} ) )
// order of bindings changes because relationship filters occur outside inner query
expect ( query ) . toEqual ( {
bindings : [ 10 , limit , "task 1" ] ,
sql : ` select * from (select * from " ${ TABLE _NAME } " where " ${ TABLE _NAME } "."age" = $ 1 limit $ 2) as " ${ TABLE _NAME } " where "task"."name" = $ 3 `
} )
} )
2021-06-03 17:31:24 +02:00
it ( "should test an create statement" , ( ) => {
2021-06-03 18:45:19 +02:00
const query = sql . _query ( generateCreateJson ( TABLE _NAME , {
2021-06-03 17:31:24 +02:00
name : "Michael" ,
age : 45 ,
} ) )
2021-06-03 18:45:19 +02:00
expect ( query ) . toEqual ( {
bindings : [ 45 , "Michael" ] ,
2021-06-17 15:42:30 +02:00
sql : ` insert into " ${ TABLE _NAME } " ("age", "name") values ( $ 1, $ 2) returning * `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:31:24 +02:00
} )
it ( "should test an update statement" , ( ) => {
2021-06-03 18:45:19 +02:00
const query = sql . _query ( generateUpdateJson ( TABLE _NAME , {
2021-06-03 17:31:24 +02:00
name : "John"
} , {
equal : {
id : 1001 ,
}
} ) )
2021-06-03 18:45:19 +02:00
expect ( query ) . toEqual ( {
bindings : [ "John" , 1001 ] ,
2021-07-02 15:49:47 +02:00
sql : ` update " ${ TABLE _NAME } " set "name" = $ 1 where " ${ TABLE _NAME } "."id" = $ 2 returning * `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:31:24 +02:00
} )
it ( "should test a delete statement" , ( ) => {
2021-06-03 18:45:19 +02:00
const query = sql . _query ( generateDeleteJson ( TABLE _NAME , {
2021-06-03 17:31:24 +02:00
equal : {
id : 1001 ,
}
} ) )
2021-06-03 18:45:19 +02:00
expect ( query ) . toEqual ( {
bindings : [ 1001 ] ,
2021-07-02 15:49:47 +02:00
sql : ` delete from " ${ TABLE _NAME } " where " ${ TABLE _NAME } "."id" = $ 1 returning * `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:31:24 +02:00
} )
2021-06-03 17:45:43 +02:00
it ( "should work with MS-SQL" , ( ) => {
2022-07-21 11:28:54 +02:00
const query = new Sql ( SqlClients . MS _SQL , 10 ) . _query ( generateReadJson ( ) )
2021-06-03 18:45:19 +02:00
expect ( query ) . toEqual ( {
bindings : [ 10 ] ,
2021-09-23 17:56:13 +02:00
sql : ` select * from (select top (@p0) * from [ ${ TABLE _NAME } ]) as [ ${ TABLE _NAME } ] `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:45:43 +02:00
} )
2022-07-21 11:28:54 +02:00
it ( "should work with MySQL" , ( ) => {
const query = new Sql ( SqlClients . MY _SQL , 10 ) . _query ( generateReadJson ( ) )
2021-06-03 18:45:19 +02:00
expect ( query ) . toEqual ( {
bindings : [ 10 ] ,
2021-09-23 17:56:13 +02:00
sql : ` select * from (select * from \` ${ TABLE _NAME } \` limit ?) as \` ${ TABLE _NAME } \` `
2021-06-03 18:45:19 +02:00
} )
2021-06-03 17:45:43 +02:00
} )
2022-03-15 12:52:54 +01:00
it ( "should use greater than when only low range specified" , ( ) => {
const date = new Date ( )
const query = sql . _query ( generateReadJson ( {
filters : {
range : {
property : {
low : date ,
}
}
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ date , limit ] ,
sql : ` select * from (select * from " ${ TABLE _NAME } " where " ${ TABLE _NAME } "."property" > $ 1 limit $ 2) as " ${ TABLE _NAME } " `
} )
} )
it ( "should use less than when only high range specified" , ( ) => {
const date = new Date ( )
const query = sql . _query ( generateReadJson ( {
filters : {
range : {
property : {
high : date ,
}
}
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ date , limit ] ,
sql : ` select * from (select * from " ${ TABLE _NAME } " where " ${ TABLE _NAME } "."property" < $ 1 limit $ 2) as " ${ TABLE _NAME } " `
} )
} )
it ( "should use greater than when only low range specified" , ( ) => {
const date = new Date ( )
const query = sql . _query ( generateReadJson ( {
filters : {
range : {
property : {
low : date ,
}
}
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ date , limit ] ,
sql : ` select * from (select * from " ${ TABLE _NAME } " where " ${ TABLE _NAME } "."property" > $ 1 limit $ 2) as " ${ TABLE _NAME } " `
} )
} )
2022-07-21 11:28:54 +02:00
it ( "should use like expression for MS-SQL when filter is contains" , ( ) => {
const query = new Sql ( SqlClients . MS _SQL , 10 ) . _query ( generateReadJson ( {
filters : {
contains : {
2022-07-26 17:58:01 +02:00
age : [ 20 ] ,
name : [ "John" ]
2022-07-21 11:28:54 +02:00
}
}
} ) )
expect ( query ) . toEqual ( {
2022-07-26 17:58:01 +02:00
bindings : [ 10 , "%20%" , ` %"John"% ` ] ,
2022-07-21 11:28:54 +02:00
sql : ` select * from (select top (@p0) * from [ ${ TABLE _NAME } ] where LOWER( ${ TABLE _NAME } .age) LIKE @p1 and LOWER( ${ TABLE _NAME } .name) LIKE @p2) as [ ${ TABLE _NAME } ] `
} )
} )
it ( "should use JSON_CONTAINS expression for MySQL when filter is contains" , ( ) => {
const query = new Sql ( SqlClients . MY _SQL , 10 ) . _query ( generateReadJson ( {
filters : {
contains : {
2022-07-26 17:58:01 +02:00
age : [ 20 ] ,
name : [ "John" ]
2022-07-21 11:28:54 +02:00
}
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ 10 ] ,
2022-07-26 17:58:01 +02:00
sql : ` select * from (select * from \` ${ TABLE _NAME } \` where JSON_CONTAINS( ${ TABLE _NAME } .age, '[20]') and JSON_CONTAINS( ${ TABLE _NAME } .name, '["John"]') limit ?) as \` ${ TABLE _NAME } \` `
2022-07-21 11:28:54 +02:00
} )
} )
it ( "should use jsonb operator expression for PostgreSQL when filter is contains" , ( ) => {
const query = new Sql ( SqlClients . POSTGRES , 10 ) . _query ( generateReadJson ( {
filters : {
contains : {
2022-07-26 17:58:01 +02:00
age : [ 20 ] ,
name : [ "John" ]
2022-07-21 11:28:54 +02:00
}
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ 10 ] ,
sql : ` select * from (select * from \" ${ TABLE _NAME } \" where \" ${ TABLE _NAME } \" . \" age \" ::jsonb @> '[20]' and \" ${ TABLE _NAME } \" . \" name \" ::jsonb @> '["John"]' limit $ 1) as \" ${ TABLE _NAME } \" `
} )
} )
2022-07-27 12:40:46 +02:00
2022-07-27 12:56:57 +02:00
it ( "should use NOT like expression for MS-SQL when filter is notContains" , ( ) => {
2022-07-27 12:40:46 +02:00
const query = new Sql ( SqlClients . MS _SQL , 10 ) . _query ( generateReadJson ( {
filters : {
notContains : {
age : [ 20 ] ,
name : [ "John" ]
}
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ 10 , "%20%" , ` %"John"% ` ] ,
2022-07-27 12:56:57 +02:00
sql : ` select * from (select top (@p0) * from [ ${ TABLE _NAME } ] where NOT (LOWER( ${ TABLE _NAME } .age) LIKE @p1) and NOT (LOWER( ${ TABLE _NAME } .name) LIKE @p2)) as [ ${ TABLE _NAME } ] `
2022-07-27 12:40:46 +02:00
} )
} )
it ( "should use NOT JSON_CONTAINS expression for MySQL when filter is notContains" , ( ) => {
const query = new Sql ( SqlClients . MY _SQL , 10 ) . _query ( generateReadJson ( {
filters : {
notContains : {
age : [ 20 ] ,
name : [ "John" ]
}
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ 10 ] ,
sql : ` select * from (select * from \` ${ TABLE _NAME } \` where NOT JSON_CONTAINS( ${ TABLE _NAME } .age, '[20]') and NOT JSON_CONTAINS( ${ TABLE _NAME } .name, '["John"]') limit ?) as \` ${ TABLE _NAME } \` `
} )
} )
2022-07-27 12:49:45 +02:00
it ( "should use jsonb operator NOT expression for PostgreSQL when filter is notContains" , ( ) => {
2022-07-27 12:40:46 +02:00
const query = new Sql ( SqlClients . POSTGRES , 10 ) . _query ( generateReadJson ( {
filters : {
notContains : {
age : [ 20 ] ,
name : [ "John" ]
}
}
} ) )
expect ( query ) . toEqual ( {
bindings : [ 10 ] ,
2022-07-27 12:49:45 +02:00
sql : ` select * from (select * from \" ${ TABLE _NAME } \" where NOT \" ${ TABLE _NAME } \" . \" age \" ::jsonb @> '[20]' and NOT \" ${ TABLE _NAME } \" . \" name \" ::jsonb @> '["John"]' limit $ 1) as \" ${ TABLE _NAME } \" `
2022-07-27 12:40:46 +02:00
} )
} )
2021-06-03 17:45:43 +02:00
} )