Add createOrUpdateRecord
and record method generators.
`createOrUpdateRecord` implements upsert: update an existing record if it exists or create a new record if not. A new error `DbUpdateError` was added to be raised when an existing record does exist but was not able to be updated.
This commit is contained in:
parent
540d0d2f67
commit
fbd20de71f
@ -107,6 +107,7 @@
|
||||
##
|
||||
## proc createTodoItem*(db: TodoDB, rec: TodoItem): TodoItem;
|
||||
## proc updateTodoItem*(db: TodoDB, rec: TodoItem): bool;
|
||||
## proc createOrUpdateTodoItem*(db: TodoDB, rec: TodoItem): bool;
|
||||
## proc deleteTodoItem*(db: TodoDB, rec: TodoItem): bool;
|
||||
## proc deleteTodoItem*(db: TodoDB, id: UUID): bool;
|
||||
##
|
||||
@ -312,6 +313,9 @@ type
|
||||
records*: seq[T]
|
||||
totalRecords*: int
|
||||
|
||||
DbUpdateError* = object of CatchableError ##\
|
||||
## Error types raised when a DB modification fails.
|
||||
|
||||
NotFoundError* = object of CatchableError ##\
|
||||
## Error type raised when no record matches a given ID
|
||||
|
||||
@ -366,6 +370,24 @@ proc updateRecord*[D: DbConnType, T](db: D, rec: T): bool =
|
||||
|
||||
return numRowsUpdated > 0;
|
||||
|
||||
proc createOrUpdateRecord*[D: DbConnType, T](db: D, rec: T): T =
|
||||
## Create or update a record. `rec` is expected to be a `model class`_. If
|
||||
## the `id` field is unset, or if there is no existing record with the given
|
||||
## id, a new record is inserted. Otherwise, the existing record is updated.
|
||||
##
|
||||
## Note that this does not perform partial updates, all fields are updated.
|
||||
|
||||
let findRecordStmt = "SELECT id FROM " & tableName(rec) & " WHERE id = ?"
|
||||
log().debug "createOrUpdateRecord: [" & findRecordStmt & "] id: " & $rec.id
|
||||
let rows = db.getAllRows(sql(findRecordStmt), [$rec.id])
|
||||
|
||||
if rows.len == 0: result = createRecord(db, rec)
|
||||
else:
|
||||
result = rec
|
||||
if not updateRecord(db, rec):
|
||||
raise newException(DbUpdateError,
|
||||
"unable to update " & modelName(rec) & " for id " & $rec.id)
|
||||
|
||||
template deleteRecord*[D: DbConnType](db: D, modelType: type, id: typed): untyped =
|
||||
## Delete a record by id.
|
||||
let sqlStmt = "DELETE FROM " & tableName(modelType) & " WHERE id = ?"
|
||||
@ -516,6 +538,7 @@ macro generateProcsForModels*(dbType: type, modelTypes: openarray[type]): untype
|
||||
## proc deleteTodoItem*(db: TodoDB, rec: TodoItem): bool;
|
||||
## proc deleteTodoItem*(db: TodoDB, id: idType): bool;
|
||||
## proc updateTodoItem*(db: TodoDB, rec: TodoItem): bool;
|
||||
## proc createOrUpdateTodoItem*(db: TodoDB, rec: TodoItem): bool;
|
||||
##
|
||||
## proc findTodoItemsWhere*(
|
||||
## db: TodoDB, whereClause: string, values: varargs[string]): TodoItem;
|
||||
@ -537,6 +560,7 @@ macro generateProcsForModels*(dbType: type, modelTypes: openarray[type]): untype
|
||||
let findWhereName = ident("find" & pluralize(modelName) & "Where")
|
||||
let createName = ident("create" & modelName)
|
||||
let updateName = ident("update" & modelName)
|
||||
let createOrUpdateName = ident("createOrUpdate" & modelName)
|
||||
let deleteName = ident("delete" & modelName)
|
||||
let idType = typeOfColumn(t, "id")
|
||||
result.add quote do:
|
||||
@ -560,6 +584,9 @@ macro generateProcsForModels*(dbType: type, modelTypes: openarray[type]): untype
|
||||
proc `updateName`*(db: `dbType`, rec: `t`): bool =
|
||||
db.withConn: result = updateRecord(conn, rec)
|
||||
|
||||
proc `createOrUpdateName`*(db: `dbType`, rec: `t`): `t` =
|
||||
db.inTransaction: result = createOrUpdateRecord(conn, rec)
|
||||
|
||||
proc `deleteName`*(db: `dbType`, rec: `t`): bool =
|
||||
db.withConn: result = deleteRecord(conn, rec)
|
||||
|
||||
|
@ -102,7 +102,7 @@ proc dbFormat*[T](list: seq[T]): string =
|
||||
|
||||
proc dbFormat*[T](item: T): string =
|
||||
## For all other types, fall back on a defined `$` function to create a
|
||||
## string version of the value we can include in an SQL query>
|
||||
## string version of the value we can include in an SQL query.
|
||||
return $item
|
||||
|
||||
type DbArrayParseState = enum
|
||||
|
Loading…
x
Reference in New Issue
Block a user