Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
{ // Проверим, существует ли строка по натуральному уникальному ключу UK
var foo int
exists, myerr := s.db.Get(reqID, tx, "DeptExists", &foo, in.Deptno)
if myerr != nil {
return myerr
}
if exists {
return myerror.New("4004", "Error create - row already exists: reqID, Deptno", reqID, in.Deptno).PrintfInfo()
}
} // Проверим, существует ли строка по натуральному уникальному ключу UK
{ // Выполняем вставку и получим значение суррогатного PK
rows, myerr := s.db.Exec(reqID, tx, "CreateDept", in)
if myerr != nil {
return myerr
}
// проверим количество обработанных строк
if rows != 1 {
return myerror.New("4004", "Error create: reqID, Deptno, rows", reqID, in.Deptno, rows).PrintfInfo()
}
// считаем созданный объект - в БД могли быть триггера, которые меняли данные
// запрос делаем по UK, так как суррогатный PK мы еще не знаем
exists, myerr := s.db.Get(reqID, tx, "GetDeptUK", newDept, in.Deptno)
if myerr != nil {
return myerr
}
if !exists {
return myerror.New("4004", "Row does not exists after creating: reqID, Deptno", reqID, in.Deptno).PrintfInfo()
}
{ // Выполняем ВСЁ: вставку, проверку и получим значение суррогатного PK
rows, myerr := s.db.Prepare("
INSERT INTO dept (deptno, dname, loc)
VALUES (:deptno, :dname, :loc)
ON CONFLICT (dept) DO NOTHING
RETURNING id;
")
.QueryRow(in.deptno, in.dname, in.loc)
.Scan(&new_dept_id)
if rows != 1 {
return myerror.New("4004", "Error create - row already exists: reqID, Deptno", reqID, in.Deptno).PrintfInfo()
}
}
{ // Обработаем вложенные объекты в рамках текущей транзакции
if in.Emps != nil {
for _, newEmp := range in.Emps {
// Копируем суррогатный PK во внешний ключ вложенного объекта
newEmp.Deptno = null.Int{sql.NullInt64{int64(newDept.Deptno), true}}
// создаем вложенные объекты
if myerr = s.createEmp(ctx, tx, newEmp, nil); myerr != nil {
return myerr
}
}
}
} // Обработаем вложенные объекты в рамках текущей транзакции
-- in_json = '[{"empno":"empno1", "ename":"ename1", "job":"job1"....},{"empno":"empno2", "ename":"ename2", "job":"job2"....}....]'
-- new_dept_id
INSERT INTO emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
WITH d AS (
SELECT json_array_elements(:in_json::json) AS r
)
SELECT r->'empno', r->'ename', r->'job', r->'mgr', r->'hiredate', r->'sal', r->'comm', :deptno FROM d
Спасибо, что очень внимательно прочитали статью. Ваш отзыв очень полезен.
Вы правильно заметили, что это не универсальная библиотека — это шаблон, который нужно адаптировать под конкретную реализацию.
Если ваше решение работает только с PostgreSQL и вам не нужна реализация проверок на слое backend, то в шаблоне нужно правильно реализовать слой DB.
Используйте максимально все возможности PostgreSQL. Библиотека jackc/pgx отлично поддерживает массовую вставку из срезов.
Очень может быть, что вам и Go не нужен — используйте стандартные возможности PostgreSQL.
Шаблон backend сервера на Golang — часть 2 (REST API)