@@ -332,11 +332,11 @@ defmodule Ecto.Adapters.SQLite3.Connection do
332332 end
333333 end
334334
335- defp build_explain_query ( query , :query_plan ) do
335+ def build_explain_query ( query , :query_plan ) do
336336 IO . iodata_to_binary ( [ "EXPLAIN QUERY PLAN " , query ] )
337337 end
338338
339- defp build_explain_query ( query , :instructions ) do
339+ def build_explain_query ( query , :instructions ) do
340340 IO . iodata_to_binary ( [ "EXPLAIN " , query ] )
341341 end
342342
@@ -444,6 +444,141 @@ defmodule Ecto.Adapters.SQLite3.Connection do
444444 end )
445445 end
446446
447+ @ impl true
448+ def execute_ddl ( { _ , % Index { concurrently: true } } ) do
449+ raise ArgumentError , "`concurrently` is not supported with SQLite3"
450+ end
451+
452+ @ impl true
453+ def execute_ddl ( { _ , % Index { only: true } } ) do
454+ raise ArgumentError , "`only` is not supported with SQLite3"
455+ end
456+
457+ @ impl true
458+ def execute_ddl ( { _ , % Index { include: x } } ) when length ( x ) != 0 do
459+ raise ArgumentError , "`include` is not supported with SQLite3"
460+ end
461+
462+ @ impl true
463+ def execute_ddl ( { _ , % Index { using: x } } ) when not is_nil ( x ) do
464+ raise ArgumentError , "`using` is not supported with SQLite3"
465+ end
466+
467+ @ impl true
468+ def execute_ddl ( { _ , % Index { nulls_distinct: x } } ) when not is_nil ( x ) do
469+ raise ArgumentError , "`nulls_distinct` is not supported with SQLite3"
470+ end
471+
472+ @ impl true
473+ def execute_ddl ( { :create , % Index { } = index } ) do
474+ fields = intersperse_map ( index . columns , ", " , & index_expr / 1 )
475+
476+ [
477+ [
478+ "CREATE " ,
479+ if_do ( index . unique , "UNIQUE " ) ,
480+ "INDEX " ,
481+ quote_name ( index . name ) ,
482+ " ON " ,
483+ quote_table ( index . prefix , index . table ) ,
484+ " (" ,
485+ fields ,
486+ ?) ,
487+ if_do ( index . where , [ " WHERE " , to_string ( index . where ) ] )
488+ ]
489+ ]
490+ end
491+
492+ @ impl true
493+ def execute_ddl ( { :create_if_not_exists , % Index { } = index } ) do
494+ fields = intersperse_map ( index . columns , ", " , & index_expr / 1 )
495+
496+ [
497+ [
498+ "CREATE " ,
499+ if_do ( index . unique , "UNIQUE " ) ,
500+ "INDEX IF NOT EXISTS " ,
501+ quote_name ( index . name ) ,
502+ " ON " ,
503+ quote_table ( index . prefix , index . table ) ,
504+ " (" ,
505+ fields ,
506+ ?) ,
507+ if_do ( index . where , [ " WHERE " , to_string ( index . where ) ] )
508+ ]
509+ ]
510+ end
511+
512+ @ impl true
513+ def execute_ddl ( { :drop , % Index { } = index } ) do
514+ [
515+ [
516+ "DROP INDEX " ,
517+ quote_table ( index . prefix , index . name )
518+ ]
519+ ]
520+ end
521+
522+ @ impl true
523+ def execute_ddl ( { :drop , % Index { } = index , _mode } ) do
524+ execute_ddl ( { :drop , index } )
525+ end
526+
527+ @ impl true
528+ def execute_ddl ( { :drop_if_exists , % Index { concurrently: true } } ) do
529+ raise ArgumentError , "`concurrently` is not supported with SQLite3"
530+ end
531+
532+ @ impl true
533+ def execute_ddl ( { :drop_if_exists , % Index { } = index } ) do
534+ [
535+ [
536+ "DROP INDEX IF EXISTS " ,
537+ quote_table ( index . prefix , index . name )
538+ ]
539+ ]
540+ end
541+
542+ @ impl true
543+ def execute_ddl ( { :drop_if_exists , % Index { } = index , _mode } ) do
544+ execute_ddl ( { :drop_if_exists , index } )
545+ end
546+
547+ @ impl true
548+ def execute_ddl ( { :rename , % Table { } = current_table , % Table { } = new_table } ) do
549+ [
550+ [
551+ "ALTER TABLE " ,
552+ quote_table ( current_table . prefix , current_table . name ) ,
553+ " RENAME TO " ,
554+ quote_table ( nil , new_table . name )
555+ ]
556+ ]
557+ end
558+
559+ @ impl true
560+ def execute_ddl ( { :rename , % Table { } = current_table , old_col , new_col } ) do
561+ [
562+ [
563+ "ALTER TABLE " ,
564+ quote_table ( current_table . prefix , current_table . name ) ,
565+ " RENAME COLUMN " ,
566+ quote_name ( old_col ) ,
567+ " TO " ,
568+ quote_name ( new_col )
569+ ]
570+ ]
571+ end
572+
573+ @ impl true
574+ def execute_ddl ( string ) when is_binary ( string ) , do: [ string ]
575+
576+ @ impl true
577+ def execute_ddl ( keyword ) when is_list ( keyword ) do
578+ raise ArgumentError , "SQLite3 adapter does not support keyword lists in execute"
579+ end
580+
581+ @ impl true
447582 def execute_ddl ( { :create , % Index { } = index } ) do
448583 fields = intersperse_map ( index . columns , ", " , & index_expr / 1 )
449584
@@ -685,12 +820,11 @@ defmodule Ecto.Adapters.SQLite3.Connection do
685820
686821 def handle_call ( fun , _arity ) , do: { :fun , Atom . to_string ( fun ) }
687822
688- def distinct ( nil , _sources , _query ) , do: [ ]
689- def distinct ( % QueryExpr { expr: true } , _sources , _query ) , do: "DISTINCT "
690- def distinct ( % QueryExpr { expr: false } , _sources , _query ) , do: [ ]
823+ defp distinct ( nil , _sources , _query ) , do: [ ]
824+ defp distinct ( % QueryExpr { expr: true } , _sources , _query ) , do: "DISTINCT "
825+ defp distinct ( % QueryExpr { expr: false } , _sources , _query ) , do: [ ]
691826
692- def distinct ( % QueryExpr { expr: expression } , _sources , query )
693- when is_list ( expression ) do
827+ defp distinct ( % QueryExpr { expr: exprs } , _sources , query ) when is_list ( exprs ) do
694828 raise Ecto.QueryError ,
695829 query: query ,
696830 message: "DISTINCT with multiple columns is not supported by SQLite3"
@@ -809,6 +943,18 @@ defmodule Ecto.Adapters.SQLite3.Connection do
809943 ]
810944 end
811945
946+ defp update_op ( :push , _quoted_key , _value , _sources , query ) do
947+ raise Ecto.QueryError ,
948+ query: query ,
949+ message: "Arrays are not supported for SQLite3"
950+ end
951+
952+ defp update_op ( :pull , _quoted_key , _value , _sources , query ) do
953+ raise Ecto.QueryError ,
954+ query: query ,
955+ message: "Arrays are not supported for SQLite3"
956+ end
957+
812958 defp update_op ( command , _quoted_key , _value , _sources , query ) do
813959 raise Ecto.QueryError ,
814960 query: query ,
@@ -823,15 +969,6 @@ defmodule Ecto.Adapters.SQLite3.Connection do
823969 % JoinExpr { qual: _qual , ix: ix , source: source } ->
824970 { join , name } = get_source ( query , sources , ix , source )
825971 [ join , " AS " | name ]
826-
827- # This is hold over from sqlite_ecto2. According to sqlite3
828- # documentation, all of the join types are allowed.
829- #
830- # %JoinExpr{qual: qual} ->
831- # raise Ecto.QueryError,
832- # query: query,
833- # message:
834- # "SQLite3 adapter supports only inner joins on #{kind}, got: `#{qual}`"
835972 end )
836973
837974 wheres =
@@ -853,14 +990,19 @@ defmodule Ecto.Adapters.SQLite3.Connection do
853990 source: source ,
854991 hints: hints
855992 } ->
993+ if hints != [ ] do
994+ raise Ecto.QueryError ,
995+ query: query ,
996+ message: "join hints are not supported by SQLite3"
997+ end
998+
856999 { join , name } = get_source ( query , sources , ix , source )
8571000
8581001 [
8591002 join_qual ( qual , query ) ,
8601003 join ,
8611004 " AS " ,
8621005 name ,
863- Enum . map ( hints , & [ ?\s | & 1 ] ) ,
8641006 join_on ( qual , expression , sources , query )
8651007 ]
8661008 end )
@@ -932,11 +1074,11 @@ defmodule Ecto.Adapters.SQLite3.Connection do
9321074 def order_by ( % { order_bys: [ ] } , _sources ) , do: [ ]
9331075
9341076 def order_by ( % { order_bys: order_bys } = query , sources ) do
1077+ order_bys = Enum . flat_map ( order_bys , & & 1 . expr )
1078+
9351079 [
9361080 " ORDER BY "
937- | intersperse_map ( order_bys , ", " , fn % QueryExpr { expr: expression } ->
938- intersperse_map ( expression , ", " , & order_by_expr ( & 1 , sources , query ) )
939- end )
1081+ | intersperse_map ( order_bys , ", " , & order_by_expr ( & 1 , sources , query ) )
9401082 ]
9411083 end
9421084
@@ -1089,6 +1231,10 @@ defmodule Ecto.Adapters.SQLite3.Connection do
10891231 source
10901232 end
10911233
1234+ def expr ( { :in , _ , [ _left , "[]" ] } , _sources , _query ) do
1235+ "0"
1236+ end
1237+
10921238 def expr ( { :in , _ , [ _left , [ ] ] } , _sources , _query ) do
10931239 "0"
10941240 end
@@ -1111,6 +1257,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do
11111257 [ expr ( left , sources , query ) , " IN " , expr ( subquery , sources , query ) ]
11121258 end
11131259
1260+ # Super Hack to handle arrays in json
11141261 def expr ( { :in , _ , [ left , right ] } , sources , query ) do
11151262 [
11161263 expr ( left , sources , query ) ,
@@ -1227,8 +1374,13 @@ defmodule Ecto.Adapters.SQLite3.Connection do
12271374 def expr ( { fun , _ , args } , sources , query ) when is_atom ( fun ) and is_list ( args ) do
12281375 { modifier , args } =
12291376 case args do
1230- [ rest , :distinct ] -> { "DISTINCT " , [ rest ] }
1231- _ -> { [ ] , args }
1377+ [ _rest , :distinct ] ->
1378+ raise Ecto.QueryError ,
1379+ query: query ,
1380+ message: "Distinct not supported in expressions"
1381+
1382+ _ ->
1383+ { [ ] , args }
12321384 end
12331385
12341386 case handle_call ( fun , length ( args ) ) do
@@ -1245,7 +1397,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do
12451397 def expr ( list , _sources , query ) when is_list ( list ) do
12461398 raise Ecto.QueryError ,
12471399 query: query ,
1248- message: "Array type is not supported by SQLite3"
1400+ message: "Array literals are not supported by SQLite3"
12491401 end
12501402
12511403 def expr ( % Decimal { } = decimal , _sources , _query ) do
@@ -1260,7 +1412,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do
12601412
12611413 def expr ( % Ecto.Query.Tagged { value: other , type: type } , sources , query )
12621414 when type in [ :decimal , :float ] do
1263- [ "(" , expr ( other , sources , query ) , " + 0 )" ]
1415+ [ "CAST (" , expr ( other , sources , query ) , " AS REAL )" ]
12641416 end
12651417
12661418 def expr ( % Ecto.Query.Tagged { value: other , type: type } , sources , query ) do
@@ -1608,7 +1760,7 @@ defmodule Ecto.Adapters.SQLite3.Connection do
16081760 end )
16091761
16101762 if length ( pks ) > 1 do
1611- composite_pk_expr = pks |> Enum . reverse ( ) |> Enum . map_join ( ", " , & quote_name / 1 )
1763+ composite_pk_expr = pks |> Enum . reverse ( ) |> Enum . map_join ( "," , & quote_name / 1 )
16121764
16131765 {
16141766 % { table | primary_key: :composite } ,
0 commit comments