fork github.com/doug-martin
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
package sqlgen
|
||||
|
||||
import (
|
||||
"git.fsdpf.net/go/db/v2/exp"
|
||||
"git.fsdpf.net/go/db/v2/internal/errors"
|
||||
"git.fsdpf.net/go/db/v2/internal/sb"
|
||||
)
|
||||
|
||||
var ErrNoUpdatedValuesProvided = errors.New("no update values provided")
|
||||
|
||||
func ErrCTENotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support CTE WITH clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func ErrRecursiveCTENotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support CTE WITH RECURSIVE clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func ErrReturnNotSupported(dialect string) error {
|
||||
return errors.New("dialect does not support RETURNING clause [dialect=%s]", dialect)
|
||||
}
|
||||
|
||||
func ErrNotSupportedFragment(sqlType string, f SQLFragmentType) error {
|
||||
return errors.New("unsupported %s SQL fragment %s", sqlType, f)
|
||||
}
|
||||
|
||||
type (
|
||||
CommonSQLGenerator interface {
|
||||
Dialect() string
|
||||
DialectOptions() *SQLDialectOptions
|
||||
ExpressionSQLGenerator() ExpressionSQLGenerator
|
||||
ReturningSQL(b sb.SQLBuilder, returns exp.ColumnListExpression)
|
||||
FromSQL(b sb.SQLBuilder, from exp.ColumnListExpression)
|
||||
SourcesSQL(b sb.SQLBuilder, from exp.ColumnListExpression)
|
||||
WhereSQL(b sb.SQLBuilder, where exp.ExpressionList)
|
||||
OrderSQL(b sb.SQLBuilder, order exp.ColumnListExpression)
|
||||
OrderWithOffsetFetchSQL(b sb.SQLBuilder, order exp.ColumnListExpression, offset uint, limit interface{})
|
||||
LimitSQL(b sb.SQLBuilder, limit interface{})
|
||||
UpdateExpressionSQL(b sb.SQLBuilder, updates ...exp.UpdateExpression)
|
||||
}
|
||||
commonSQLGenerator struct {
|
||||
dialect string
|
||||
esg ExpressionSQLGenerator
|
||||
dialectOptions *SQLDialectOptions
|
||||
}
|
||||
)
|
||||
|
||||
func NewCommonSQLGenerator(dialect string, do *SQLDialectOptions) CommonSQLGenerator {
|
||||
return &commonSQLGenerator{dialect: dialect, esg: NewExpressionSQLGenerator(dialect, do), dialectOptions: do}
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) Dialect() string {
|
||||
return csg.dialect
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) DialectOptions() *SQLDialectOptions {
|
||||
return csg.dialectOptions
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) ExpressionSQLGenerator() ExpressionSQLGenerator {
|
||||
return csg.esg
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) ReturningSQL(b sb.SQLBuilder, returns exp.ColumnListExpression) {
|
||||
if returns != nil && len(returns.Columns()) > 0 {
|
||||
if csg.dialectOptions.SupportsReturn {
|
||||
b.Write(csg.dialectOptions.ReturningFragment)
|
||||
csg.esg.Generate(b, returns)
|
||||
} else {
|
||||
b.SetError(ErrReturnNotSupported(csg.dialect))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the FROM clause and tables to an sql statement
|
||||
func (csg *commonSQLGenerator) FromSQL(b sb.SQLBuilder, from exp.ColumnListExpression) {
|
||||
if from != nil && !from.IsEmpty() {
|
||||
b.Write(csg.dialectOptions.FromFragment)
|
||||
csg.SourcesSQL(b, from)
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the generates the SQL for a column list
|
||||
func (csg *commonSQLGenerator) SourcesSQL(b sb.SQLBuilder, from exp.ColumnListExpression) {
|
||||
b.WriteRunes(csg.dialectOptions.SpaceRune)
|
||||
csg.esg.Generate(b, from)
|
||||
}
|
||||
|
||||
// Generates the WHERE clause for an SQL statement
|
||||
func (csg *commonSQLGenerator) WhereSQL(b sb.SQLBuilder, where exp.ExpressionList) {
|
||||
if where != nil && !where.IsEmpty() {
|
||||
b.Write(csg.dialectOptions.WhereFragment)
|
||||
csg.esg.Generate(b, where)
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the ORDER BY clause for an SQL statement
|
||||
func (csg *commonSQLGenerator) OrderSQL(b sb.SQLBuilder, order exp.ColumnListExpression) {
|
||||
if order != nil && len(order.Columns()) > 0 {
|
||||
b.Write(csg.dialectOptions.OrderByFragment)
|
||||
csg.esg.Generate(b, order)
|
||||
}
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) OrderWithOffsetFetchSQL(
|
||||
b sb.SQLBuilder,
|
||||
order exp.ColumnListExpression,
|
||||
offset uint,
|
||||
limit interface{},
|
||||
) {
|
||||
if order == nil {
|
||||
return
|
||||
}
|
||||
|
||||
csg.OrderSQL(b, order)
|
||||
if offset > 0 {
|
||||
b.Write(csg.dialectOptions.OffsetFragment)
|
||||
csg.esg.Generate(b, offset)
|
||||
b.Write([]byte(" ROWS"))
|
||||
|
||||
if limit != nil {
|
||||
b.Write(csg.dialectOptions.FetchFragment)
|
||||
csg.esg.Generate(b, limit)
|
||||
b.Write([]byte(" ROWS ONLY"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates the LIMIT clause for an SQL statement
|
||||
func (csg *commonSQLGenerator) LimitSQL(b sb.SQLBuilder, limit interface{}) {
|
||||
if limit != nil {
|
||||
b.Write(csg.dialectOptions.LimitFragment)
|
||||
if csg.dialectOptions.SurroundLimitWithParentheses {
|
||||
b.WriteRunes(csg.dialectOptions.LeftParenRune)
|
||||
}
|
||||
csg.esg.Generate(b, limit)
|
||||
if csg.dialectOptions.SurroundLimitWithParentheses {
|
||||
b.WriteRunes(csg.dialectOptions.RightParenRune)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (csg *commonSQLGenerator) UpdateExpressionSQL(b sb.SQLBuilder, updates ...exp.UpdateExpression) {
|
||||
if len(updates) == 0 {
|
||||
b.SetError(ErrNoUpdatedValuesProvided)
|
||||
return
|
||||
}
|
||||
updateLen := len(updates)
|
||||
for i, update := range updates {
|
||||
csg.esg.Generate(b, update)
|
||||
if i < updateLen-1 {
|
||||
b.WriteRunes(csg.dialectOptions.CommaRune)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user