github.com/aacfactory/fns-contrib/databases/sql@v1.2.84/dac/specifications/dialect.go (about)

     1  package specifications
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/aacfactory/errors"
     6  	"github.com/aacfactory/fns-contrib/databases/sql"
     7  	"github.com/aacfactory/fns/context"
     8  	"io"
     9  )
    10  
    11  var (
    12  	SELECT    = []byte("SELECT")
    13  	FROM      = []byte("FROM")
    14  	WHERE     = []byte("WHERE")
    15  	INSERT    = []byte("INSERT")
    16  	UPDATE    = []byte("UPDATE")
    17  	DELETE    = []byte("DELETE")
    18  	SPACE     = []byte(" ")
    19  	INTO      = []byte("INTO")
    20  	AND       = []byte("AND")
    21  	SET       = []byte("SET")
    22  	EQ        = []byte("=")
    23  	PLUS      = []byte("+")
    24  	AT        = []byte("@")
    25  	LB        = []byte("(")
    26  	RB        = []byte(")")
    27  	COMMA     = []byte(", ")
    28  	DOT       = []byte(".")
    29  	STAR      = []byte("*")
    30  	AS        = []byte("AS")
    31  	VALUES    = []byte("VALUES")
    32  	EXISTS    = []byte("EXISTS")
    33  	COUNT     = []byte("COUNT")
    34  	NOT       = []byte("NOT")
    35  	CONFLICT  = []byte("CONFLICT")
    36  	ON        = []byte("ON")
    37  	RETURNING = []byte("RETURNING")
    38  	DO        = []byte("DO")
    39  	NOTHING   = []byte("NOTHING")
    40  	ORDER     = []byte("ORDER")
    41  	BY        = []byte("BY")
    42  	DESC      = []byte("DESC")
    43  	GROUP     = []byte("GROUP")
    44  	HAVING    = []byte("HAVING")
    45  	OFFSET    = []byte("OFFSET")
    46  	LIMIT     = []byte("LIMIT")
    47  )
    48  
    49  const (
    50  	QueryMethod Method = iota + 1
    51  	ExecuteMethod
    52  )
    53  
    54  type Method int
    55  
    56  type QueryPlaceholder interface {
    57  	Next() (v string)
    58  	SkipCursor(n int)
    59  	Current() (v string)
    60  }
    61  
    62  type Render interface {
    63  	Render(ctx Context, w io.Writer) (argument []any, err error)
    64  }
    65  
    66  type Dialect interface {
    67  	Name() string
    68  	FormatIdent(ident string) string
    69  	QueryPlaceholder() QueryPlaceholder
    70  	Insert(ctx Context, spec *Specification, values int) (method Method, query []byte, fields []string, returning []string, err error)
    71  	InsertOrUpdate(ctx Context, spec *Specification) (method Method, query []byte, fields []string, returning []string, err error)
    72  	InsertWhenExist(ctx Context, spec *Specification, src QueryExpr) (method Method, query []byte, fields []string, arguments []any, returning []string, err error)
    73  	InsertWhenNotExist(ctx Context, spec *Specification, src QueryExpr) (method Method, query []byte, fields []string, arguments []any, returning []string, err error)
    74  	Update(ctx Context, spec *Specification) (method Method, query []byte, fields []string, err error)
    75  	UpdateFields(ctx Context, spec *Specification, fields []FieldValue, cond Condition) (method Method, query []byte, arguments []any, err error)
    76  	Delete(ctx Context, spec *Specification) (method Method, query []byte, fields []string, err error)
    77  	DeleteByConditions(ctx Context, spec *Specification, cond Condition) (method Method, query []byte, audits []string, arguments []any, err error)
    78  	Exist(ctx Context, spec *Specification, cond Condition) (method Method, query []byte, arguments []any, err error)
    79  	Count(ctx Context, spec *Specification, cond Condition) (method Method, query []byte, arguments []any, err error)
    80  	Query(ctx Context, spec *Specification, cond Condition, orders Orders, offset int, length int) (method Method, query []byte, arguments []any, fields []string, err error)
    81  	View(ctx Context, spec *Specification, cond Condition, orders Orders, groupBy GroupBy, offset int, length int) (method Method, query []byte, arguments []any, fields []string, err error)
    82  }
    83  
    84  var (
    85  	dialects = make([]Dialect, 0, 1)
    86  )
    87  
    88  func RegisterDialect(dialect Dialect) {
    89  	if dialect == nil {
    90  		return
    91  	}
    92  	name := dialect.Name()
    93  	if _, has := getDialect(name); has {
    94  		panic(fmt.Errorf("%+v", errors.Warning(fmt.Sprintf("sql: %s dialect has registered", name))))
    95  		return
    96  	}
    97  	dialects = append(dialects, dialect)
    98  }
    99  
   100  func getDialect(name string) (dialect Dialect, has bool) {
   101  	for _, d := range dialects {
   102  		if d.Name() == name {
   103  			dialect = d
   104  			has = true
   105  			return
   106  		}
   107  	}
   108  	return
   109  }
   110  
   111  func LoadDialect(ctx context.Context) (dialect Dialect, err error) {
   112  	name, nameErr := sql.Dialect(ctx)
   113  	if nameErr != nil {
   114  		err = errors.Warning("sql: load dialect failed").WithCause(nameErr)
   115  		return
   116  	}
   117  	has := name != ""
   118  	if has {
   119  		dialect, has = getDialect(name)
   120  		if !has {
   121  			err = errors.Warning("sql: load dialect failed").WithCause(fmt.Errorf("%s was not found", name))
   122  			return
   123  		}
   124  		return
   125  	}
   126  	dialect, has = defaultDialect()
   127  	if !has {
   128  		err = errors.Warning("sql: load dialect failed").WithCause(fmt.Errorf("no dialect was registerd"))
   129  		return
   130  	}
   131  	return
   132  }
   133  
   134  func defaultDialect() (dialect Dialect, has bool) {
   135  	if len(dialects) == 0 {
   136  		return
   137  	}
   138  	dialect = dialects[0]
   139  	has = true
   140  	return
   141  }