1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-24 07:39:43 +02:00

PostgreSQL prep

Update of vendored SQL libs and refactoring of store provider layer.
This commit is contained in:
HarveyKandola 2018-09-26 17:59:56 +01:00
parent d0e005f638
commit b455e5eaf5
105 changed files with 10949 additions and 2376 deletions

View file

@ -13,7 +13,6 @@ package database
import (
"fmt"
"strings"
"github.com/documize/community/core/env"
"github.com/documize/community/core/streamutil"
@ -83,7 +82,7 @@ func Check(runtime *env.Runtime) bool {
return false
}
if strings.TrimSpace(flds[0]) == "0" {
if len(flds) == 0 {
runtime.Log.Info("Database: starting setup mode for empty database")
runtime.Flags.SiteMode = env.SiteModeSetup
return false

View file

@ -12,36 +12,37 @@
package database
import (
"github.com/documize/community/core/env"
"testing"
)
// go test github.com/documize/community/core/database -run TestGetVersion
func TestGetVersion(t *testing.T) {
ts2(t, "5.7.10", []int{5, 7, 10})
ts2(t, "5.7.10-log", []int{5, 7, 10})
ts2(t, "5.7.10-demo", []int{5, 7, 10})
ts2(t, "5.7.10-debug", []int{5, 7, 10})
ts2(t, "5.7.16-10", []int{5, 7, 16})
ts2(t, "5.7.12-0ubuntu0-12.12.3", []int{5, 7, 12})
ts2(t, "10.1.20-MariaDB-1~jessie", []int{10, 1, 20})
ts2(t, "ubuntu0-12.12.3", []int{0, 0, 0})
ts2(t, "junk-string", []int{0, 0, 0})
ts2(t, "somethingstring", []int{0, 0, 0})
}
// func TestGetVersion(t *testing.T) {
// ts2(t, "5.7.10", []int{5, 7, 10})
// ts2(t, "5.7.10-log", []int{5, 7, 10})
// ts2(t, "5.7.10-demo", []int{5, 7, 10})
// ts2(t, "5.7.10-debug", []int{5, 7, 10})
// ts2(t, "5.7.16-10", []int{5, 7, 16})
// ts2(t, "5.7.12-0ubuntu0-12.12.3", []int{5, 7, 12})
// ts2(t, "10.1.20-MariaDB-1~jessie", []int{10, 1, 20})
// ts2(t, "ubuntu0-12.12.3", []int{0, 0, 0})
// ts2(t, "junk-string", []int{0, 0, 0})
// ts2(t, "somethingstring", []int{0, 0, 0})
// }
func ts2(t *testing.T, in string, out []int) {
got, _ := GetSQLVersion(in)
// func ts2(t *testing.T, in string, out []int) {
// got, _ := GetSQLVersion(in)
// if err != nil {
// t.Errorf("Unable to GetSQLVersion %s", err)
// }
// // if err != nil {
// // t.Errorf("Unable to GetSQLVersion %s", err)
// // }
for k, v := range got {
if v != out[k] {
t.Errorf("version input of %s got %d for position %d but expected %d\n", in, v, k, out[k])
}
}
}
// for k, v := range got {
// if v != out[k] {
// t.Errorf("version input of %s got %d for position %d but expected %d\n", in, v, k, out[k])
// }
// }
// }
func TestDatabaseVersionLegacy(t *testing.T) {
i := extractVersionNumber("db_00021.sql")
@ -59,3 +60,15 @@ func TestDatabaseVersionLegacy(t *testing.T) {
t.Errorf("expected 26 got %d", i)
}
}
func TestParamRebind(t *testing.T) {
q1in := "INSERT INTO dmz_org (c_refid, c_company, c_title) VALUES (?, ?, ?)"
q1out := "INSERT INTO dmz_org (c_refid, c_company, c_title) VALUES ($1, $2, $3)"
test1 := RebindParams(q1in, env.StoreTypePostgreSQL)
if test1 != q1out {
t.Errorf("expected %s got %s", q1in, test1)
}
t.Log(test1)
}

View file

@ -16,7 +16,6 @@ import (
"regexp"
"strconv"
"strings"
// "time"
"github.com/documize/community/core/env"
"github.com/jmoiron/sqlx"
@ -62,9 +61,9 @@ func InstallUpgrade(runtime *env.Runtime, existingDB bool) (err error) {
}
}
runtime.Log.Info(fmt.Sprintf("Database: %d scripts to process", len(toProcess)))
runtime.Log.Info(fmt.Sprintf("Database: %d scripts to process", len(toProcess)))
// For MySQL type there was major new schema introduced in v24.
// For MySQL type there was major new schema introduced in v24.
// We check for this release and bypass usual locking code
// because tables have changed.
legacyMigration := runtime.StoreProvider.Type() == env.StoreTypeMySQL &&
@ -75,7 +74,7 @@ func InstallUpgrade(runtime *env.Runtime, existingDB bool) (err error) {
// which we are about to install.
toProcess = toProcess[len(toProcess)-1:]
runtime.Log.Info(fmt.Sprintf("Database: legacy schema has %d scripts to process", len(toProcess)))
runtime.Log.Info(fmt.Sprintf("Database: legacy schema has %d scripts to process", len(toProcess)))
}
tx, err := runtime.Db.Beginx()
@ -160,14 +159,14 @@ func runScripts(runtime *env.Runtime, tx *sqlx.Tx, scripts []Script) (err error)
_, err = tx.Exec(runtime.StoreProvider.QueryRecordVersionUpgradeLegacy(script.Version))
if err != nil {
runtime.Log.Error(fmt.Sprintf("error recording execution of SQL script %d", script.Version), err)
runtime.Log.Error(fmt.Sprintf("error recording execution of SQL script %d", script.Version), err)
return err
}
} else {
// Unknown issue running script on non-MySQL database.
runtime.Log.Error(fmt.Sprintf("error executing SQL script %d", script.Version), err)
return err
}
// Unknown issue running script on non-MySQL database.
runtime.Log.Error(fmt.Sprintf("error executing SQL script %d", script.Version), err)
return err
}
}
}

