2019-06-21 13:56:57 +02:00
|
|
|
package jet
|
2019-05-07 13:44:30 +02:00
|
|
|
|
|
|
|
|
import (
|
2019-06-20 12:22:19 +02:00
|
|
|
"context"
|
2019-05-07 13:44:30 +02:00
|
|
|
"database/sql"
|
2019-06-21 16:16:57 +02:00
|
|
|
"errors"
|
2019-06-21 13:56:57 +02:00
|
|
|
"github.com/go-jet/jet/execution"
|
2019-05-07 13:44:30 +02:00
|
|
|
)
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// TableLockMode is a type of possible SQL table lock
|
2019-06-15 13:58:45 +02:00
|
|
|
type TableLockMode string
|
2019-05-07 13:44:30 +02:00
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// Lock types for LockStatement.
|
2019-05-07 13:44:30 +02:00
|
|
|
const (
|
|
|
|
|
LOCK_ACCESS_SHARE = "ACCESS SHARE"
|
|
|
|
|
LOCK_ROW_SHARE = "ROW SHARE"
|
|
|
|
|
LOCK_ROW_EXCLUSIVE = "ROW EXCLUSIVE"
|
|
|
|
|
LOCK_SHARE_UPDATE_EXCLUSIVE = "SHARE UPDATE EXCLUSIVE"
|
|
|
|
|
LOCK_SHARE = "SHARE"
|
|
|
|
|
LOCK_SHARE_ROW_EXCLUSIVE = "SHARE ROW EXCLUSIVE"
|
|
|
|
|
LOCK_EXCLUSIVE = "EXCLUSIVE"
|
|
|
|
|
LOCK_ACCESS_EXCLUSIVE = "ACCESS EXCLUSIVE"
|
|
|
|
|
)
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// LockStatement interface for SQL LOCK statement
|
2019-06-04 12:10:23 +02:00
|
|
|
type LockStatement interface {
|
2019-05-12 18:15:23 +02:00
|
|
|
Statement
|
2019-05-07 13:44:30 +02:00
|
|
|
|
2019-06-15 13:58:45 +02:00
|
|
|
IN(lockMode TableLockMode) LockStatement
|
2019-06-04 12:10:23 +02:00
|
|
|
NOWAIT() LockStatement
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type lockStatementImpl struct {
|
2019-06-05 17:15:20 +02:00
|
|
|
tables []WritableTable
|
2019-06-15 13:58:45 +02:00
|
|
|
lockMode TableLockMode
|
2019-05-07 13:44:30 +02:00
|
|
|
nowait bool
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
// LOCK creates lock statement for list of tables.
|
2019-06-05 17:15:20 +02:00
|
|
|
func LOCK(tables ...WritableTable) LockStatement {
|
2019-05-07 13:44:30 +02:00
|
|
|
return &lockStatementImpl{
|
|
|
|
|
tables: tables,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-15 13:58:45 +02:00
|
|
|
func (l *lockStatementImpl) IN(lockMode TableLockMode) LockStatement {
|
2019-05-07 13:44:30 +02:00
|
|
|
l.lockMode = lockMode
|
|
|
|
|
return l
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-04 12:10:23 +02:00
|
|
|
func (l *lockStatementImpl) NOWAIT() LockStatement {
|
2019-05-07 13:44:30 +02:00
|
|
|
l.nowait = true
|
|
|
|
|
return l
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-28 14:57:02 +02:00
|
|
|
func (l *lockStatementImpl) DebugSql(dialect ...Dialect) (query string, err error) {
|
|
|
|
|
return debugSql(l, dialect...)
|
2019-05-12 18:15:23 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-28 14:57:02 +02:00
|
|
|
func (l *lockStatementImpl) accept(visitor visitor) {
|
|
|
|
|
visitor.visit(l)
|
|
|
|
|
|
|
|
|
|
for _, table := range l.tables {
|
|
|
|
|
table.accept(visitor)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (l *lockStatementImpl) Sql(dialect ...Dialect) (query string, args []interface{}, err error) {
|
2019-05-07 13:44:30 +02:00
|
|
|
if l == nil {
|
2019-07-18 17:43:11 +02:00
|
|
|
return "", nil, errors.New("jet: nil Statement")
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(l.tables) == 0 {
|
2019-07-18 17:43:11 +02:00
|
|
|
return "", nil, errors.New("jet: There is no table selected to be locked")
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-28 14:57:02 +02:00
|
|
|
out := &sqlBuilder{
|
|
|
|
|
dialect: detectDialect(l, dialect...),
|
|
|
|
|
}
|
2019-05-07 13:44:30 +02:00
|
|
|
|
2019-06-14 14:35:50 +02:00
|
|
|
out.newLine()
|
2019-05-12 18:15:23 +02:00
|
|
|
out.writeString("LOCK TABLE")
|
2019-05-07 13:44:30 +02:00
|
|
|
|
|
|
|
|
for i, table := range l.tables {
|
|
|
|
|
if i > 0 {
|
2019-05-08 13:47:01 +02:00
|
|
|
out.writeString(", ")
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-18 17:43:11 +02:00
|
|
|
err := table.serialize(lockStatement, out)
|
2019-05-07 13:44:30 +02:00
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", nil, err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if l.lockMode != "" {
|
2019-05-12 18:15:23 +02:00
|
|
|
out.writeString("IN")
|
2019-05-08 13:47:01 +02:00
|
|
|
out.writeString(string(l.lockMode))
|
2019-05-12 18:15:23 +02:00
|
|
|
out.writeString("MODE")
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if l.nowait {
|
2019-05-12 18:15:23 +02:00
|
|
|
out.writeString("NOWAIT")
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
2019-05-12 18:15:23 +02:00
|
|
|
query, args = out.finalize()
|
|
|
|
|
return
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-23 18:55:57 +02:00
|
|
|
func (l *lockStatementImpl) Query(db execution.DB, destination interface{}) error {
|
2019-06-29 16:58:41 +02:00
|
|
|
return query(l, db, destination)
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
|
|
|
|
|
2019-07-19 10:40:30 +02:00
|
|
|
func (l *lockStatementImpl) QueryContext(context context.Context, db execution.DB, destination interface{}) error {
|
2019-07-18 17:43:11 +02:00
|
|
|
return queryContext(context, l, db, destination)
|
2019-06-20 12:22:19 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-23 18:55:57 +02:00
|
|
|
func (l *lockStatementImpl) Exec(db execution.DB) (sql.Result, error) {
|
2019-06-29 16:58:41 +02:00
|
|
|
return exec(l, db)
|
2019-05-07 13:44:30 +02:00
|
|
|
}
|
2019-06-20 12:22:19 +02:00
|
|
|
|
2019-07-19 10:40:30 +02:00
|
|
|
func (l *lockStatementImpl) ExecContext(context context.Context, db execution.DB) (res sql.Result, err error) {
|
2019-07-19 10:46:41 +02:00
|
|
|
return execContext(context, l, db)
|
2019-06-20 12:22:19 +02:00
|
|
|
}
|