elm-ssr 0.92.0 → 0.99.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/elm-src/ElmSsr/Db/Elmto/Changeset.elm +315 -0
- package/elm-src/ElmSsr/Db/Elmto/Compiler.elm +241 -0
- package/elm-src/ElmSsr/Db/Elmto/Query.elm +1335 -0
- package/elm-src/ElmSsr/Db/Elmto/Repo.elm +567 -0
- package/elm-src/ElmSsr/Db/Elmto.elm +130 -0
- package/elm-src/ElmSsr/Loader.elm +78 -1
- package/elm-src/ElmSsr/Route.elm +28 -3
- package/package.json +1 -1
- package/src/effects.ts +125 -0
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
module ElmSsr.Db.Elmto.Changeset exposing
|
|
2
|
+
( Changeset
|
|
3
|
+
, cast, castRecord
|
|
4
|
+
, validateRequired
|
|
5
|
+
, validateFormat
|
|
6
|
+
, validateLength
|
|
7
|
+
, validateNumber
|
|
8
|
+
, applyChanges
|
|
9
|
+
, errors, isValid, changes
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
import Dict exposing (Dict)
|
|
13
|
+
import ElmSsr.Db.Elmto as Elmto exposing (Schema, Field)
|
|
14
|
+
import Json.Decode as Decode
|
|
15
|
+
import Json.Encode as Encode
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
type alias Changeset record =
|
|
19
|
+
{ data : Maybe record
|
|
20
|
+
, changes : Dict String Encode.Value
|
|
21
|
+
, errors : List (String, String)
|
|
22
|
+
, isValid : Bool
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
cast : Schema record -> Dict String Decode.Value -> Changeset record
|
|
27
|
+
cast schema schemaAttrs =
|
|
28
|
+
let
|
|
29
|
+
schemaFields =
|
|
30
|
+
Elmto.fields schema
|
|
31
|
+
|
|
32
|
+
processField : Field record -> ( Dict String Encode.Value, List (String, String) ) -> ( Dict String Encode.Value, List (String, String) )
|
|
33
|
+
processField f ( accChanges, accErrors ) =
|
|
34
|
+
case Dict.get f.name schemaAttrs of
|
|
35
|
+
Just rawVal ->
|
|
36
|
+
case Decode.decodeValue f.decoder rawVal of
|
|
37
|
+
Ok encodedVal ->
|
|
38
|
+
( Dict.insert f.name encodedVal accChanges, accErrors )
|
|
39
|
+
|
|
40
|
+
Err err ->
|
|
41
|
+
( accChanges, ( f.name, "is invalid: " ++ Decode.errorToString err ) :: accErrors )
|
|
42
|
+
|
|
43
|
+
Nothing ->
|
|
44
|
+
( accChanges, accErrors )
|
|
45
|
+
|
|
46
|
+
( finalChanges, finalErrors ) =
|
|
47
|
+
List.foldl processField ( Dict.empty, [] ) schemaFields
|
|
48
|
+
in
|
|
49
|
+
{ data = Nothing
|
|
50
|
+
, changes = finalChanges
|
|
51
|
+
, errors = finalErrors
|
|
52
|
+
, isValid = List.isEmpty finalErrors
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
castRecord : Schema record -> record -> Dict String Decode.Value -> Changeset record
|
|
57
|
+
castRecord schema record schemaAttrs =
|
|
58
|
+
let
|
|
59
|
+
initial =
|
|
60
|
+
cast schema schemaAttrs
|
|
61
|
+
in
|
|
62
|
+
{ initial | data = Just record }
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
validateRequired : List String -> Changeset record -> Changeset record
|
|
66
|
+
validateRequired requiredFields changeset =
|
|
67
|
+
let
|
|
68
|
+
checkField : String -> List (String, String) -> List (String, String)
|
|
69
|
+
checkField fieldName acc =
|
|
70
|
+
let
|
|
71
|
+
changeVal =
|
|
72
|
+
Dict.get fieldName changeset.changes
|
|
73
|
+
|
|
74
|
+
isBlank =
|
|
75
|
+
case changeVal of
|
|
76
|
+
Just val ->
|
|
77
|
+
val == Encode.null
|
|
78
|
+
|
|
79
|
+
Nothing ->
|
|
80
|
+
case changeset.data of
|
|
81
|
+
Just _ ->
|
|
82
|
+
False
|
|
83
|
+
|
|
84
|
+
Nothing ->
|
|
85
|
+
True
|
|
86
|
+
in
|
|
87
|
+
if isBlank then
|
|
88
|
+
( fieldName, "can't be blank" ) :: acc
|
|
89
|
+
|
|
90
|
+
else
|
|
91
|
+
acc
|
|
92
|
+
|
|
93
|
+
newErrors =
|
|
94
|
+
List.foldl checkField changeset.errors requiredFields
|
|
95
|
+
in
|
|
96
|
+
{ changeset
|
|
97
|
+
| errors = newErrors
|
|
98
|
+
, isValid = List.isEmpty newErrors
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
validateFormat : String -> (String -> Bool) -> String -> Changeset record -> Changeset record
|
|
103
|
+
validateFormat fieldName formatFn msg changeset =
|
|
104
|
+
let
|
|
105
|
+
val =
|
|
106
|
+
Dict.get fieldName changeset.changes
|
|
107
|
+
|
|
108
|
+
isInvalid =
|
|
109
|
+
case val of
|
|
110
|
+
Just encodedVal ->
|
|
111
|
+
case Decode.decodeValue Decode.string encodedVal of
|
|
112
|
+
Ok str ->
|
|
113
|
+
not (formatFn str)
|
|
114
|
+
|
|
115
|
+
Err _ ->
|
|
116
|
+
False
|
|
117
|
+
|
|
118
|
+
Nothing ->
|
|
119
|
+
False
|
|
120
|
+
in
|
|
121
|
+
if isInvalid then
|
|
122
|
+
let
|
|
123
|
+
newErrors =
|
|
124
|
+
( fieldName, msg ) :: changeset.errors
|
|
125
|
+
in
|
|
126
|
+
{ changeset | errors = newErrors, isValid = False }
|
|
127
|
+
|
|
128
|
+
else
|
|
129
|
+
changeset
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
validateLength : String -> { min : Maybe Int, max : Maybe Int } -> Changeset record -> Changeset record
|
|
133
|
+
validateLength fieldName opts changeset =
|
|
134
|
+
let
|
|
135
|
+
val =
|
|
136
|
+
Dict.get fieldName changeset.changes
|
|
137
|
+
|
|
138
|
+
isInvalid =
|
|
139
|
+
case val of
|
|
140
|
+
Just encodedVal ->
|
|
141
|
+
case Decode.decodeValue Decode.string encodedVal of
|
|
142
|
+
Ok str ->
|
|
143
|
+
let
|
|
144
|
+
len =
|
|
145
|
+
String.length str
|
|
146
|
+
|
|
147
|
+
tooShort =
|
|
148
|
+
case opts.min of
|
|
149
|
+
Just m ->
|
|
150
|
+
len < m
|
|
151
|
+
|
|
152
|
+
Nothing ->
|
|
153
|
+
False
|
|
154
|
+
|
|
155
|
+
tooLong =
|
|
156
|
+
case opts.max of
|
|
157
|
+
Just m ->
|
|
158
|
+
len > m
|
|
159
|
+
|
|
160
|
+
Nothing ->
|
|
161
|
+
False
|
|
162
|
+
in
|
|
163
|
+
tooShort || tooLong
|
|
164
|
+
|
|
165
|
+
Err _ ->
|
|
166
|
+
False
|
|
167
|
+
|
|
168
|
+
Nothing ->
|
|
169
|
+
False
|
|
170
|
+
in
|
|
171
|
+
if isInvalid then
|
|
172
|
+
let
|
|
173
|
+
msg =
|
|
174
|
+
case ( opts.min, opts.max ) of
|
|
175
|
+
( Just minVal, Just maxVal ) ->
|
|
176
|
+
"should be between " ++ String.fromInt minVal ++ " and " ++ String.fromInt maxVal ++ " characters"
|
|
177
|
+
|
|
178
|
+
( Just minVal, Nothing ) ->
|
|
179
|
+
"should be at least " ++ String.fromInt minVal ++ " characters"
|
|
180
|
+
|
|
181
|
+
( Nothing, Just maxVal ) ->
|
|
182
|
+
"should be at most " ++ String.fromInt maxVal ++ " characters"
|
|
183
|
+
|
|
184
|
+
_ ->
|
|
185
|
+
"invalid length"
|
|
186
|
+
|
|
187
|
+
newErrors =
|
|
188
|
+
( fieldName, msg ) :: changeset.errors
|
|
189
|
+
in
|
|
190
|
+
{ changeset | errors = newErrors, isValid = False }
|
|
191
|
+
|
|
192
|
+
else
|
|
193
|
+
changeset
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
validateNumber : String -> { greaterThan : Maybe Float, lessThan : Maybe Float } -> Changeset record -> Changeset record
|
|
197
|
+
validateNumber fieldName opts changeset =
|
|
198
|
+
let
|
|
199
|
+
val =
|
|
200
|
+
Dict.get fieldName changeset.changes
|
|
201
|
+
|
|
202
|
+
isInvalid =
|
|
203
|
+
case val of
|
|
204
|
+
Just encodedVal ->
|
|
205
|
+
case Decode.decodeValue Decode.float encodedVal of
|
|
206
|
+
Ok num ->
|
|
207
|
+
let
|
|
208
|
+
tooSmall =
|
|
209
|
+
case opts.greaterThan of
|
|
210
|
+
Just gtVal ->
|
|
211
|
+
num <= gtVal
|
|
212
|
+
|
|
213
|
+
Nothing ->
|
|
214
|
+
False
|
|
215
|
+
|
|
216
|
+
tooLarge =
|
|
217
|
+
case opts.lessThan of
|
|
218
|
+
Just ltVal ->
|
|
219
|
+
num >= ltVal
|
|
220
|
+
|
|
221
|
+
Nothing ->
|
|
222
|
+
False
|
|
223
|
+
in
|
|
224
|
+
tooSmall || tooLarge
|
|
225
|
+
|
|
226
|
+
Err _ ->
|
|
227
|
+
False
|
|
228
|
+
|
|
229
|
+
Nothing ->
|
|
230
|
+
False
|
|
231
|
+
in
|
|
232
|
+
if isInvalid then
|
|
233
|
+
let
|
|
234
|
+
msg =
|
|
235
|
+
case ( opts.greaterThan, opts.lessThan ) of
|
|
236
|
+
( Just gtVal, Just ltVal ) ->
|
|
237
|
+
"must be greater than " ++ String.fromFloat gtVal ++ " and less than " ++ String.fromFloat ltVal
|
|
238
|
+
|
|
239
|
+
( Just gtVal, Nothing ) ->
|
|
240
|
+
"must be greater than " ++ String.fromFloat gtVal
|
|
241
|
+
|
|
242
|
+
( Nothing, Just ltVal ) ->
|
|
243
|
+
"must be less than " ++ String.fromFloat ltVal
|
|
244
|
+
|
|
245
|
+
_ ->
|
|
246
|
+
"invalid number"
|
|
247
|
+
|
|
248
|
+
newErrors =
|
|
249
|
+
( fieldName, msg ) :: changeset.errors
|
|
250
|
+
in
|
|
251
|
+
{ changeset | errors = newErrors, isValid = False }
|
|
252
|
+
|
|
253
|
+
else
|
|
254
|
+
changeset
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
applyChanges : Schema record -> Changeset record -> Result (List (String, String)) record
|
|
258
|
+
applyChanges schema schemaChangeset =
|
|
259
|
+
if not schemaChangeset.isValid then
|
|
260
|
+
Err schemaChangeset.errors
|
|
261
|
+
|
|
262
|
+
else
|
|
263
|
+
let
|
|
264
|
+
originalJson =
|
|
265
|
+
case schemaChangeset.data of
|
|
266
|
+
Just rec ->
|
|
267
|
+
let
|
|
268
|
+
schemaFields =
|
|
269
|
+
Elmto.fields schema
|
|
270
|
+
|
|
271
|
+
encField f acc =
|
|
272
|
+
( f.name, f.encoder rec ) :: acc
|
|
273
|
+
in
|
|
274
|
+
List.foldl encField [] schemaFields
|
|
275
|
+
|> Encode.object
|
|
276
|
+
|
|
277
|
+
Nothing ->
|
|
278
|
+
Encode.object []
|
|
279
|
+
|
|
280
|
+
mergedJson =
|
|
281
|
+
case Decode.decodeValue (Decode.dict Decode.value) originalJson of
|
|
282
|
+
Ok dict ->
|
|
283
|
+
let
|
|
284
|
+
mergedDict =
|
|
285
|
+
Dict.foldl (\k v acc -> Dict.insert k v acc) dict schemaChangeset.changes
|
|
286
|
+
in
|
|
287
|
+
Encode.dict identity (\v -> v) mergedDict
|
|
288
|
+
|
|
289
|
+
Err _ ->
|
|
290
|
+
originalJson
|
|
291
|
+
|
|
292
|
+
decoded =
|
|
293
|
+
Decode.decodeValue (Elmto.decoder schema) mergedJson
|
|
294
|
+
in
|
|
295
|
+
case decoded of
|
|
296
|
+
Ok rec ->
|
|
297
|
+
Ok rec
|
|
298
|
+
|
|
299
|
+
Err err ->
|
|
300
|
+
Err [ ( "changeset", "Failed to apply changes: " ++ Decode.errorToString err ) ]
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
errors : Changeset record -> List (String, String)
|
|
304
|
+
errors changeset =
|
|
305
|
+
changeset.errors
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
isValid : Changeset record -> Bool
|
|
309
|
+
isValid changeset =
|
|
310
|
+
changeset.isValid
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
changes : Changeset record -> Dict String Encode.Value
|
|
314
|
+
changes changeset =
|
|
315
|
+
changeset.changes
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
module ElmSsr.Db.Elmto.Compiler exposing
|
|
2
|
+
( Dialect(..)
|
|
3
|
+
, compileSelect
|
|
4
|
+
, compileInsert
|
|
5
|
+
, compileUpdate
|
|
6
|
+
, compileUpdateAll
|
|
7
|
+
, compileDelete
|
|
8
|
+
, compileDeleteAll
|
|
9
|
+
, toDialectSql
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
import Dict
|
|
13
|
+
import ElmSsr.Db.Elmto as Elmto exposing (Schema, Field)
|
|
14
|
+
import ElmSsr.Db.Elmto.Changeset as Changeset exposing (Changeset)
|
|
15
|
+
import ElmSsr.Db.Elmto.Query as Query exposing (Query)
|
|
16
|
+
import Json.Decode as Decode
|
|
17
|
+
import Json.Encode as Encode
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
type Dialect
|
|
21
|
+
= PostgreSQL
|
|
22
|
+
| SQLite
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
toDialectSql : Dialect -> String -> String
|
|
26
|
+
toDialectSql dialect baseSql =
|
|
27
|
+
case dialect of
|
|
28
|
+
SQLite ->
|
|
29
|
+
baseSql
|
|
30
|
+
|
|
31
|
+
PostgreSQL ->
|
|
32
|
+
let
|
|
33
|
+
parts =
|
|
34
|
+
String.split "?" baseSql
|
|
35
|
+
|
|
36
|
+
joinParts index list acc =
|
|
37
|
+
case list of
|
|
38
|
+
[] ->
|
|
39
|
+
acc
|
|
40
|
+
|
|
41
|
+
x :: xs ->
|
|
42
|
+
if index == 0 then
|
|
43
|
+
joinParts 1 xs x
|
|
44
|
+
|
|
45
|
+
else
|
|
46
|
+
joinParts (index + 1) xs (acc ++ "$" ++ String.fromInt index ++ x)
|
|
47
|
+
in
|
|
48
|
+
joinParts 0 parts ""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
compileSelect : Dialect -> Query record selection -> { sql : String, params : List Encode.Value, decoder : Decode.Decoder selection }
|
|
52
|
+
compileSelect dialect query =
|
|
53
|
+
let
|
|
54
|
+
castPostgresNumbers =
|
|
55
|
+
case dialect of
|
|
56
|
+
PostgreSQL ->
|
|
57
|
+
True
|
|
58
|
+
|
|
59
|
+
SQLite ->
|
|
60
|
+
False
|
|
61
|
+
|
|
62
|
+
compiled =
|
|
63
|
+
Query.rawSelect castPostgresNumbers query
|
|
64
|
+
|
|
65
|
+
q =
|
|
66
|
+
Query.toParts query
|
|
67
|
+
in
|
|
68
|
+
{ sql = toDialectSql dialect compiled.sql
|
|
69
|
+
, params = compiled.params
|
|
70
|
+
, decoder = q.decoder
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
compileInsert : Dialect -> Schema record -> Changeset record -> Result (List (String, String)) { sql : String, params : List Encode.Value }
|
|
75
|
+
compileInsert dialect schema changeset =
|
|
76
|
+
if not (Changeset.isValid changeset) then
|
|
77
|
+
Err (Changeset.errors changeset)
|
|
78
|
+
|
|
79
|
+
else
|
|
80
|
+
let
|
|
81
|
+
changeList =
|
|
82
|
+
Dict.toList (Changeset.changes changeset)
|
|
83
|
+
in
|
|
84
|
+
if List.isEmpty changeList then
|
|
85
|
+
case dialect of
|
|
86
|
+
SQLite ->
|
|
87
|
+
Ok
|
|
88
|
+
{ sql = "INSERT INTO " ++ Elmto.tableName schema ++ " DEFAULT VALUES"
|
|
89
|
+
, params = []
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
PostgreSQL ->
|
|
93
|
+
Ok
|
|
94
|
+
{ sql = "INSERT INTO " ++ Elmto.tableName schema ++ " DEFAULT VALUES RETURNING *"
|
|
95
|
+
, params = []
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
else
|
|
99
|
+
let
|
|
100
|
+
cols =
|
|
101
|
+
List.map Tuple.first changeList
|
|
102
|
+
|
|
103
|
+
vals =
|
|
104
|
+
List.map Tuple.second changeList
|
|
105
|
+
|
|
106
|
+
placeholders =
|
|
107
|
+
List.map (\_ -> "?") cols
|
|
108
|
+
|> String.join ", "
|
|
109
|
+
|
|
110
|
+
columnsStr =
|
|
111
|
+
String.join ", " cols
|
|
112
|
+
|
|
113
|
+
returningStr =
|
|
114
|
+
case dialect of
|
|
115
|
+
PostgreSQL ->
|
|
116
|
+
" RETURNING *"
|
|
117
|
+
|
|
118
|
+
SQLite ->
|
|
119
|
+
""
|
|
120
|
+
|
|
121
|
+
rawSql =
|
|
122
|
+
"INSERT INTO " ++ Elmto.tableName schema ++ " (" ++ columnsStr ++ ") VALUES (" ++ placeholders ++ ")" ++ returningStr
|
|
123
|
+
in
|
|
124
|
+
Ok
|
|
125
|
+
{ sql = toDialectSql dialect rawSql
|
|
126
|
+
, params = vals
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
compileUpdate : Dialect -> Schema record -> Changeset record -> Result (List (String, String)) { sql : String, params : List Encode.Value }
|
|
131
|
+
compileUpdate dialect schema changeset =
|
|
132
|
+
if not (Changeset.isValid changeset) then
|
|
133
|
+
Err (Changeset.errors changeset)
|
|
134
|
+
|
|
135
|
+
else
|
|
136
|
+
case changeset.data of
|
|
137
|
+
Nothing ->
|
|
138
|
+
Err [ ( "changeset", "cannot update a changeset without a loaded record" ) ]
|
|
139
|
+
|
|
140
|
+
Just record ->
|
|
141
|
+
let
|
|
142
|
+
idField =
|
|
143
|
+
List.filter (\f -> f.name == "id") (Elmto.fields schema)
|
|
144
|
+
|> List.head
|
|
145
|
+
|
|
146
|
+
idVal =
|
|
147
|
+
case idField of
|
|
148
|
+
Just f ->
|
|
149
|
+
f.encoder record
|
|
150
|
+
|
|
151
|
+
Nothing ->
|
|
152
|
+
Encode.null
|
|
153
|
+
in
|
|
154
|
+
if idVal == Encode.null then
|
|
155
|
+
Err [ ( "changeset", "record has no id field for updates" ) ]
|
|
156
|
+
|
|
157
|
+
else
|
|
158
|
+
let
|
|
159
|
+
changeList =
|
|
160
|
+
Dict.toList (Changeset.changes changeset)
|
|
161
|
+
in
|
|
162
|
+
if List.isEmpty changeList then
|
|
163
|
+
Err [ ( "changeset", "no changes to update" ) ]
|
|
164
|
+
|
|
165
|
+
else
|
|
166
|
+
let
|
|
167
|
+
setClauses =
|
|
168
|
+
List.map (\( col, _ ) -> col ++ " = ?") changeList
|
|
169
|
+
|> String.join ", "
|
|
170
|
+
|
|
171
|
+
params =
|
|
172
|
+
List.map Tuple.second changeList ++ [ idVal ]
|
|
173
|
+
|
|
174
|
+
returningStr =
|
|
175
|
+
case dialect of
|
|
176
|
+
PostgreSQL ->
|
|
177
|
+
" RETURNING *"
|
|
178
|
+
|
|
179
|
+
SQLite ->
|
|
180
|
+
""
|
|
181
|
+
|
|
182
|
+
rawSql =
|
|
183
|
+
"UPDATE " ++ Elmto.tableName schema ++ " SET " ++ setClauses ++ " WHERE id = ?" ++ returningStr
|
|
184
|
+
in
|
|
185
|
+
Ok
|
|
186
|
+
{ sql = toDialectSql dialect rawSql
|
|
187
|
+
, params = params
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
compileUpdateAll : Dialect -> Schema record -> Query.Expression record -> Changeset record -> Result (List (String, String)) { sql : String, params : List Encode.Value }
|
|
192
|
+
compileUpdateAll dialect schema expr changeset =
|
|
193
|
+
if not (Changeset.isValid changeset) then
|
|
194
|
+
Err (Changeset.errors changeset)
|
|
195
|
+
|
|
196
|
+
else
|
|
197
|
+
let
|
|
198
|
+
changeList =
|
|
199
|
+
Dict.toList (Changeset.changes changeset)
|
|
200
|
+
in
|
|
201
|
+
if List.isEmpty changeList then
|
|
202
|
+
Err [ ( "changeset", "no changes to update" ) ]
|
|
203
|
+
|
|
204
|
+
else
|
|
205
|
+
let
|
|
206
|
+
setClauses =
|
|
207
|
+
List.map (\( col, _ ) -> col ++ " = ?") changeList
|
|
208
|
+
|> String.join ", "
|
|
209
|
+
|
|
210
|
+
whereSql =
|
|
211
|
+
Query.expressionSqlFrom (Elmto.tableName schema) identity expr
|
|
212
|
+
|
|
213
|
+
rawSql =
|
|
214
|
+
"UPDATE " ++ Elmto.tableName schema ++ " SET " ++ setClauses ++ " WHERE " ++ whereSql
|
|
215
|
+
in
|
|
216
|
+
Ok
|
|
217
|
+
{ sql = toDialectSql dialect rawSql
|
|
218
|
+
, params = List.map Tuple.second changeList ++ Query.expressionParams expr
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
compileDelete : Dialect -> Schema record -> Encode.Value -> { sql : String, params : List Encode.Value }
|
|
223
|
+
compileDelete dialect schema idVal =
|
|
224
|
+
let
|
|
225
|
+
rawSql =
|
|
226
|
+
"DELETE FROM " ++ Elmto.tableName schema ++ " WHERE id = ?"
|
|
227
|
+
in
|
|
228
|
+
{ sql = toDialectSql dialect rawSql
|
|
229
|
+
, params = [ idVal ]
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
compileDeleteAll : Dialect -> Schema record -> Query.Expression record -> { sql : String, params : List Encode.Value }
|
|
234
|
+
compileDeleteAll dialect schema expr =
|
|
235
|
+
let
|
|
236
|
+
rawSql =
|
|
237
|
+
"DELETE FROM " ++ Elmto.tableName schema ++ " WHERE " ++ Query.expressionSqlFrom (Elmto.tableName schema) identity expr
|
|
238
|
+
in
|
|
239
|
+
{ sql = toDialectSql dialect rawSql
|
|
240
|
+
, params = Query.expressionParams expr
|
|
241
|
+
}
|