View file

@ -11,100 +11,100 @@
package database
import (
"crypto/rand"
"time"
// import (
// "crypto/rand"
// "time"
"github.com/documize/community/core/env"
"github.com/jmoiron/sqlx"
)
// "github.com/documize/community/core/env"
// "github.com/jmoiron/sqlx"
// )
// Lock will try to lock the database instance to the running process.
// Uses a "random" delay as a por man's database cluster-aware process.
// We skip delay if there are no scripts to process.
func Lock(runtime *env.Runtime, scriptsToProcess int) (bool, error) {
// Wait for random period of time.
b := make([]byte, 2)
_, err := rand.Read(b)
if err != nil {
return false, err
}
wait := ((time.Duration(b[0]) << 8) | time.Duration(b[1])) * time.Millisecond / 10 // up to 6.5 secs wait
// // Lock will try to lock the database instance to the running process.
// // Uses a "random" delay as a por man's database cluster-aware process.
// // We skip delay if there are no scripts to process.
// func Lock(runtime *env.Runtime, scriptsToProcess int) (bool, error) {
// // Wait for random period of time.
// b := make([]byte, 2)
// _, err := rand.Read(b)
// if err != nil {
// return false, err
// }
// wait := ((time.Duration(b[0]) << 8) | time.Duration(b[1])) * time.Millisecond / 10 // up to 6.5 secs wait
// Why delay if nothing to process?
if scriptsToProcess > 0 {
time.Sleep(wait)
}
// // Why delay if nothing to process?
// if scriptsToProcess > 0 {
// time.Sleep(wait)
// }
// Start transaction fotr lock process.
tx, err := runtime.Db.Beginx()
if err != nil {
runtime.Log.Error("Database: unable to start transaction", err)
return false, err
}
// // Start transaction fotr lock process.
// tx, err := runtime.Db.Beginx()
// if err != nil {
// runtime.Log.Error("Database: unable to start transaction", err)
// return false, err
// }
// Lock the database.
_, err = tx.Exec(runtime.StoreProvider.QueryStartLock())
if err != nil {
runtime.Log.Error("Database: unable to lock tables", err)
return false, err
}
// // Lock the database.
// _, err = tx.Exec(runtime.StoreProvider.QueryStartLock())
// if err != nil {
// runtime.Log.Error("Database: unable to lock tables", err)
// return false, err
// }
// Unlock the database at the end of this function.
defer func() {
_, err = tx.Exec(runtime.StoreProvider.QueryFinishLock())
if err != nil {
runtime.Log.Error("Database: unable to unlock tables", err)
}
tx.Commit()
}()
// // Unlock the database at the end of this function.
// defer func() {
// _, err = tx.Exec(runtime.StoreProvider.QueryFinishLock())
// if err != nil {
// runtime.Log.Error("Database: unable to unlock tables", err)
// }
// tx.Commit()
// }()
// Try to record this process as leader of database migration process.
_, err = tx.Exec(runtime.StoreProvider.QueryInsertProcessID())
if err != nil {
runtime.Log.Info("Database: marked as slave process awaiting upgrade")
return false, nil
}
// // Try to record this process as leader of database migration process.
// _, err = tx.Exec(runtime.StoreProvider.QueryInsertProcessID())
// if err != nil {
// runtime.Log.Info("Database: marked as slave process awaiting upgrade")
// return false, nil
// }
// We are the leader!
runtime.Log.Info("Database: marked as database upgrade process leader")
return true, err
}
// // We are the leader!
// runtime.Log.Info("Database: marked as database upgrade process leader")
// return true, err
// }
// Unlock completes process that was started with Lock().
func Unlock(runtime *env.Runtime, tx *sqlx.Tx, err error, amLeader bool) error {
if amLeader {
defer func() {
doUnlock(runtime)
}()
// // Unlock completes process that was started with Lock().
// func Unlock(runtime *env.Runtime, tx *sqlx.Tx, err error, amLeader bool) error {
// if amLeader {
// defer func() {
// doUnlock(runtime)
// }()
if tx != nil {
if err == nil {
tx.Commit()
runtime.Log.Info("Database: is ready")
return nil
}
tx.Rollback()
}
// if tx != nil {
// if err == nil {
// tx.Commit()
// runtime.Log.Info("Database: is ready")
// return nil
// }
// tx.Rollback()
// }
runtime.Log.Error("Database: install/upgrade failed", err)
// runtime.Log.Error("Database: install/upgrade failed", err)
return err
}
// return err
// }
return nil // not the leader, so ignore errors
}
// return nil // not the leader, so ignore errors
// }
// Helper method for defer function called from Unlock().
func doUnlock(runtime *env.Runtime) error {
tx, err := runtime.Db.Beginx()
if err != nil {
return err
}
_, err = tx.Exec(runtime.StoreProvider.QueryDeleteProcessID())
if err != nil {
return err
}
// // Helper method for defer function called from Unlock().
// func doUnlock(runtime *env.Runtime) error {
// tx, err := runtime.Db.Beginx()
// if err != nil {
// return err
// }
// _, err = tx.Exec(runtime.StoreProvider.QueryDeleteProcessID())
// if err != nil {
// return err
// }
return tx.Commit()
}
// return tx.Commit()
// }

