@@ -1146,6 +1146,50 @@ local function insert_internal(self, collection_name, from, filter, args, extra)
1146
1146
return {new_object }
1147
1147
end
1148
1148
1149
+ --- XXX
1150
+ local function update_internal (self , collection_name , from , filter , args ,
1151
+ extra , selected )
1152
+ local xobject = extra .extra_args .update
1153
+ if xobject == nil then return nil end
1154
+
1155
+ -- convert xobject -> update statements
1156
+ local collection = self .collections [collection_name ]
1157
+ assert (collection ~= nil ,
1158
+ (' cannot find the collection "%s"' ):format (collection_name ))
1159
+ local schema_name = collection .schema_name
1160
+ assert (type (schema_name ) == ' string' ,
1161
+ ' schema_name must be a string, got ' .. type (schema_name ))
1162
+
1163
+ local default_xflatten = self .default_xflatten [schema_name ]
1164
+ assert (default_xflatten ~= nil ,
1165
+ (' cannot find default_xflatten ' ..
1166
+ ' for collection "%s"' ):format (collection_name ))
1167
+
1168
+ local statements = self .funcs .xflatten (collection_name , xobject , {
1169
+ service_fields_defaults =
1170
+ self .service_fields_defaults [schema_name ],
1171
+ }, default_xflatten )
1172
+
1173
+ local _ , primary_index_meta = get_primary_index_meta (self , collection_name )
1174
+ local new_objects = {}
1175
+ for _ , object in ipairs (selected ) do
1176
+ local key = {}
1177
+ for _ , field_name in ipairs (primary_index_meta .fields ) do
1178
+ table.insert (key , object [field_name ])
1179
+ end
1180
+ -- XXX: we can pass a tuple corresponding the object to update_tuple to
1181
+ -- save one get operation
1182
+ local new_tuple = self .funcs .update_tuple (collection_name , key ,
1183
+ statements )
1184
+ local new_object = self .funcs .unflatten_tuple (collection_name ,
1185
+ new_tuple , {use_tomap = self .collection_use_tomap [collection_name ]},
1186
+ self .default_unflatten_tuple [schema_name ])
1187
+ table.insert (new_objects , new_object )
1188
+ end
1189
+
1190
+ return new_objects
1191
+ end
1192
+
1149
1193
--- Set of asserts to check the `funcs` argument of the @{accessor_general.new}
1150
1194
--- function.
1151
1195
--- @tparam table funcs set of function as defined in the
@@ -1169,9 +1213,15 @@ local function validate_funcs(funcs)
1169
1213
assert (type (funcs .flatten_object ) == ' function' ,
1170
1214
' funcs.flatten_object must be a function, got ' ..
1171
1215
type (funcs .flatten_object ))
1216
+ assert (type (funcs .xflatten ) == ' function' ,
1217
+ ' funcs.xflatten must be a function, got ' ..
1218
+ type (funcs .xflatten ))
1172
1219
assert (type (funcs .insert_tuple ) == ' function' ,
1173
1220
' funcs.insert_tuple must be a function, got ' ..
1174
1221
type (funcs .insert_tuple ))
1222
+ assert (type (funcs .update_tuple ) == ' function' ,
1223
+ ' funcs.update_tuple must be a function, got ' ..
1224
+ type (funcs .update_tuple ))
1175
1225
end
1176
1226
1177
1227
--- This function is called on first select related to a query. Its purpose is
@@ -1294,6 +1344,60 @@ local function get_pcre_argument_type(self, collection_name)
1294
1344
return pcre_type
1295
1345
end
1296
1346
1347
+ --- Create default unflatten/flatten/xflatten functions, that can be called
1348
+ --- from funcs.unflatten_tuple/funcs.flatten_object/funcs.xflatten when an
1349
+ --- additional pre/postprocessing is not needed.
1350
+ ---
1351
+ --- @tparam table models list of compiled schemas
1352
+ ---
1353
+ --- @treturn table table with default_* fields with maps from schema name to
1354
+ --- the corresponding default *flatten function
1355
+ local function gen_default_object_tuple_map_funcs (models )
1356
+ local default_unflatten_tuple = {}
1357
+ local default_flatten_object = {}
1358
+ local default_xflatten = {}
1359
+ for schema_name , model in pairs (models ) do
1360
+ default_unflatten_tuple [schema_name ] = function (_ , tuple , opts )
1361
+ local opts = opts or {}
1362
+ check (opts , ' opts' , ' table' )
1363
+
1364
+ local ok , obj = model .unflatten (tuple )
1365
+ assert (ok , (' cannot unflat tuple of schema "%s": %s' ):format (
1366
+ schema_name , tostring (obj )))
1367
+ return obj
1368
+ end
1369
+ default_flatten_object [schema_name ] = function (_ , obj , opts )
1370
+ local opts = opts or {}
1371
+ check (opts , ' opts' , ' table' )
1372
+ local sf_defaults = opts .service_fields_defaults or {}
1373
+ check (sf_defaults , ' service_fields_defaults' , ' table' )
1374
+
1375
+ local ok , tuple = model .flatten (obj , unpack (sf_defaults ))
1376
+ assert (ok , (' cannot flat object of schema "%s": %s' ):format (
1377
+ schema_name , tostring (tuple )))
1378
+ return tuple
1379
+ end
1380
+ default_xflatten [schema_name ] = function (_ , xobject , opts )
1381
+ local opts = opts or {}
1382
+ check (opts , ' opts' , ' table' )
1383
+
1384
+ -- it is not needed now, but maybe needed in custom xflatten
1385
+ local sf_defaults = opts .service_fields_defaults or {}
1386
+ check (sf_defaults , ' service_fields_defaults' , ' table' )
1387
+
1388
+ local ok , statements = model .xflatten (xobject )
1389
+ assert (ok , (' cannot xflat xobject of schema "%s": %s' ):format (
1390
+ schema_name , tostring (xobject )))
1391
+ return statements
1392
+ end
1393
+ end
1394
+ return {
1395
+ default_unflatten_tuple = default_unflatten_tuple ,
1396
+ default_flatten_object = default_flatten_object ,
1397
+ default_xflatten = default_xflatten ,
1398
+ }
1399
+ end
1400
+
1297
1401
--- Create a new data accessor.
1298
1402
---
1299
1403
--- Provided `funcs` argument determines certain functions for retrieving
@@ -1393,39 +1497,8 @@ function accessor_general.new(opts, funcs)
1393
1497
service_fields )
1394
1498
validate_collections (collections , schemas , indexes )
1395
1499
local index_cache = build_index_cache (indexes , collections )
1396
-
1397
- -- create default unflatten/flatten functions, that can be called from
1398
- -- funcs.unflatten_tuple/funcs.flatten_object when an additional
1399
- -- pre/postprocessing is not needed
1400
- local default_unflatten_tuple = {}
1401
- local default_flatten_object = {}
1402
- for schema_name , model in pairs (models ) do
1403
- default_unflatten_tuple [schema_name ] =
1404
- function (_ , tuple , opts )
1405
- local opts = opts or {}
1406
- check (opts , ' opts' , ' table' )
1407
-
1408
- local ok , obj = model .unflatten (tuple )
1409
- assert (ok , (' cannot unflat tuple of schema "%s": %s' ):format (
1410
- schema_name , tostring (obj )))
1411
- return obj
1412
- end
1413
- default_flatten_object [schema_name ] =
1414
- function (_ , obj , opts )
1415
- local opts = opts or {}
1416
- check (opts , ' opts' , ' table' )
1417
- local service_fields_defaults = opts .service_fields_defaults or
1418
- {}
1419
- check (service_fields_defaults , ' service_fields_defaults' ,
1420
- ' table' )
1421
-
1422
- local ok , tuple = model .flatten (obj ,
1423
- unpack (service_fields_defaults ))
1424
- assert (ok , (' cannot flat object of schema "%s": %s' ):format (
1425
- schema_name , tostring (tuple )))
1426
- return tuple
1427
- end
1428
- end
1500
+ local default_object_tuple_map_funcs =
1501
+ gen_default_object_tuple_map_funcs (models )
1429
1502
1430
1503
validate_funcs (funcs )
1431
1504
@@ -1435,8 +1508,12 @@ function accessor_general.new(opts, funcs)
1435
1508
service_fields = service_fields ,
1436
1509
indexes = indexes ,
1437
1510
models = models ,
1438
- default_unflatten_tuple = default_unflatten_tuple ,
1439
- default_flatten_object = default_flatten_object ,
1511
+ default_unflatten_tuple =
1512
+ default_object_tuple_map_funcs .default_unflatten_tuple ,
1513
+ default_flatten_object =
1514
+ default_object_tuple_map_funcs .default_flatten_object ,
1515
+ default_xflatten =
1516
+ default_object_tuple_map_funcs .default_xflatten ,
1440
1517
service_fields_defaults = service_fields_defaults ,
1441
1518
collection_use_tomap = opts .collection_use_tomap or {},
1442
1519
index_cache = index_cache ,
@@ -1463,8 +1540,14 @@ function accessor_general.new(opts, funcs)
1463
1540
filter , args , extra )
1464
1541
if inserted ~= nil then return inserted end
1465
1542
1466
- return select_internal (self , collection_name , from , filter ,
1543
+ local selected = select_internal (self , collection_name , from , filter ,
1467
1544
args , extra )
1545
+
1546
+ local updated = update_internal (self , collection_name , from ,
1547
+ filter , args , extra , selected )
1548
+ if updated ~= nil then return updated end
1549
+
1550
+ return selected
1468
1551
end ,
1469
1552
list_args = function (self , collection_name )
1470
1553
local offset_type = get_primary_key_type (self , collection_name )
@@ -1486,10 +1569,56 @@ function accessor_general.new(opts, funcs)
1486
1569
extra_args = function (self , collection_name )
1487
1570
local collection = self .collections [collection_name ]
1488
1571
local schema_name = collection .schema_name
1489
- local schema = table .copy (self .schemas [schema_name ])
1490
- schema .name = collection_name .. ' _insert'
1572
+
1573
+ local schema_insert = table .copy (self .schemas [schema_name ])
1574
+ schema_insert .name = collection_name .. ' _insert'
1575
+
1576
+ local _ , primary_index_meta = get_primary_index_meta (self ,
1577
+ collection_name )
1578
+
1579
+ local schema_update = {
1580
+ name = collection_name .. ' _update' ,
1581
+ type = ' record' ,
1582
+ fields = {},
1583
+ }
1584
+ -- add all fields except ones whose are part of the primary key
1585
+ for _ , field in ipairs (self .schemas [schema_name ].fields ) do
1586
+ assert (field .name ~= nil , ' field.name is nil' )
1587
+ local is_field_part_of_primary_key = false
1588
+ for _ , pk_field_name in ipairs (primary_index_meta .fields ) do
1589
+ if field .name == pk_field_name then
1590
+ is_field_part_of_primary_key = true
1591
+ break
1592
+ end
1593
+ end
1594
+
1595
+ if not is_field_part_of_primary_key then
1596
+ local field = table .copy (field )
1597
+ field .type = avro_helpers .make_avro_type_nullable (
1598
+ field .type )
1599
+ table.insert (schema_update .fields , field )
1600
+ end
1601
+ end
1602
+
1603
+ local schema_delete = ' boolean'
1604
+
1491
1605
return {
1492
- {name = ' insert' , type = schema }
1606
+ {name = ' insert' , type = schema_insert },
1607
+ {name = ' update' , type = schema_update },
1608
+ {name = ' delete' , type = schema_delete },
1609
+ }, {
1610
+ insert = {
1611
+ add_to_mutations_only = true ,
1612
+ add_to_top_fields_only = true ,
1613
+ },
1614
+ update = {
1615
+ add_to_mutations_only = true ,
1616
+ add_to_top_fields_only = false ,
1617
+ },
1618
+ delete = {
1619
+ add_to_mutations_only = true ,
1620
+ add_to_top_fields_only = false ,
1621
+ },
1493
1622
}
1494
1623
end ,
1495
1624
}
0 commit comments