121 lines
4.3 KiB
Go
121 lines
4.3 KiB
Go
//go:build mysql
|
|
// +build mysql
|
|
|
|
package mysql
|
|
|
|
import (
|
|
"errors"
|
|
|
|
mysqldriver "github.com/go-sql-driver/mysql"
|
|
)
|
|
|
|
type ignoreSQLError struct {
|
|
sql string
|
|
code uint16
|
|
}
|
|
|
|
func ensureIMRegistrationInviteControlTables(exec sqlExecutor) error {
|
|
statements := []string{
|
|
`CREATE TABLE IF NOT EXISTS im_registration_invite_batches(
|
|
id BIGINT NOT NULL,
|
|
tenant_id BIGINT NOT NULL,
|
|
quantity INT UNSIGNED NOT NULL,
|
|
max_uses_per_code INT UNSIGNED NOT NULL DEFAULT 0,
|
|
idempotency_key VARCHAR(128) NOT NULL,
|
|
expires_at DATETIME(3) NOT NULL,
|
|
created_by BIGINT NOT NULL,
|
|
remark VARCHAR(255) NOT NULL DEFAULT '',
|
|
created_at DATETIME(3) NOT NULL,
|
|
updated_at DATETIME(3) NOT NULL,
|
|
PRIMARY KEY(id),
|
|
UNIQUE INDEX uk_im_registration_invite_batch_tenant_idempotency(tenant_id,idempotency_key),
|
|
INDEX idx_im_registration_invite_batch_tenant_created(tenant_id,created_at)
|
|
)`,
|
|
`CREATE TABLE IF NOT EXISTS im_registration_invite_codes(
|
|
id BIGINT NOT NULL,
|
|
tenant_id BIGINT NOT NULL,
|
|
batch_id BIGINT,
|
|
code CHAR(5) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
|
|
status VARCHAR(16) NOT NULL,
|
|
expires_at DATETIME(3) NOT NULL,
|
|
max_uses INT UNSIGNED NOT NULL DEFAULT 0,
|
|
bound_user_id BIGINT NULL,
|
|
bound_user_label VARCHAR(128) NOT NULL DEFAULT '',
|
|
usage_count INT UNSIGNED NOT NULL DEFAULT 0,
|
|
last_used_at DATETIME(3) NULL,
|
|
created_by BIGINT NOT NULL,
|
|
remark VARCHAR(255) NOT NULL DEFAULT '',
|
|
created_at DATETIME(3) NOT NULL,
|
|
updated_at DATETIME(3) NOT NULL,
|
|
PRIMARY KEY(id),
|
|
UNIQUE INDEX uk_im_registration_invite_code_tenant(tenant_id,code),
|
|
INDEX idx_im_registration_invite_tenant_bound_user(tenant_id,bound_user_id),
|
|
INDEX idx_im_registration_invite_tenant_status_expires(tenant_id,status,expires_at),
|
|
INDEX idx_im_registration_invite_tenant_batch(tenant_id,batch_id),
|
|
INDEX idx_im_registration_invite_tenant_created(tenant_id,created_at)
|
|
)`,
|
|
}
|
|
for _, stmt := range statements {
|
|
if _, err := exec.Exec(stmt); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
alterStatements := []ignoreSQLError{
|
|
{`ALTER TABLE im_registration_invite_codes ADD COLUMN max_uses INT UNSIGNED NOT NULL DEFAULT 0 AFTER expires_at`, 1060},
|
|
{`ALTER TABLE im_registration_invite_codes ADD COLUMN bound_user_id BIGINT NULL AFTER max_uses`, 1060},
|
|
{`ALTER TABLE im_registration_invite_codes ADD COLUMN bound_user_label VARCHAR(128) NOT NULL DEFAULT '' AFTER bound_user_id`, 1060},
|
|
{`ALTER TABLE im_registration_invite_codes ADD INDEX idx_im_registration_invite_tenant_bound_user(tenant_id,bound_user_id)`, 1061},
|
|
{`ALTER TABLE im_registration_invite_batches ADD COLUMN max_uses_per_code INT UNSIGNED NOT NULL DEFAULT 0 AFTER quantity`, 1060},
|
|
}
|
|
for _, stmt := range alterStatements {
|
|
if err := execIgnoreMySQLError(exec, stmt.sql, stmt.code); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func execIgnoreMySQLError(exec sqlExecutor, statement string, code uint16) error {
|
|
if _, err := exec.Exec(statement); err != nil {
|
|
var mysqlErr *mysqldriver.MySQLError
|
|
if errors.As(err, &mysqlErr) && mysqlErr.Number == code {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ensureIMRegistrationInviteUseTable(exec sqlExecutor) error {
|
|
if _, err := exec.Exec(`CREATE TABLE IF NOT EXISTS im_registration_invite_uses(
|
|
id BIGINT NOT NULL,
|
|
invite_code_id BIGINT NOT NULL,
|
|
user_id BIGINT NOT NULL,
|
|
request_id VARCHAR(64) NOT NULL,
|
|
used_at DATETIME(3) NOT NULL,
|
|
PRIMARY KEY(id),
|
|
INDEX idx_im_registration_invite_use_code(invite_code_id),
|
|
UNIQUE INDEX uk_im_registration_invite_use_user(user_id),
|
|
INDEX idx_im_registration_invite_use_request(request_id)
|
|
)`); err != nil {
|
|
return err
|
|
}
|
|
for _, migration := range []struct {
|
|
statement string
|
|
ignored uint16
|
|
}{
|
|
{`ALTER TABLE im_registration_invite_uses DROP INDEX uk_im_registration_invite_use_code`, 1091},
|
|
{`ALTER TABLE im_registration_invite_uses ADD INDEX idx_im_registration_invite_use_code(invite_code_id)`, 1061},
|
|
} {
|
|
if _, err := exec.Exec(migration.statement); err != nil && !isMySQLErrorNumber(err, migration.ignored) {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func isMySQLErrorNumber(err error, number uint16) bool {
|
|
var mysqlErr *mysqldriver.MySQLError
|
|
return errors.As(err, &mysqlErr) && mysqlErr.Number == number
|
|
}
|