39
core/database/params.go Normal file
View file

@ -0,0 +1,39 @@
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
//
// This software (Documize Community Edition) is licensed under
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
//
// You can operate outside the AGPL restrictions by purchasing
// Documize Enterprise Edition and obtaining a commercial license
// by contacting <sales@documize.com>.
//
// https://documize.com
package database
import (
"github.com/documize/community/core/env"
"github.com/jmoiron/sqlx"
)
// RebindParams changes MySQL query parameter placeholder from "?" to
// correct value for given database provider.
//
// MySQL uses ?, ?, ? (default for all Documize queries)
// PostgreSQL uses $1, $2, $3
// MS SQL Server uses @p1, @p2, @p3
func RebindParams(sql string, s env.StoreType) string {
bindParam := sqlx.QUESTION
switch s {
case env.StoreTypePostgreSQL:
bindParam = sqlx.DOLLAR
}
return sqlx.Rebind(bindParam, sql)
}
// RebindPostgreSQL is a helper method on top of RebindParams.
func RebindPostgreSQL(sql string) string {
return RebindParams(sql, env.StoreTypePostgreSQL)
}

View file

@ -21,9 +21,9 @@ import (
// Scripts holds all .SQL files for all supported database providers.
type Scripts struct {
MySQLScripts []Script
PostgresSQLScripts []Script
SQLServerScripts []Script
MySQL []Script
PostgreSQL []Script
SQLServer []Script
}
// Script holds SQL script and it's associated version number.
@ -37,7 +37,12 @@ func LoadScripts() (s Scripts, err error) {
assetDir := "bindata/scripts"
// MySQL
s.MySQLScripts, err = loadFiles(fmt.Sprintf("%s/mysql", assetDir))
s.MySQL, err = loadFiles(fmt.Sprintf("%s/mysql", assetDir))
if err != nil {
return
}
// PostgreSQL
s.PostgreSQL, err = loadFiles(fmt.Sprintf("%s/postgresql", assetDir))
if err != nil {
return
}
@ -49,11 +54,11 @@ func LoadScripts() (s Scripts, err error) {
func SpecificScripts(runtime *env.Runtime, all Scripts) (s []Script) {
switch runtime.StoreProvider.Type() {
case env.StoreTypeMySQL, env.StoreTypeMariaDB, env.StoreTypePercona:
return all.MySQLScripts
return all.MySQL
case env.StoreTypePostgreSQL:
return all.PostgresSQLScripts
return all.PostgreSQL
case env.StoreTypeMSSQL:
return all.SQLServerScripts
return all.SQLServer
}
return

View file

@ -1,5 +1,4 @@
-- SQL to set up the Documize database
-- SELECT version() as vstring, current_setting('server_version_num') as vnumber, pg_encoding_to_char(encoding) AS charset FROM pg_database WHERE datname = 'documize';
-- select * from information_schema.tables WHERE table_catalog='documize';
-- http://www.postgresqltutorial.com/postgresql-json/
-- https://en.wikibooks.org/wiki/Converting_MySQL_to_PostgreSQL
@ -491,3 +490,8 @@ CREATE TABLE dmz_user_config (
c_config json DEFAULT NULL,
UNIQUE (c_orgid,c_userid,c_key)
);
INSERT INTO dmz_config VALUES ('SMTP','{"userid": "","password": "","host": "","port": "","sender": ""}');
INSERT INTO dmz_config VALUES ('FILEPLUGINS', '[{"Comment": "Disable (or not) built-in html import (NOTE: no Plugin name)","Disabled": false,"API": "Convert","Actions": ["htm","html"]},{"Comment": "Disable (or not) built-in Documize API import used from SDK (NOTE: no Plugin name)","Disabled": false,"API": "Convert","Actions": ["documizeapi"]}]');
INSERT INTO dmz_config VALUES ('SECTION-TRELLO','{"appKey": ""}');
INSERT INTO dmz_config VALUES ('META','{"database": "0"}');

View file

@ -13,9 +13,7 @@ package database
import (
"errors"
"fmt"
"net/http"
"strings"
"time"
"github.com/documize/community/core/api/plugins"
@ -124,130 +122,124 @@ type onboardRequest struct {
// setupAccount prepares the database for a newly onboard customer.
// Once done, they can then login and use Documize.
func setupAccount(rt *env.Runtime, completion onboardRequest, serial string) (err error) {
//accountTitle := "This is where you will find documentation for your all projects. You can customize this message from the settings screen."
salt := secrets.GenerateSalt()
password := secrets.GeneratePassword(completion.Password, salt)
// Allocate organization to the user.
orgID := uniqueid.Generate()
sql := fmt.Sprintf("insert into dmz_org (c_refid, c_company, c_title, c_message, c_domain, c_email, c_serial) VALUES (\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\")",
orgID, completion.Company, completion.CompanyLong, completion.Message, completion.URL, completion.Email, serial)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT TINO dmz_org failed", err)
return
}
userID := uniqueid.Generate()
sql = fmt.Sprintf("INSERT INTO dmz_user (c_refid, c_firstname, c_lastname, c_email, c_initials, c_salt, c_password, c_globaladmin) VALUES (\"%s\",\"%s\", \"%s\", \"%s\", \"%s\", \"%s\", \"%s\", 1)",
userID, completion.Firstname, completion.Lastname, completion.Email, stringutil.MakeInitials(completion.Firstname, completion.Lastname), salt, password)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT TINO dmz_user failed", err)
return err
}
// Link user to organization.
accountID := uniqueid.Generate()
sql = fmt.Sprintf("INSERT INTO dmz_user_account (c_refid, c_userid, c_orgid, c_admin, c_editor, c_users, c_analytics) VALUES (\"%s\", \"%s\", \"%s\", 1, 1, 1, 1)", accountID, userID, orgID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT TINO dmz_user_account failed", err)
return err
}
// create space
labelID := uniqueid.Generate()
sql = fmt.Sprintf("INSERT INTO dmz_space (c_refid, c_orgid, c_name, c_type, c_userid) VALUES (\"%s\", \"%s\", \"My Project\", 2, \"%s\")", labelID, orgID, userID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT INTO dmz_space failed", err)
}
// assign permissions to space
perms := []string{"view", "manage", "own", "doc-add", "doc-edit", "doc-delete", "doc-move", "doc-copy", "doc-template", "doc-approve", "doc-version", "doc-lifecycle"}
for _, p := range perms {
sql = fmt.Sprintf("INSERT INTO dmz_permission (c_orgid, c_who, c_whoid, c_action, c_scope, c_location, c_refid) VALUES (\"%s\", 'user', \"%s\", \"%s\", 'object', 'space', \"%s\")", orgID, userID, p, labelID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT INTO dmz_permission failed", err)
}
}
// Create some user groups
groupDevID := uniqueid.Generate()
sql = fmt.Sprintf("INSERT INTO dmz_group (c_refid, c_orgid, c_name, c_desc) VALUES (\"%s\", \"%s\", \"Technology\", \"On-site and remote development teams\")", groupDevID, orgID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group failed", err)
}
groupProjectID := uniqueid.Generate()
sql = fmt.Sprintf("INSERT INTO dmz_group (c_refid, c_orgid, c_name, c_desc) VALUES (\"%s\", \"%s\", \"Project Management\", \"HQ project management\")", groupProjectID, orgID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group failed", err)
}
groupBackofficeID := uniqueid.Generate()
sql = fmt.Sprintf("INSERT INTO dmz_group (c_refid, c_orgid, c_name, c_desc) VALUES (\"%s\", \"%s\", \"Back Office\", \"Non-IT and PMO personnel\")", groupBackofficeID, orgID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group failed", err)
}
// Join some groups
sql = fmt.Sprintf("INSERT INTO dmz_group_member (c_orgid, c_groupid, c_userid) VALUES (\"%s\", \"%s\", \"%s\")", orgID, groupDevID, userID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group_member failed", err)
}
sql = fmt.Sprintf("INSERT INTO dmz_group_member (c_orgid, c_groupid, c_userid) VALUES (\"%s\", \"%s\", \"%s\")", orgID, groupProjectID, userID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group_member failed", err)
}
sql = fmt.Sprintf("INSERT INTO dmz_group_member (c_orgid, c_groupid, c_userid) VALUES (\"%s\", \"%s\", \"%s\")", orgID, groupBackofficeID, userID)
_, err = runSQL(rt, sql)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group_member failed", err)
}
return
}
// runSQL creates a transaction per call
func runSQL(rt *env.Runtime, sql string) (id uint64, err error) {
if strings.TrimSpace(sql) == "" {
return 0, nil
}
tx, err := rt.Db.Beginx()
if err != nil {
rt.Log.Error("setup - failed to get transaction", err)
return
}
result, err := tx.Exec(sql)
//accountTitle := "This is where you will find documentation for your all projects. You can customize this message from the settings screen."
salt := secrets.GenerateSalt()
password := secrets.GeneratePassword(completion.Password, salt)
// Allocate organization to the user.
orgID := uniqueid.Generate()
_, err = tx.Exec(RebindParams("INSERT INTO dmz_org (c_refid, c_company, c_title, c_message, c_domain, c_email, c_serial) VALUES (?, ?, ?, ?, ?, ?, ?)", rt.StoreProvider.Type()),
orgID, completion.Company, completion.CompanyLong, completion.Message, completion.URL, completion.Email, serial)
if err != nil {
rt.Log.Error("INSERT INTO dmz_org failed", err)
tx.Rollback()
rt.Log.Error("setup - unable to run sql", err)
return
}
// Create user.
userID := uniqueid.Generate()
_, err = tx.Exec(RebindParams("INSERT INTO dmz_user (c_refid, c_firstname, c_lastname, c_email, c_initials, c_salt, c_password, c_globaladmin) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", rt.StoreProvider.Type()),
userID, completion.Firstname, completion.Lastname, completion.Email, stringutil.MakeInitials(completion.Firstname, completion.Lastname), salt, password, 1)
if err != nil {
rt.Log.Error("INSERT INTO dmz_user failed", err)
tx.Rollback()
return
}
// Link user to organization.
accountID := uniqueid.Generate()
_, err = tx.Exec(RebindParams("INSERT INTO dmz_user_account (c_refid, c_userid, c_orgid, c_admin, c_editor, c_users, c_analytics) VALUES (?, ?, ?, ?, ?, ?, ?)", rt.StoreProvider.Type()),
accountID, userID, orgID, 1, 1, 1, 1)
if err != nil {
rt.Log.Error("INSERT INTO dmz_user_account failed", err)
tx.Rollback()
return
}
// Create space.
labelID := uniqueid.Generate()
_, err = tx.Exec(RebindParams("INSERT INTO dmz_space (c_refid, c_orgid, c_userid, c_name, c_type) VALUES (?, ?, ?, ?, ?)", rt.StoreProvider.Type()),
labelID, orgID, userID, "Welcome", 2)
if err != nil {
rt.Log.Error("INSERT INTO dmz_space failed", err)
tx.Rollback()
return
}
// Assign permissions to space.
perms := []string{"view", "manage", "own", "doc-add", "doc-edit", "doc-delete", "doc-move", "doc-copy", "doc-template", "doc-approve", "doc-version", "doc-lifecycle"}
for _, p := range perms {
_, err = tx.Exec(RebindParams("INSERT INTO dmz_permission (c_orgid, c_who, c_whoid, c_action, c_scope, c_location, c_refid) VALUES (?, ?, ?, ?, ?, ?, ?)", rt.StoreProvider.Type()),
orgID, "user", userID, p, "object", "space", labelID)
if err != nil {
rt.Log.Error("INSERT INTO dmz_permission failed", err)
tx.Rollback()
return
}
}
// Create some user groups.
groupDevID := uniqueid.Generate()
_, err = tx.Exec(RebindParams("INSERT INTO dmz_group (c_refid, c_orgid, c_name, c_desc) VALUES (?, ?, ?, ?)", rt.StoreProvider.Type()),
groupDevID, orgID, "Technology", "On-site and remote development teams")
if err != nil {
rt.Log.Error("INSERT INTO dmz_group failed", err)
tx.Rollback()
return
}
groupProjectID := uniqueid.Generate()
_, err = tx.Exec(RebindParams("INSERT INTO dmz_group (c_refid, c_orgid, c_name, c_desc) VALUES (?, ?, ?, ?)", rt.StoreProvider.Type()),
groupProjectID, orgID, "Project Management", "HQ PMO and Account Management departments")
if err != nil {
rt.Log.Error("INSERT INTO dmz_group failed", err)
tx.Rollback()
return
}
groupBackofficeID := uniqueid.Generate()
_, err = tx.Exec(RebindParams("INSERT INTO dmz_group (c_refid, c_orgid, c_name, c_desc) VALUES (?, ?, ?, ?)", rt.StoreProvider.Type()),
groupBackofficeID, orgID, "Back Office", "Finance and HR people")
if err != nil {
rt.Log.Error("INSERT INTO dmz_group failed", err)
tx.Rollback()
return
}
// Join the user groups.
_, err = tx.Exec(RebindParams("INSERT INTO dmz_group_member (c_orgid, c_groupid, c_userid) VALUES (?, ?, ?)", rt.StoreProvider.Type()),
orgID, groupDevID, userID)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group_member failed", err)
tx.Rollback()
return
}
_, err = tx.Exec(RebindParams("INSERT INTO dmz_group_member (c_orgid, c_groupid, c_userid) VALUES (?, ?, ?)", rt.StoreProvider.Type()),
orgID, groupProjectID, userID)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group_member failed", err)
tx.Rollback()
return
}
_, err = tx.Exec(RebindParams("INSERT INTO dmz_group_member (c_orgid, c_groupid, c_userid) VALUES (?, ?, ?)", rt.StoreProvider.Type()),
orgID, groupBackofficeID, userID)
if err != nil {
rt.Log.Error("INSERT INTO dmz_group_member failed", err)
tx.Rollback()
return
}
// Finish up.
if err = tx.Commit(); err != nil {
rt.Log.Error("setup - unable to commit sql", err)
return
}
tempID, _ := result.LastInsertId()
id = uint64(tempID)
return
}