An Ecto SQLite3 adapter.
0

Configure Feed

Select the types of activity you want to include in your feed.

Fix various issues with ecto 3.12 (#147)

* Make expr function private
* Support column type integer
* Bump locked dependencies
* Fix issue ByExpr
closes: #146
* Swap in `Enum.map_intersperse/3`
* Tag constraint test to keep with upstream
* SQLite doesn't suffer from this issue anymore
* Simplify default_expr to no longer consider type
* Fix integration test setup

authored by

Matthew Johnston and committed by
GitHub
(Aug 13, 2024, 10:15 PM -0500) 0ddc2bd4 802fbf65

+223 -214
+1
integration_test/constraints_test.exs
··· 39 39 :ok 40 40 end 41 41 42 + @tag :create_constraint 42 43 test "check constraint" do 43 44 changeset = Ecto.Changeset.change(%Constraint{}, fromm: 0, too: 10) 44 45 {:ok, _} = PoolRepo.insert(changeset)
+80 -61
integration_test/test_helper.exs
··· 57 57 {:ok, _} = TestRepo.start_link() 58 58 {:ok, _pid} = PoolRepo.start_link() 59 59 60 + excludes = [ 61 + :delete_with_join, 62 + :right_join, 63 + 64 + # SQLite does not have an array type 65 + :array_type, 66 + :transaction_isolation, 67 + :insert_cell_wise_defaults, 68 + :insert_select, 69 + 70 + # sqlite does not support microsecond precision, only millisecond 71 + :microsecond_precision, 72 + 73 + # sqlite supports FKs, but does not return sufficient data 74 + # for ecto to support matching on a given constraint violation name 75 + # which is what most of the tests validate 76 + :foreign_key_constraint, 77 + 78 + # SQLite with DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 79 + # does not support using LIKE on BLOB types 80 + :like_match_blob, 81 + 82 + # SQLite will return a string for schemaless map types as 83 + # Ecto does not have enough information to call the associated loader 84 + # that converts the string JSON representaiton into a map 85 + :map_type_schemaless, 86 + 87 + # right now in lock_for_migrations() we do effectively nothing, this is because 88 + # SQLite is single-writer so there isn't really a need for us to do anything. 89 + # ecto assumes all implementing adapters need >=2 connections for migrations 90 + # which is not true for SQLite 91 + :lock_for_migrations, 92 + 93 + # Migration we don't support 94 + :prefix, 95 + :add_column_if_not_exists, 96 + :remove_column_if_exists, 97 + :alter_primary_key, 98 + :alter_foreign_key, 99 + :assigns_id_type, 100 + :modify_column, 101 + :restrict, 102 + 103 + # SQLite3 does not support the concat function 104 + :concat, 105 + 106 + # SQLite3 does not support placeholders 107 + :placeholders, 108 + 109 + # SQLite3 stores booleans as integers, causing Ecto's json_extract_path tests to fail 110 + :json_extract_path, 111 + 112 + # SQLite3 doesn't support specifying columns for ON DELETE SET NULL 113 + :on_delete_nilify_column_list, 114 + 115 + # not sure how to support this yet 116 + :bitstring_type, 117 + 118 + # sqlite does not have a duration type... yet 119 + :duration_type, 120 + 121 + # We don't support selected_as 122 + :selected_as_with_group_by, 123 + :selected_as_with_order_by, 124 + :selected_as_with_order_by_expression, 125 + :selected_as_with_having, 126 + 127 + # Distinct with options not supported 128 + :distinct_count, 129 + 130 + # SQLite does not support anything except a single column in DISTINCT 131 + :multicolumn_distinct, 132 + 133 + # Values list 134 + :values_list 135 + ] 136 + 137 + ExUnit.configure(exclude: excludes) 138 + 60 139 # migrate the pool repo 61 140 case Ecto.Migrator.migrated_versions(PoolRepo) do 62 141 [] -> ··· 71 150 Ecto.Adapters.SQL.Sandbox.mode(TestRepo, :manual) 72 151 Process.flag(:trap_exit, true) 73 152 74 - ExUnit.start( 75 - exclude: [ 76 - :delete_with_join, 77 - :right_join, 78 - # SQLite does not have an array type 79 - :array_type, 80 - :transaction_isolation, 81 - :insert_cell_wise_defaults, 82 - :insert_select, 83 - # sqlite does not support microsecond precision, only millisecond 84 - :microsecond_precision, 85 - # sqlite supports FKs, but does not return sufficient data 86 - # for ecto to support matching on a given constraint violation name 87 - # which is what most of the tests validate 88 - :foreign_key_constraint, 89 - # SQLite with DSQLITE_LIKE_DOESNT_MATCH_BLOBS=1 90 - # does not support using LIKE on BLOB types 91 - :like_match_blob, 92 - # SQLite will return a string for schemaless map types as 93 - # Ecto does not have enough information to call the associated loader 94 - # that converts the string JSON representaiton into a map 95 - :map_type_schemaless, 96 - 97 - # right now in lock_for_migrations() we do effectively nothing, this is because 98 - # SQLite is single-writer so there isn't really a need for us to do anything. 99 - # ecto assumes all implementing adapters need >=2 connections for migrations 100 - # which is not true for SQLite 101 - :lock_for_migrations, 102 - 103 - # Migration we don't support 104 - :prefix, 105 - :add_column_if_not_exists, 106 - :remove_column_if_exists, 107 - :alter_primary_key, 108 - :alter_foreign_key, 109 - :assigns_id_type, 110 - :modify_column, 111 - :restrict, 112 - 113 - # SQLite3 does not support the concat function 114 - :concat, 115 - # SQLite3 does not support placeholders 116 - :placeholders, 117 - # SQLite3 stores booleans as integers, causing Ecto's json_extract_path tests to fail 118 - :json_extract_path, 119 - # SQLite3 doesn't support specifying columns for ON DELETE SET NULL 120 - :on_delete_nilify_column_list, 121 - 122 - # We don't support selected_as 123 - :selected_as_with_group_by, 124 - :selected_as_with_order_by, 125 - :selected_as_with_order_by_expression, 126 - :selected_as_with_having, 127 - 128 - # Distinct with options not supported 129 - :distinct_count, 130 - 131 - # Values list 132 - :values_list 133 - ] 134 - ) 153 + ExUnit.start()
+124 -137
lib/ecto/adapters/sqlite3/connection.ex
··· 9 9 alias Ecto.Migration.Reference 10 10 alias Ecto.Migration.Table 11 11 alias Ecto.Query.BooleanExpr 12 + alias Ecto.Query.ByExpr 12 13 alias Ecto.Query.JoinExpr 13 14 alias Ecto.Query.QueryExpr 14 15 alias Ecto.Query.WithExpr ··· 284 285 285 286 @impl true 286 287 def update(prefix, table, fields, filters, returning) do 287 - fields = intersperse_map(fields, ", ", &[quote_name(&1), " = ?"]) 288 + fields = Enum.map_intersperse(fields, ", ", &[quote_name(&1), " = ?"]) 288 289 289 290 filters = 290 - intersperse_map(filters, " AND ", fn 291 + Enum.map_intersperse(filters, " AND ", fn 291 292 {field, nil} -> 292 293 [quote_name(field), " IS NULL"] 293 294 ··· 309 310 @impl true 310 311 def delete(prefix, table, filters, returning) do 311 312 filters = 312 - intersperse_map(filters, " AND ", fn 313 + Enum.map_intersperse(filters, " AND ", fn 313 314 {field, nil} -> 314 315 [quote_name(field), " IS NULL"] 315 316 ··· 481 482 482 483 @impl true 483 484 def execute_ddl({:create, %Index{} = index}) do 484 - fields = intersperse_map(index.columns, ", ", &index_expr/1) 485 + fields = Enum.map_intersperse(index.columns, ", ", &index_expr/1) 485 486 486 487 [ 487 488 [ ··· 501 502 502 503 @impl true 503 504 def execute_ddl({:create_if_not_exists, %Index{} = index}) do 504 - fields = intersperse_map(index.columns, ", ", &index_expr/1) 505 + fields = Enum.map_intersperse(index.columns, ", ", &index_expr/1) 505 506 506 507 [ 507 508 [ ··· 590 591 591 592 @impl true 592 593 def execute_ddl({:create, %Index{} = index}) do 593 - fields = intersperse_map(index.columns, ", ", &index_expr/1) 594 + fields = Enum.map_intersperse(index.columns, ", ", &index_expr/1) 594 595 595 596 [ 596 597 [ ··· 610 611 end 611 612 612 613 def execute_ddl({:create_if_not_exists, %Index{} = index}) do 613 - fields = intersperse_map(index.columns, ", ", &index_expr/1) 614 + fields = Enum.map_intersperse(index.columns, ", ", &index_expr/1) 614 615 615 616 [ 616 617 [ ··· 752 753 do: [fragment, ?\s] 753 754 754 755 defp conflict_target(targets) do 755 - [?(, intersperse_map(targets, ?,, &quote_name/1), ?), ?\s] 756 + [?(, Enum.map_intersperse(targets, ?,, &quote_name/1), ?), ?\s] 756 757 end 757 758 758 759 defp replace(fields) do 759 760 [ 760 761 "UPDATE SET " 761 - | intersperse_map(fields, ?,, fn field -> 762 + | Enum.map_intersperse(fields, ?,, fn field -> 762 763 quoted = quote_name(field) 763 764 [quoted, " = ", "EXCLUDED." | quoted] 764 765 end) ··· 766 767 end 767 768 768 769 def insert_all(rows, on_conflict), do: insert_all(rows, on_conflict, 1) 769 - 770 - def insert_all(%Ecto.Query{wheres: []} = _query, on_conflict, _counter) 771 - when not is_nil(on_conflict) do 772 - raise ArgumentError, 773 - "SQLite3 requires a where clause to avoid ambiguity. Even simply specify where: true will work" 774 - end 775 770 776 771 def insert_all(%Ecto.Query{} = query, _on_conflict, _counter) do 777 772 [all(query)] ··· 844 839 def handle_call(fun, _arity), do: {:fun, Atom.to_string(fun)} 845 840 846 841 defp distinct(nil, _sources, _query), do: [] 847 - defp distinct(%QueryExpr{expr: true}, _sources, _query), do: "DISTINCT " 848 - defp distinct(%QueryExpr{expr: false}, _sources, _query), do: [] 842 + defp distinct(%ByExpr{expr: true}, _sources, _query), do: "DISTINCT " 843 + defp distinct(%ByExpr{expr: false}, _sources, _query), do: [] 849 844 850 - defp distinct(%QueryExpr{expr: exprs}, _sources, query) when is_list(exprs) do 845 + defp distinct(%ByExpr{expr: exprs}, _sources, query) when is_list(exprs) do 851 846 raise Ecto.QueryError, 852 847 query: query, 853 848 message: "DISTINCT with multiple columns is not supported by SQLite3" 854 849 end 855 850 856 - def select(%{select: %{fields: fields}, distinct: distinct} = query, sources) do 851 + defp select(%{select: %{fields: fields}, distinct: distinct} = query, sources) do 857 852 [ 858 853 "SELECT ", 859 854 distinct(distinct, sources, query) | select_fields(fields, sources, query) ··· 863 858 defp select_fields([], _sources, _query), do: "1" 864 859 865 860 defp select_fields(fields, sources, query) do 866 - intersperse_map(fields, ", ", fn 861 + Enum.map_intersperse(fields, ", ", fn 867 862 {:&, _, [idx]} -> 868 863 case elem(sources, idx) do 869 864 {source, _, nil} -> ··· 905 900 sources 906 901 ) do 907 902 recursive_opt = if recursive, do: "RECURSIVE ", else: "" 908 - ctes = intersperse_map(queries, ", ", &cte_expr(&1, sources, query)) 903 + ctes = Enum.map_intersperse(queries, ", ", &cte_expr(&1, sources, query)) 909 904 910 905 [ 911 906 "WITH ", ··· 992 987 993 988 defp using_join(%{joins: joins} = query, _kind, prefix, sources) do 994 989 froms = 995 - intersperse_map(joins, ", ", fn 990 + Enum.map_intersperse(joins, ", ", fn 996 991 %JoinExpr{qual: _qual, ix: ix, source: source} -> 997 992 {join, name} = get_source(query, sources, ix, source) 998 993 [join, " AS " | name] ··· 1065 1060 def group_by(%{group_bys: group_bys} = query, sources) do 1066 1061 [ 1067 1062 " GROUP BY " 1068 - | intersperse_map(group_bys, ", ", fn %QueryExpr{expr: expression} -> 1069 - intersperse_map(expression, ", ", &expr(&1, sources, query)) 1063 + | Enum.map_intersperse(group_bys, ", ", fn %ByExpr{expr: expression} -> 1064 + Enum.map_intersperse(expression, ", ", &top_level_expr(&1, sources, query)) 1070 1065 end) 1071 1066 ] 1072 1067 end ··· 1076 1071 def window(%{windows: windows} = query, sources) do 1077 1072 [ 1078 1073 " WINDOW " 1079 - | intersperse_map(windows, ", ", fn {name, %{expr: kw}} -> 1074 + | Enum.map_intersperse(windows, ", ", fn {name, %{expr: kw}} -> 1080 1075 [quote_name(name), " AS " | window_exprs(kw, sources, query)] 1081 1076 end) 1082 1077 ] 1083 1078 end 1084 1079 1085 1080 defp window_exprs(kw, sources, query) do 1086 - [?(, intersperse_map(kw, ?\s, &window_expr(&1, sources, query)), ?)] 1081 + [?(, Enum.map_intersperse(kw, ?\s, &window_expr(&1, sources, query)), ?)] 1087 1082 end 1088 1083 1089 1084 defp window_expr({:partition_by, fields}, sources, query) do 1090 - ["PARTITION BY " | intersperse_map(fields, ", ", &expr(&1, sources, query))] 1085 + ["PARTITION BY " | Enum.map_intersperse(fields, ", ", &expr(&1, sources, query))] 1091 1086 end 1092 1087 1093 1088 defp window_expr({:order_by, fields}, sources, query) do 1094 - ["ORDER BY " | intersperse_map(fields, ", ", &order_by_expr(&1, sources, query))] 1089 + [ 1090 + "ORDER BY " 1091 + | Enum.map_intersperse(fields, ", ", &order_by_expr(&1, sources, query)) 1092 + ] 1095 1093 end 1096 1094 1097 1095 defp window_expr({:frame, {:fragment, _, _} = fragment}, sources, query) do ··· 1105 1103 1106 1104 [ 1107 1105 " ORDER BY " 1108 - | intersperse_map(order_bys, ", ", &order_by_expr(&1, sources, query)) 1106 + | Enum.map_intersperse(order_bys, ", ", &order_by_expr(&1, sources, query)) 1109 1107 ] 1110 1108 end 1111 1109 1112 1110 defp order_by_expr({dir, expression}, sources, query) do 1113 - str = expr(expression, sources, query) 1111 + str = top_level_expr(expression, sources, query) 1114 1112 1115 1113 case dir do 1116 1114 :asc -> ··· 1219 1217 [?(, expr(expression, sources, query), ?)] 1220 1218 end 1221 1219 1220 + defp top_level_expr(%Ecto.SubQuery{query: query}, sources, parent_query) do 1221 + combinations = 1222 + Enum.map(query.combinations, fn {type, combination_query} -> 1223 + {type, put_in(combination_query.aliases[@parent_as], {parent_query, sources})} 1224 + end) 1225 + 1226 + query = put_in(query.combinations, combinations) 1227 + query = put_in(query.aliases[@parent_as], {parent_query, sources}) 1228 + [all(query, subquery_as_prefix(sources))] 1229 + end 1230 + 1231 + defp top_level_expr(other, sources, parent_query) do 1232 + expr(other, sources, parent_query) 1233 + end 1234 + 1222 1235 ## 1223 1236 ## Expression generation 1224 1237 ## 1225 1238 1226 - def expr({:^, [], [_ix]}, _sources, _query) do 1239 + defp expr({:^, [], [_ix]}, _sources, _query) do 1227 1240 ~c"?" 1228 1241 end 1229 1242 1230 1243 # workaround for the fact that SQLite3 as of 3.35.4 does not support specifying table 1231 1244 # in the returning clause. when a later release adds the ability, this code can be deleted 1232 - def expr( 1233 - {{:., _, [{:parent_as, _, [{:&, _, [_idx]}]}, field]}, _, []}, 1234 - _sources, 1235 - %{returning: true} 1236 - ) 1237 - when is_atom(field) do 1245 + defp expr( 1246 + {{:., _, [{:parent_as, _, [{:&, _, [_idx]}]}, field]}, _, []}, 1247 + _sources, 1248 + %{returning: true} 1249 + ) 1250 + when is_atom(field) do 1238 1251 quote_name(field) 1239 1252 end 1240 1253 1241 1254 # workaround for the fact that SQLite3 as of 3.35.4 does not support specifying table 1242 1255 # in the returning clause. when a later release adds the ability, this code can be deleted 1243 - def expr({{:., _, [{:&, _, [_idx]}, field]}, _, []}, _sources, %{returning: true}) 1244 - when is_atom(field) do 1256 + defp expr({{:., _, [{:&, _, [_idx]}, field]}, _, []}, _sources, %{returning: true}) 1257 + when is_atom(field) do 1245 1258 quote_name(field) 1246 1259 end 1247 1260 1248 - def expr({{:., _, [{:parent_as, _, [as]}, field]}, _, []}, _sources, query) 1249 - when is_atom(field) do 1261 + defp expr({{:., _, [{:parent_as, _, [as]}, field]}, _, []}, _sources, query) 1262 + when is_atom(field) do 1250 1263 {ix, sources} = get_parent_sources_ix(query, as) 1251 1264 {_, name, _} = elem(sources, ix) 1252 1265 [name, ?. | quote_name(field)] 1253 1266 end 1254 1267 1255 - def expr({{:., _, [{:&, _, [idx]}, field]}, _, []}, sources, _query) 1256 - when is_atom(field) do 1268 + defp expr({{:., _, [{:&, _, [idx]}, field]}, _, []}, sources, _query) 1269 + when is_atom(field) do 1257 1270 {_, name, _} = elem(sources, idx) 1258 1271 [name, ?. | quote_name(field)] 1259 1272 end 1260 1273 1261 - def expr({:&, _, [idx]}, sources, _query) do 1274 + defp expr({:&, _, [idx]}, sources, _query) do 1262 1275 {_, source, _} = elem(sources, idx) 1263 1276 source 1264 1277 end 1265 1278 1266 - def expr({:in, _, [_left, "[]"]}, _sources, _query) do 1279 + defp expr({:in, _, [_left, "[]"]}, _sources, _query) do 1267 1280 "0" 1268 1281 end 1269 1282 1270 - def expr({:in, _, [_left, []]}, _sources, _query) do 1283 + defp expr({:in, _, [_left, []]}, _sources, _query) do 1271 1284 "0" 1272 1285 end 1273 1286 1274 - def expr({:in, _, [left, right]}, sources, query) when is_list(right) do 1275 - args = intersperse_map(right, ?,, &expr(&1, sources, query)) 1287 + defp expr({:in, _, [left, right]}, sources, query) when is_list(right) do 1288 + args = Enum.map_intersperse(right, ?,, &expr(&1, sources, query)) 1276 1289 [expr(left, sources, query), " IN (", args, ?)] 1277 1290 end 1278 1291 1279 - def expr({:in, _, [_, {:^, _, [_, 0]}]}, _sources, _query) do 1292 + defp expr({:in, _, [_, {:^, _, [_, 0]}]}, _sources, _query) do 1280 1293 "0" 1281 1294 end 1282 1295 1283 - def expr({:in, _, [left, {:^, _, [_, len]}]}, sources, query) do 1296 + defp expr({:in, _, [left, {:^, _, [_, len]}]}, sources, query) do 1284 1297 args = Enum.intersperse(List.duplicate(??, len), ?,) 1285 1298 [expr(left, sources, query), " IN (", args, ?)] 1286 1299 end 1287 1300 1288 - def expr({:in, _, [left, %Ecto.SubQuery{} = subquery]}, sources, query) do 1301 + defp expr({:in, _, [left, %Ecto.SubQuery{} = subquery]}, sources, query) do 1289 1302 [expr(left, sources, query), " IN ", expr(subquery, sources, query)] 1290 1303 end 1291 1304 1292 1305 # Super Hack to handle arrays in json 1293 - def expr({:in, _, [left, right]}, sources, query) do 1306 + defp expr({:in, _, [left, right]}, sources, query) do 1294 1307 [ 1295 1308 expr(left, sources, query), 1296 1309 " IN (SELECT value FROM JSON_EACH(", ··· 1300 1313 ] 1301 1314 end 1302 1315 1303 - def expr({:is_nil, _, [arg]}, sources, query) do 1316 + defp expr({:is_nil, _, [arg]}, sources, query) do 1304 1317 [expr(arg, sources, query) | " IS NULL"] 1305 1318 end 1306 1319 1307 - def expr({:not, _, [expression]}, sources, query) do 1320 + defp expr({:not, _, [expression]}, sources, query) do 1308 1321 ["NOT (", expr(expression, sources, query), ?)] 1309 1322 end 1310 1323 1311 - def expr({:filter, _, [agg, filter]}, sources, query) do 1324 + defp expr({:filter, _, [agg, filter]}, sources, query) do 1312 1325 aggregate = expr(agg, sources, query) 1313 1326 [aggregate, " FILTER (WHERE ", expr(filter, sources, query), ?)] 1314 1327 end 1315 1328 1316 - def expr(%Ecto.SubQuery{query: query}, sources, parent_query) do 1329 + defp expr(%Ecto.SubQuery{query: query}, sources, parent_query) do 1317 1330 combinations = 1318 1331 Enum.map(query.combinations, fn {type, combination_query} -> 1319 1332 {type, put_in(combination_query.aliases[@parent_as], {parent_query, sources})} ··· 1324 1337 [?(, all(query, subquery_as_prefix(sources)), ?)] 1325 1338 end 1326 1339 1327 - def expr({:fragment, _, [kw]}, _sources, query) 1328 - when is_list(kw) or tuple_size(kw) == 3 do 1340 + defp expr({:fragment, _, [kw]}, _sources, query) 1341 + when is_list(kw) or tuple_size(kw) == 3 do 1329 1342 raise Ecto.QueryError, 1330 1343 query: query, 1331 1344 message: "SQLite3 adapter does not support keyword or interpolated fragments" 1332 1345 end 1333 1346 1334 - def expr({:fragment, _, parts}, sources, query) do 1347 + defp expr({:fragment, _, parts}, sources, query) do 1335 1348 parts 1336 1349 |> Enum.map(fn 1337 1350 {:raw, part} -> part ··· 1340 1353 |> parens_for_select 1341 1354 end 1342 1355 1343 - def expr({:values, _, _}, _, _query) do 1356 + defp expr({:values, _, _}, _, _query) do 1344 1357 raise ArgumentError, "SQLite3 adapter does not support values lists" 1345 1358 end 1346 1359 1347 - def expr({:literal, _, [literal]}, _sources, _query) do 1360 + defp expr({:literal, _, [literal]}, _sources, _query) do 1348 1361 quote_name(literal) 1349 1362 end 1350 1363 1351 - def expr({:splice, _, [{:^, _, [_, length]}]}, _sources, _query) do 1364 + defp expr({:splice, _, [{:^, _, [_, length]}]}, _sources, _query) do 1352 1365 Enum.intersperse(List.duplicate(??, length), ?,) 1353 1366 end 1354 1367 1355 - def expr({:selected_as, _, [name]}, _sources, _query) do 1368 + defp expr({:selected_as, _, [name]}, _sources, _query) do 1356 1369 [quote_name(name)] 1357 1370 end 1358 1371 1359 - def expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do 1372 + defp expr({:datetime_add, _, [datetime, count, interval]}, sources, query) do 1360 1373 [ 1361 1374 "CAST (", 1362 1375 "strftime('%Y-%m-%d %H:%M:%f000Z'", ··· 1368 1381 ] 1369 1382 end 1370 1383 1371 - def expr({:date_add, _, [date, count, interval]}, sources, query) do 1384 + defp expr({:date_add, _, [date, count, interval]}, sources, query) do 1372 1385 [ 1373 1386 "CAST (", 1374 1387 "strftime('%Y-%m-%d'", ··· 1380 1393 ] 1381 1394 end 1382 1395 1383 - def expr({:ilike, _, [_, _]}, _sources, query) do 1396 + defp expr({:ilike, _, [_, _]}, _sources, query) do 1384 1397 raise Ecto.QueryError, 1385 1398 query: query, 1386 1399 message: "ilike is not supported by SQLite3" 1387 1400 end 1388 1401 1389 - def expr({:over, _, [agg, name]}, sources, query) when is_atom(name) do 1402 + defp expr({:over, _, [agg, name]}, sources, query) when is_atom(name) do 1390 1403 [expr(agg, sources, query), " OVER " | quote_name(name)] 1391 1404 end 1392 1405 1393 - def expr({:over, _, [agg, kw]}, sources, query) do 1406 + defp expr({:over, _, [agg, kw]}, sources, query) do 1394 1407 [expr(agg, sources, query), " OVER " | window_exprs(kw, sources, query)] 1395 1408 end 1396 1409 1397 - def expr({:{}, _, elems}, sources, query) do 1398 - [?(, intersperse_map(elems, ?,, &expr(&1, sources, query)), ?)] 1410 + defp expr({:{}, _, elems}, sources, query) do 1411 + [?(, Enum.map_intersperse(elems, ?,, &expr(&1, sources, query)), ?)] 1399 1412 end 1400 1413 1401 - def expr({:count, _, []}, _sources, _query), do: "count(*)" 1414 + defp expr({:count, _, []}, _sources, _query), do: "count(*)" 1402 1415 1403 - def expr({:count, _, [{:&, _, [_]}]}, _sources, query) do 1416 + defp expr({:count, _, [{:&, _, [_]}]}, _sources, query) do 1404 1417 raise Ecto.QueryError, 1405 1418 query: query, 1406 1419 message: "The argument to `count/1` must be a column in SQLite3" 1407 1420 end 1408 1421 1409 - def expr({:json_extract_path, _, [expr, path]}, sources, query) do 1422 + defp expr({:json_extract_path, _, [expr, path]}, sources, query) do 1410 1423 path = 1411 1424 Enum.map(path, fn 1412 1425 binary when is_binary(binary) -> ··· 1419 1432 ["json_extract(", expr(expr, sources, query), ", '$", path, "')"] 1420 1433 end 1421 1434 1422 - def expr({:exists, _, [subquery]}, sources, query) do 1435 + defp expr({:exists, _, [subquery]}, sources, query) do 1423 1436 ["exists", expr(subquery, sources, query)] 1424 1437 end 1425 1438 1426 - def expr({fun, _, args}, sources, query) when is_atom(fun) and is_list(args) do 1439 + defp expr({fun, _, args}, sources, query) when is_atom(fun) and is_list(args) do 1427 1440 {modifier, args} = 1428 1441 case args do 1429 1442 [_rest, :distinct] -> ··· 1441 1454 [op_to_binary(left, sources, query), op | op_to_binary(right, sources, query)] 1442 1455 1443 1456 {:fun, fun} -> 1444 - [fun, ?(, modifier, intersperse_map(args, ", ", &expr(&1, sources, query)), ?)] 1457 + [ 1458 + fun, 1459 + ?(, 1460 + modifier, 1461 + Enum.map_intersperse(args, ", ", &expr(&1, sources, query)), 1462 + ?) 1463 + ] 1445 1464 end 1446 1465 end 1447 1466 1448 1467 # TODO It technically is, its just a json array, so we *could* support it 1449 - def expr(list, _sources, query) when is_list(list) do 1468 + defp expr(list, _sources, query) when is_list(list) do 1450 1469 raise Ecto.QueryError, 1451 1470 query: query, 1452 1471 message: "Array literals are not supported by SQLite3" 1453 1472 end 1454 1473 1455 - def expr(%Decimal{} = decimal, _sources, _query) do 1474 + defp expr(%Decimal{} = decimal, _sources, _query) do 1456 1475 Decimal.to_string(decimal, :normal) 1457 1476 end 1458 1477 1459 - def expr(%Ecto.Query.Tagged{value: binary, type: :binary}, _sources, _query) 1460 - when is_binary(binary) do 1478 + defp expr(%Ecto.Query.Tagged{value: binary, type: :binary}, _sources, _query) 1479 + when is_binary(binary) do 1461 1480 hex = Base.encode16(binary, case: :lower) 1462 1481 [?x, ?', hex, ?'] 1463 1482 end 1464 1483 1465 - def expr(%Ecto.Query.Tagged{value: expr, type: :binary_id}, sources, query) do 1484 + defp expr(%Ecto.Query.Tagged{value: expr, type: :binary_id}, sources, query) do 1466 1485 case Application.get_env(:ecto_sqlite3, :binary_id_type, :string) do 1467 1486 :string -> 1468 1487 ["CAST(", expr(expr, sources, query), " AS ", column_type(:string, query), ?)] ··· 1472 1491 end 1473 1492 end 1474 1493 1475 - def expr(%Ecto.Query.Tagged{value: expr, type: :uuid}, sources, query) do 1494 + defp expr(%Ecto.Query.Tagged{value: expr, type: :uuid}, sources, query) do 1476 1495 case Application.get_env(:ecto_sqlite3, :uuid_type, :string) do 1477 1496 :string -> 1478 1497 ["CAST(", expr(expr, sources, query), " AS ", column_type(:string, query), ?)] ··· 1482 1501 end 1483 1502 end 1484 1503 1485 - def expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) 1486 - when type in [:decimal, :float] do 1504 + defp expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) 1505 + when type in [:decimal, :float] do 1487 1506 ["CAST(", expr(other, sources, query), " AS REAL)"] 1488 1507 end 1489 1508 1490 - def expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) do 1509 + defp expr(%Ecto.Query.Tagged{value: other, type: type}, sources, query) do 1491 1510 ["CAST(", expr(other, sources, query), " AS ", column_type(type, query), ?)] 1492 1511 end 1493 1512 1494 - def expr(nil, _sources, _query), do: "NULL" 1495 - def expr(true, _sources, _query), do: "1" 1496 - def expr(false, _sources, _query), do: "0" 1513 + defp expr(nil, _sources, _query), do: "NULL" 1514 + defp expr(true, _sources, _query), do: "1" 1515 + defp expr(false, _sources, _query), do: "0" 1497 1516 1498 - def expr(literal, _sources, _query) when is_binary(literal) do 1517 + defp expr(literal, _sources, _query) when is_binary(literal) do 1499 1518 [?', escape_string(literal), ?'] 1500 1519 end 1501 1520 1502 - def expr(literal, _sources, _query) when is_integer(literal) do 1521 + defp expr(literal, _sources, _query) when is_integer(literal) do 1503 1522 Integer.to_string(literal) 1504 1523 end 1505 1524 1506 - def expr(literal, _sources, _query) when is_float(literal) do 1525 + defp expr(literal, _sources, _query) when is_float(literal) do 1507 1526 ["CAST(", Float.to_string(literal), " AS REAL)"] 1508 1527 end 1509 1528 1510 - def expr(expr, _sources, query) do 1529 + defp expr(expr, _sources, query) do 1511 1530 raise Ecto.QueryError, 1512 1531 query: query, 1513 1532 message: "unsupported expression #{inspect(expr)}" ··· 1591 1610 end 1592 1611 1593 1612 defp column_definitions(table, columns) do 1594 - intersperse_map(columns, ", ", &column_definition(table, &1)) 1613 + Enum.map_intersperse(columns, ", ", &column_definition(table, &1)) 1595 1614 end 1596 1615 1597 1616 defp column_definition(table, {:add, name, %Reference{} = ref, opts}) do ··· 1681 1700 check = Keyword.get(opts, :check) 1682 1701 1683 1702 [ 1684 - default_expr(default, type), 1703 + default_expr(default), 1685 1704 null_expr(null), 1686 1705 collate_expr(collate), 1687 1706 check_expr(check), ··· 1705 1724 defp null_expr(true), do: " NULL" 1706 1725 defp null_expr(_), do: [] 1707 1726 1708 - defp default_expr({:ok, nil}, _type) do 1727 + defp default_expr({:ok, nil}) do 1709 1728 " DEFAULT NULL" 1710 1729 end 1711 1730 1712 - defp default_expr({:ok, literal}, _type) when is_binary(literal) do 1713 - [ 1714 - " DEFAULT '", 1715 - escape_string(literal), 1716 - ?' 1717 - ] 1731 + defp default_expr({:ok, literal}) when is_binary(literal) do 1732 + [" DEFAULT '", escape_string(literal), ?'] 1718 1733 end 1719 1734 1720 - defp default_expr({:ok, literal}, _type) 1721 - when is_number(literal) or is_boolean(literal) do 1722 - [ 1723 - " DEFAULT ", 1724 - to_string(literal) 1725 - ] 1735 + defp default_expr({:ok, literal}) when is_number(literal) or is_boolean(literal) do 1736 + [" DEFAULT ", to_string(literal)] 1726 1737 end 1727 1738 1728 - defp default_expr({:ok, {:fragment, expression}}, _type) do 1729 - [ 1730 - " DEFAULT ", 1731 - expression 1732 - ] 1739 + defp default_expr({:ok, {:fragment, expression}}) do 1740 + [" DEFAULT ", expression] 1733 1741 end 1734 1742 1735 - defp default_expr({:ok, value}, _type) when is_map(value) or is_list(value) do 1743 + defp default_expr({:ok, value}) when is_map(value) or is_list(value) do 1736 1744 library = Application.get_env(:ecto_sqlite3, :json_library, Jason) 1737 1745 expression = IO.iodata_to_binary(library.encode_to_iodata!(value)) 1738 1746 1739 - [ 1740 - " DEFAULT ", 1741 - ?(, 1742 - ?', 1743 - escape_string(expression), 1744 - ?', 1745 - ?) 1746 - ] 1747 + [" DEFAULT ('", escape_string(expression), "')"] 1747 1748 end 1748 1749 1749 - defp default_expr(:error, _type), do: [] 1750 + defp default_expr(:error), do: [] 1750 1751 1751 1752 defp index_expr(literal) when is_binary(literal), do: literal 1752 1753 defp index_expr(literal), do: quote_name(literal) ··· 1884 1885 end 1885 1886 end 1886 1887 1887 - defp quote_names(names), do: intersperse_map(names, ?,, &quote_name/1) 1888 + defp quote_names(names), do: Enum.map_intersperse(names, ?,, &quote_name/1) 1888 1889 1889 1890 def quote_name(name), do: quote_entity(name) 1890 1891 ··· 1901 1902 end 1902 1903 1903 1904 defp quote_entity(val), do: [[?", val, ?"]] 1904 - 1905 - defp intersperse_map(list, separator, mapper, acc \\ []) 1906 - 1907 - defp intersperse_map([], _separator, _mapper, acc) do 1908 - acc 1909 - end 1910 - 1911 - defp intersperse_map([elem], _separator, mapper, acc) do 1912 - [acc | mapper.(elem)] 1913 - end 1914 - 1915 - defp intersperse_map([elem | rest], separator, mapper, acc) do 1916 - intersperse_map(rest, separator, mapper, [acc, mapper.(elem), separator]) 1917 - end 1918 1905 1919 1906 defp intersperse_reduce(list, separator, user_acc, reducer, acc \\ []) 1920 1907
+1
lib/ecto/adapters/sqlite3/data_type.ex
··· 12 12 def column_type(:serial, _opts), do: "INTEGER" 13 13 def column_type(:bigserial, _opts), do: "INTEGER" 14 14 def column_type(:boolean, _opts), do: "INTEGER" 15 + def column_type(:integer, _opts), do: "INTEGER" 15 16 def column_type(:bigint, _opts), do: "INTEGER" 16 17 def column_type(:string, _opts), do: "TEXT" 17 18 def column_type(:float, _opts), do: "NUMERIC"
+13 -13
mix.lock
··· 1 1 %{ 2 - "benchee": {:hex, :benchee, "1.3.0", "f64e3b64ad3563fa9838146ddefb2d2f94cf5b473bdfd63f5ca4d0657bf96694", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "34f4294068c11b2bd2ebf2c59aac9c7da26ffa0068afdf3419f1b176e16c5f81"}, 2 + "benchee": {:hex, :benchee, "1.3.1", "c786e6a76321121a44229dde3988fc772bca73ea75170a73fd5f4ddf1af95ccf", [:mix], [{:deep_merge, "~> 1.0", [hex: :deep_merge, repo: "hexpm", optional: false]}, {:statistex, "~> 1.0", [hex: :statistex, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "76224c58ea1d0391c8309a8ecbfe27d71062878f59bd41a390266bf4ac1cc56d"}, 3 3 "benchee_markdown": {:hex, :benchee_markdown, "0.3.3", "d48a1d9782693fae6c294fdb12f653bb90088172d467996bedb9887ff41cf4ef", [:mix], [{:benchee, ">= 1.1.0 and < 2.0.0", [hex: :benchee, repo: "hexpm", optional: false]}], "hexpm", "106dab9ae0b448747da89b9af7285b71841f5d8131f37c6612b7370a157860a4"}, 4 4 "bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"}, 5 5 "cc_precompiler": {:hex, :cc_precompiler, "0.1.10", "47c9c08d8869cf09b41da36538f62bc1abd3e19e41701c2cea2675b53c704258", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "f6e046254e53cd6b41c6bacd70ae728011aa82b2742a80d6e2214855c6e06b22"}, 6 - "credo": {:hex, :credo, "1.7.6", "b8f14011a5443f2839b04def0b252300842ce7388f3af177157c86da18dfbeea", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "146f347fb9f8cbc5f7e39e3f22f70acbef51d441baa6d10169dd604bfbc55296"}, 7 - "db_connection": {:hex, :db_connection, "2.6.0", "77d835c472b5b67fc4f29556dee74bf511bbafecdcaf98c27d27fa5918152086", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c2f992d15725e721ec7fbc1189d4ecdb8afef76648c746a8e1cad35e3b8a35f3"}, 6 + "credo": {:hex, :credo, "1.7.7", "771445037228f763f9b2afd612b6aa2fd8e28432a95dbbc60d8e03ce71ba4446", [:mix], [{:bunt, "~> 0.2.1 or ~> 1.0", [hex: :bunt, repo: "hexpm", optional: false]}, {:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "8bc87496c9aaacdc3f90f01b7b0582467b69b4bd2441fe8aae3109d843cc2f2e"}, 7 + "db_connection": {:hex, :db_connection, "2.7.0", "b99faa9291bb09892c7da373bb82cba59aefa9b36300f6145c5f201c7adf48ec", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dcf08f31b2701f857dfc787fbad78223d61a32204f217f15e881dd93e4bdd3ff"}, 8 8 "decimal": {:hex, :decimal, "2.1.1", "5611dca5d4b2c3dd497dec8f68751f1f1a54755e8ed2a966c2633cf885973ad6", [:mix], [], "hexpm", "53cfe5f497ed0e7771ae1a475575603d77425099ba5faef9394932b35020ffcc"}, 9 9 "deep_merge": {:hex, :deep_merge, "1.0.0", "b4aa1a0d1acac393bdf38b2291af38cb1d4a52806cf7a4906f718e1feb5ee961", [:mix], [], "hexpm", "ce708e5f094b9cd4e8f2be4f00d2f4250c4095be93f8cd6d018c753894885430"}, 10 - "earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"}, 11 - "ecto": {:hex, :ecto, "3.11.2", "e1d26be989db350a633667c5cda9c3d115ae779b66da567c68c80cfb26a8c9ee", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c38bca2c6f8d8023f2145326cc8a80100c3ffe4dcbd9842ff867f7fc6156c65"}, 12 - "ecto_sql": {:hex, :ecto_sql, "3.11.2", "c7cc7f812af571e50b80294dc2e535821b3b795ce8008d07aa5f336591a185a8", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.11.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.6.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.16 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "73c07f995ac17dbf89d3cfaaf688fcefabcd18b7b004ac63b0dc4ef39499ed6b"}, 13 - "elixir_make": {:hex, :elixir_make, "0.8.3", "d38d7ee1578d722d89b4d452a3e36bcfdc644c618f0d063b874661876e708683", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "5c99a18571a756d4af7a4d89ca75c28ac899e6103af6f223982f09ce44942cc9"}, 14 - "ex_doc": {:hex, :ex_doc, "0.33.0", "690562b153153c7e4d455dc21dab86e445f66ceba718defe64b0ef6f0bd83ba0", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "3f69adc28274cb51be37d09b03e4565232862a4b10288a3894587b0131412124"}, 10 + "earmark_parser": {:hex, :earmark_parser, "1.4.41", "ab34711c9dc6212dda44fcd20ecb87ac3f3fce6f0ca2f28d4a00e4154f8cd599", [:mix], [], "hexpm", "a81a04c7e34b6617c2792e291b5a2e57ab316365c2644ddc553bb9ed863ebefa"}, 11 + "ecto": {:hex, :ecto, "3.12.1", "626765f7066589de6fa09e0876a253ff60c3d00870dd3a1cd696e2ba67bfceea", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "df0045ab9d87be947228e05a8d153f3e06e0d05ab10c3b3cc557d2f7243d1940"}, 12 + "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"}, 13 + "elixir_make": {:hex, :elixir_make, "0.8.4", "4960a03ce79081dee8fe119d80ad372c4e7badb84c493cc75983f9d3bc8bde0f", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.0", [hex: :certifi, repo: "hexpm", optional: true]}], "hexpm", "6e7f1d619b5f61dfabd0a20aa268e575572b542ac31723293a4c1a567d5ef040"}, 14 + "ex_doc": {:hex, :ex_doc, "0.34.2", "13eedf3844ccdce25cfd837b99bea9ad92c4e511233199440488d217c92571e8", [:mix], [{:earmark_parser, "~> 1.4.39", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_c, ">= 0.1.0", [hex: :makeup_c, repo: "hexpm", optional: true]}, {:makeup_elixir, "~> 0.14 or ~> 1.0", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1 or ~> 1.0", [hex: :makeup_erlang, repo: "hexpm", optional: false]}, {:makeup_html, ">= 0.1.0", [hex: :makeup_html, repo: "hexpm", optional: true]}], "hexpm", "5ce5f16b41208a50106afed3de6a2ed34f4acfd65715b82a0b84b49d995f95c1"}, 15 15 "exqlite": {:hex, :exqlite, "0.23.0", "6e851c937a033299d0784994c66da24845415072adbc455a337e20087bce9033", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "404341cceec5e6466aaed160cf0b58be2019b60af82588c215e1224ebd3ec831"}, 16 16 "file_system": {:hex, :file_system, "1.0.0", "b689cc7dcee665f774de94b5a832e578bd7963c8e637ef940cd44327db7de2cd", [:mix], [], "hexpm", "6752092d66aec5a10e662aefeed8ddb9531d79db0bc145bb8c40325ca1d8536d"}, 17 - "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, 17 + "jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"}, 18 18 "makeup": {:hex, :makeup, "1.1.2", "9ba8837913bdf757787e71c1581c21f9d2455f4dd04cfca785c70bbfff1a76a3", [:mix], [{:nimble_parsec, "~> 1.2.2 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cce1566b81fbcbd21eca8ffe808f33b221f9eee2cbc7a1706fc3da9ff18e6cac"}, 19 19 "makeup_elixir": {:hex, :makeup_elixir, "0.16.2", "627e84b8e8bf22e60a2579dad15067c755531fea049ae26ef1020cad58fe9578", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.2.3 or ~> 1.3", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "41193978704763f6bbe6cc2758b84909e62984c7752b3784bd3c218bb341706b"}, 20 - "makeup_erlang": {:hex, :makeup_erlang, "1.0.0", "6f0eff9c9c489f26b69b61440bf1b238d95badae49adac77973cbacae87e3c2e", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "ea7a9307de9d1548d2a72d299058d1fd2339e3d398560a0e46c27dab4891e4d2"}, 21 - "myxql": {:hex, :myxql, "0.6.4", "1502ea37ee23c31b79725b95d4cc3553693c2bda7421b1febc50722fd988c918", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a3307f4671f3009d3708283649adf205bfe280f7e036fc8ef7f16dbf821ab8e9"}, 20 + "makeup_erlang": {:hex, :makeup_erlang, "1.0.1", "c7f58c120b2b5aa5fd80d540a89fdf866ed42f1f3994e4fe189abebeab610839", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "8a89a1eeccc2d798d6ea15496a6e4870b75e014d1af514b1b71fa33134f57814"}, 21 + "myxql": {:hex, :myxql, "0.7.1", "7c7b75aa82227cd2bc9b7fbd4de774fb19a1cdb309c219f411f82ca8860f8e01", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:geo, "~> 3.4", [hex: :geo, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a491cdff53353a09b5850ac2d472816ebe19f76c30b0d36a43317a67c9004936"}, 22 22 "nimble_parsec": {:hex, :nimble_parsec, "1.4.0", "51f9b613ea62cfa97b25ccc2c1b4216e81df970acd8e16e8d1bdc58fef21370d", [:mix], [], "hexpm", "9c565862810fb383e9838c1dd2d7d2c437b3d13b267414ba6af33e50d2d1cf28"}, 23 - "postgrex": {:hex, :postgrex, "0.18.0", "f34664101eaca11ff24481ed4c378492fed2ff416cd9b06c399e90f321867d7e", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "a042989ba1bc1cca7383ebb9e461398e3f89f868c92ce6671feb7ef132a252d1"}, 23 + "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"}, 24 24 "statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"}, 25 25 "telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"}, 26 - "temp": {:hex, :temp, "0.4.7", "2c78482cc2294020a4bc0c95950b907ff386523367d4e63308a252feffbea9f2", [:mix], [], "hexpm", "6af19e7d6a85a427478be1021574d1ae2a1e1b90882586f06bde76c63cd03e0d"}, 26 + "temp": {:hex, :temp, "0.4.8", "89769b507614e50969aee1ee51bc799cf658bdde7aa73ec3909cbf68d93b7525", [:mix], [], "hexpm", "1e86d2361df398d3803e0d495042a9a4548d2b7316b83c0d60ad54250b03c5db"}, 27 27 }
+4 -3
test/ecto/adapters/sqlite3/connection/insert_test.exs
··· 131 131 test "insert with query as rows" do 132 132 query = from(s in "schema", select: %{foo: fragment("3"), bar: s.bar}) |> plan(:all) 133 133 134 - assert_raise ArgumentError, fn -> 135 - insert(nil, "schema", [:foo, :bar], query, {:raise, [], []}, [:foo]) 136 - end 134 + query = insert(nil, "schema", [:foo, :bar], query, {:raise, [], []}, [:foo]) 135 + 136 + assert query == 137 + ~s{INSERT INTO "schema" ("foo","bar") SELECT 3, s0."bar" FROM "schema" AS s0 RETURNING "foo"} 137 138 138 139 query = 139 140 from(s in "schema", select: %{foo: fragment("3"), bar: s.bar}, where: true)