2019-07-30 21:29:24 +00:00
# frozen_string_literal: true
2019-01-09 23:57:35 +00:00
require './lib/qx.rb'
require 'pg'
require 'minitest/autorun'
require 'pry'
ActiveRecord :: Base . establish_connection ( 'postgres://admin:password@localhost/qx_test' )
tm = PG :: BasicTypeMapForResults . new ( ActiveRecord :: Base . connection . raw_connection )
Qx . config ( type_map : tm )
# Execute test schema
Qx . execute_file ( './test/test_schema.sql' )
class QxTest < Minitest :: Test
2019-07-30 21:29:24 +00:00
def setup ; end
2019-01-09 23:57:35 +00:00
# Let's just test that the schema was executed
def test_execute_file
email = 'uzzzr@example.com'
result = Qx . execute_file ( './test/test_insert_user.sql' , email : email , id : 1 ) . last
Qx . delete_from ( :users ) . where ( id : 1 ) . ex
assert_equal email , result [ 'email' ]
end
def test_select_from
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_distinct_on
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . distinct_on ( :distinct_col1 , :distinct_col2 ) . from ( :table_name ) . parse
assert_equal parsed , %( SELECT DISTINCT ON ( distinct_col1, distinct_col2 ) id, name FROM table_name )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_distinct
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . distinct . from ( :table_name ) . parse
assert_equal parsed , %( SELECT DISTINCT id, name FROM table_name )
2019-01-09 23:57:35 +00:00
end
def test_select_as
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . as ( :alias ) . parse
assert_equal parsed , %( ( SELECT id, name FROM table_name ) AS "alias" )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_where
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . where ( 'x = $y OR a = $b' , y : 1 , b : 2 ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name WHERE ( x = 1 OR a = 2 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_where_hash_array
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . where ( [ x : 1 ] , [ 'y = $n' , { n : 2 } ] ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name WHERE ( "x" IN ( 1 ) ) AND ( y = 2 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_and_where
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . where ( 'x = $y' , y : 1 ) . and_where ( 'a = $b' , b : 2 ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name WHERE ( x = 1 ) AND ( a = 2 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_and_where_hash
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . where ( 'x = $y' , y : 1 ) . and_where ( a : 2 ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name WHERE ( x = 1 ) AND ( "a" IN ( 2 ) ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_and_group_by
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . group_by ( 'col1' , 'col2' ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name GROUP BY col1, col2 )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_and_order_by
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . order_by ( 'col1' , [ 'col2' , 'DESC NULLS LAST' ] ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name ORDER BY col1 , col2 DESC NULLS LAST )
2019-01-09 23:57:35 +00:00
end
def test_select_having
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . having ( 'COUNT(col1) > $n' , n : 1 ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name HAVING ( COUNT ( col1 ) > 1 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_and_having
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . having ( 'COUNT(col1) > $n' , n : 1 ) . and_having ( 'SUM(col2) > $m' , m : 2 ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name HAVING ( COUNT ( col1 ) > 1 ) AND ( SUM ( col2 ) > 2 ) )
2019-01-09 23:57:35 +00:00
end
def test_select_limit
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . limit ( 10 ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name LIMIT 10 )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_offset
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . offset ( 10 ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name OFFSET 10 )
2019-01-09 23:57:35 +00:00
end
def test_select_join
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . join ( [ 'assoc1' , 'assoc1.table_name_id=table_name.id' ] ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name JOIN assoc1 ON assoc1.table_name_id=table_name.id )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_add_join
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . join ( 'assoc1' , 'assoc1.table_name_id=table_name.id' )
. add_join ( [ 'assoc2' , 'assoc2.table_name_id=table_name.id' ] ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name JOIN assoc1 ON assoc1.table_name_id=table_name.id JOIN assoc2 ON assoc2.table_name_id=table_name.id )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_left_join
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . left_join ( [ 'assoc1' , 'assoc1.table_name_id=table_name.id' ] ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name LEFT JOIN assoc1 ON assoc1.table_name_id=table_name.id )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_select_add_left_join
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . left_join ( 'assoc1' , 'assoc1.table_name_id=table_name.id' )
. add_left_join ( [ 'assoc2' , 'assoc2.table_name_id=table_name.id' ] ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name LEFT JOIN assoc1 ON assoc1.table_name_id=table_name.id LEFT JOIN assoc2 ON assoc2.table_name_id=table_name.id )
2019-01-09 23:57:35 +00:00
end
def test_select_where_subquery
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id , 'name' ) . from ( :table_name ) . where ( 'id IN ($ids)' , ids : Qx . select ( 'id' ) . from ( 'assoc' ) ) . parse
assert_equal parsed , %( SELECT id, name FROM table_name WHERE ( id IN ( SELECT id FROM assoc ) ) )
2019-01-09 23:57:35 +00:00
end
def test_select_join_subquery
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( :id ) . from ( :table ) . join ( [ Qx . select ( :id ) . from ( :assoc ) . as ( :assoc ) , 'assoc.table_id=table.id' ] ) . parse
assert_equal parsed , %( SELECT id FROM table JOIN ( SELECT id FROM assoc ) AS "assoc" ON assoc.table_id=table.id )
2019-01-09 23:57:35 +00:00
end
def test_select_from_subquery
parsed = Qx . select ( :id ) . from ( Qx . select ( :id ) . from ( :table ) . as ( :table ) ) . parse
2019-07-30 21:29:24 +00:00
assert_equal parsed , %( SELECT id FROM ( SELECT id FROM table ) AS "table" )
2019-01-09 23:57:35 +00:00
end
def test_select_integration
parsed = Qx . select ( :id )
2019-07-30 21:29:24 +00:00
. from ( :table )
. join ( [ Qx . select ( :id ) . from ( :assoc ) . as ( :assoc ) , 'assoc.table_id=table.id' ] )
. left_join ( [ 'lefty' , 'lefty.table_id=table.id' ] )
. where ( 'x = $n' , n : 1 )
. and_where ( 'y = $n' , n : 1 )
. group_by ( :x )
. order_by ( :y )
. having ( 'COUNT(x) > $n' , n : 1 )
. and_having ( 'COUNT(y) > $n' , n : 1 )
. limit ( 10 )
. offset ( 10 )
. parse
assert_equal parsed , %( SELECT id FROM table JOIN ( SELECT id FROM assoc ) AS "assoc" ON assoc.table_id=table.id LEFT JOIN lefty ON lefty.table_id=table.id WHERE ( x = 1 ) AND ( y = 1 ) GROUP BY x HAVING ( COUNT ( x ) > 1 ) AND ( COUNT ( y ) > 1 ) ORDER BY y LIMIT 10 OFFSET 10 )
2019-01-09 23:57:35 +00:00
end
def test_insert_into_values_hash
parsed = Qx . insert_into ( :table_name ) . values ( x : 1 ) . parse
2019-07-30 21:29:24 +00:00
assert_equal parsed , %( INSERT INTO "table_name" ( "x" ) VALUES ( 1 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_insert_into_values_hash_array
2019-07-30 21:29:24 +00:00
parsed = Qx . insert_into ( :table_name ) . values ( [ { x : 1 } , { x : 2 } ] ) . parse
assert_equal parsed , %( INSERT INTO "table_name" ( "x" ) VALUES ( 1 ) , ( 2 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_insert_into_values_csv_style
parsed = Qx . insert_into ( :table_name ) . values ( [ [ 'x' ] , [ 1 ] , [ 2 ] ] ) . parse
2019-07-30 21:29:24 +00:00
assert_equal parsed , %( INSERT INTO "table_name" ( "x" ) VALUES ( 1 ) , ( 2 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_insert_into_values_common_values
2019-07-30 21:29:24 +00:00
parsed = Qx . insert_into ( :table_name ) . values ( [ { x : 'bye' } , { x : 'hi' } ] ) . common_values ( z : 1 ) . parse
assert_equal parsed , %( INSERT INTO "table_name" ( "x", "z" ) VALUES ( $Q$bye$Q$, 1 ) , ( $Q$hi$Q$, 1 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_insert_into_values_timestamps
parsed = Qx . insert_into ( :table_name ) . values ( x : 1 ) . ts . parse
2019-07-30 21:29:24 +00:00
assert_equal parsed , %( INSERT INTO "table_name" ( "x", created_at, updated_at ) VALUES ( 1, ' #{ Time . now . utc } ', ' #{ Time . now . utc } ' ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_insert_into_values_returning
parsed = Qx . insert_into ( :table_name ) . values ( x : 1 ) . returning ( '*' ) . parse
2019-07-30 21:29:24 +00:00
assert_equal parsed , %( INSERT INTO "table_name" ( "x" ) VALUES ( 1 ) RETURNING * )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_insert_into_select
2019-07-30 21:29:24 +00:00
parsed = Qx . insert_into ( :table_name , [ 'hi' ] ) . select ( 'hi' ) . from ( :table2 ) . where ( 'x=y' ) . parse
assert_equal parsed , %( INSERT INTO "table_name" ( "hi" ) SELECT hi FROM table2 WHERE ( x=y ) )
2019-01-09 23:57:35 +00:00
end
def test_update_set
2019-07-30 21:29:24 +00:00
parsed = Qx . update ( :table_name ) . set ( x : 1 ) . where ( 'y = 2' ) . parse
assert_equal parsed , %( UPDATE "table_name" SET "x" = 1 WHERE ( y = 2 ) )
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_update_timestamps
now = Time . now . utc
2019-07-30 21:29:24 +00:00
parsed = Qx . update ( :table_name ) . set ( x : 1 ) . where ( 'y = 2' ) . timestamps . parse
assert_equal parsed , %( UPDATE "table_name" SET "x" = 1, updated_at = ' #{ now } ' WHERE ( y = 2 ) )
2019-01-09 23:57:35 +00:00
end
def test_update_on_conflict
2019-07-30 21:29:24 +00:00
Qx . update ( :table_name ) . set ( x : 1 ) . where ( 'y = 2' ) . on_conflict ( :nothing ) . parse
assert_equal parsed , %( UPDATE "table_name" SET "x" = 1 WHERE ( y = 2 ) ON CONFLICT DO NOTHING )
2019-01-09 23:57:35 +00:00
end
def test_insert_timestamps
now = Time . now . utc
2019-07-30 21:29:24 +00:00
parsed = Qx . insert_into ( :table_name ) . values ( x : 1 ) . ts . parse
assert_equal parsed , %( INSERT INTO "table_name" ( "x", created_at, updated_at ) VALUES ( 1, ' #{ now } ', ' #{ now } ' ) )
2019-01-09 23:57:35 +00:00
end
def test_delete_from
parsed = Qx . delete_from ( :table_name ) . where ( x : 1 ) . parse
2019-07-30 21:29:24 +00:00
assert_equal parsed , %( DELETE FROM "table_name" WHERE ( "x" IN ( 1 ) ) )
2019-01-09 23:57:35 +00:00
end
def test_pagination
parsed = Qx . select ( :x ) . from ( :y ) . paginate ( 4 , 30 ) . parse
2019-07-30 21:29:24 +00:00
assert_equal parsed , %( SELECT x FROM y LIMIT 30 OFFSET 90 )
2019-01-09 23:57:35 +00:00
end
def test_execute_string
2019-07-30 21:29:24 +00:00
result = Qx . execute ( 'SELECT * FROM (VALUES ($x)) AS t' , x : 'x' )
assert_equal result , [ { 'column1' = > 'x' } ]
2019-01-09 23:57:35 +00:00
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_execute_format_csv
2019-07-30 21:29:24 +00:00
result = Qx . execute ( 'SELECT * FROM (VALUES ($x)) AS t' , { x : 'x' } , format : 'csv' )
2019-01-09 23:57:35 +00:00
assert_equal result , [ [ 'column1' ] , [ 'x' ] ]
end
2019-07-30 21:29:24 +00:00
2019-01-09 23:57:35 +00:00
def test_execute_on_instances
result = Qx . insert_into ( :users ) . values ( id : 1 , email : 'uzr@example.com' ) . execute
2019-07-30 21:29:24 +00:00
result = Qx . execute ( Qx . select ( '*' ) . from ( :users ) . limit ( 1 ) )
assert_equal result , [ { 'id' = > 1 , 'email' = > 'uzr@example.com' } ]
2019-01-09 23:57:35 +00:00
Qx . delete_from ( :users ) . where ( id : 1 ) . execute
end
def test_explain
2019-07-30 21:29:24 +00:00
parsed = Qx . select ( '*' ) . from ( 'table_name' ) . explain . parse
assert_equal parsed , %( EXPLAIN SELECT * FROM table_name )
2019-01-09 23:57:35 +00:00
end
# Manually test this one for now
def test_pp_select
2019-07-30 21:29:24 +00:00
pp = Qx . select ( 'id, name' ) . from ( 'table_name' ) . where ( status : 'active' ) . and_where ( id : Qx . select ( 'id' ) . from ( 'roles' ) . where ( name : 'admin' ) ) . pp
2019-01-09 23:57:35 +00:00
pp2 = Qx . insert_into ( :table_name ) . values ( [ x : 1 , y : 2 ] ) . pp
pp3 = Qx . update ( :table_name ) . set ( x : 1 , y : 2 ) . where ( z : 1 , a : 22 ) . pp
pp_delete = Qx . delete_from ( :table_name ) . where ( id : 123 ) . pp
2019-07-30 21:29:24 +00:00
puts ''
puts '--- pretty print'
2019-01-09 23:57:35 +00:00
puts pp
puts pp2
puts pp3
puts pp_delete
2019-07-30 21:29:24 +00:00
puts '---'
2019-01-09 23:57:35 +00:00
end
def test_to_json
parsed = Qx . select ( :id ) . from ( :users ) . to_json ( :t ) . parse
2019-07-30 21:29:24 +00:00
assert_equal parsed , %( SELECT array_to_json ( array_agg ( row_to_json ( t ) ) ) FROM ( SELECT id FROM users ) AS "t" )
2019-01-09 23:57:35 +00:00
end
def test_to_json_nested
definitions = Qx . select ( :part_of_speech , :body )
2019-07-30 21:29:24 +00:00
. from ( :definitions )
. where ( 'word_id=words.id' )
. order_by ( 'position ASC' )
. to_json ( :ds )
. as ( 'definitions' )
2019-01-09 23:57:35 +00:00
parsed = Qx . select ( :text , :pronunciation , definitions )
2019-07-30 21:29:24 +00:00
. from ( :words )
. where ( " text='autumn' " )
. to_json ( :ws )
. parse
2019-01-09 23:57:35 +00:00
assert_equal parsed , " SELECT array_to_json(array_agg(row_to_json(ws))) FROM (SELECT text, pronunciation, (SELECT array_to_json(array_agg(row_to_json(ds))) FROM (SELECT part_of_speech, body FROM definitions WHERE (word_id=words.id) ORDER BY position ASC ) AS \" ds \" ) AS \" definitions \" FROM words WHERE (text='autumn')) AS \" ws \" "
end
def test_copy_csv_execution
2019-07-30 21:29:24 +00:00
data = { 'id' = > '1' , 'email' = > 'uzr@example.com' }
2019-01-09 23:57:35 +00:00
filename = '/tmp/qx-test.csv'
Qx . insert_into ( :users ) . values ( data ) . ex
2019-07-30 21:29:24 +00:00
copy = Qx . select ( '*' ) . from ( 'users' ) . execute ( copy_csv : filename )
2019-01-09 23:57:35 +00:00
contents = File . open ( filename , 'r' ) . read
2019-07-30 21:29:24 +00:00
csv_data = contents . split ( " \n " ) . map { | l | l . split ( ',' ) }
2019-01-09 23:57:35 +00:00
headers = csv_data . first
row = csv_data . last
assert_equal data . keys , headers
assert_equal data . values , row
end
def test_remove_clause
2019-07-30 21:29:24 +00:00
expr = Qx . select ( '*' ) . from ( 'table' ) . limit ( 1 )
2019-01-09 23:57:35 +00:00
expr = expr . remove_clause ( 'limit' )
2019-07-30 21:29:24 +00:00
assert_equal 'SELECT * FROM table' , expr . parse
2019-01-09 23:57:35 +00:00
end
end