474 lines
13 KiB
Go
474 lines
13 KiB
Go
package jet
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
)
|
|
|
|
// LiteralExpression is representation of an escaped literal
|
|
type LiteralExpression interface {
|
|
Expression
|
|
|
|
Value() interface{}
|
|
SetConstant(constant bool)
|
|
}
|
|
|
|
type literalExpressionImpl struct {
|
|
ExpressionInterfaceImpl
|
|
|
|
value interface{}
|
|
constant bool
|
|
}
|
|
|
|
func literal(value interface{}, optionalConstant ...bool) *literalExpressionImpl {
|
|
exp := literalExpressionImpl{value: value}
|
|
|
|
if len(optionalConstant) > 0 {
|
|
exp.constant = optionalConstant[0]
|
|
}
|
|
|
|
exp.ExpressionInterfaceImpl.Root = &exp
|
|
|
|
return &exp
|
|
}
|
|
|
|
// Literal is injected directly to SQL query, and does not appear in parametrized argument list.
|
|
func Literal(value interface{}) *literalExpressionImpl {
|
|
exp := literal(value)
|
|
return exp
|
|
}
|
|
|
|
// FixedLiteral is injected directly to SQL query, and does not appear in parametrized argument list.
|
|
func FixedLiteral(value interface{}) *literalExpressionImpl {
|
|
exp := literal(value)
|
|
exp.constant = true
|
|
|
|
return exp
|
|
}
|
|
|
|
func (l *literalExpressionImpl) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
|
if l.constant {
|
|
out.insertConstantArgument(l.value)
|
|
} else {
|
|
out.insertParametrizedArgument(l.value)
|
|
}
|
|
}
|
|
|
|
func (l *literalExpressionImpl) Value() interface{} {
|
|
return l.value
|
|
}
|
|
|
|
func (l *literalExpressionImpl) SetConstant(constant bool) {
|
|
l.constant = constant
|
|
}
|
|
|
|
type integerLiteralExpression struct {
|
|
literalExpressionImpl
|
|
integerInterfaceImpl
|
|
}
|
|
|
|
func intLiteral(value interface{}) IntegerExpression {
|
|
numLiteral := &integerLiteralExpression{}
|
|
|
|
numLiteral.literalExpressionImpl = *literal(value)
|
|
|
|
numLiteral.literalExpressionImpl.Root = numLiteral
|
|
numLiteral.integerInterfaceImpl.root = numLiteral
|
|
|
|
return numLiteral
|
|
}
|
|
|
|
// Int creates a new 64 bit signed integer literal
|
|
func Int(value int64) IntegerExpression {
|
|
return intLiteral(value)
|
|
}
|
|
|
|
// Int8 creates a new 8 bit signed integer literal
|
|
func Int8(value int8) IntegerExpression {
|
|
return intLiteral(value)
|
|
}
|
|
|
|
// Int16 creates a new 16 bit signed integer literal
|
|
func Int16(value int16) IntegerExpression {
|
|
return intLiteral(value)
|
|
}
|
|
|
|
// Int32 creates a new 32 bit signed integer literal
|
|
func Int32(value int32) IntegerExpression {
|
|
return intLiteral(value)
|
|
}
|
|
|
|
// Uint8 creates a new 8 bit unsigned integer literal
|
|
func Uint8(value uint8) IntegerExpression {
|
|
return intLiteral(value)
|
|
}
|
|
|
|
// Uint16 creates a new 16 bit unsigned integer literal
|
|
func Uint16(value uint16) IntegerExpression {
|
|
return intLiteral(value)
|
|
}
|
|
|
|
// Uint32 creates a new 32 bit unsigned integer literal
|
|
func Uint32(value uint32) IntegerExpression {
|
|
return intLiteral(value)
|
|
}
|
|
|
|
// Uint64 creates a new 64 bit unsigned integer literal
|
|
func Uint64(value uint64) IntegerExpression {
|
|
return intLiteral(value)
|
|
}
|
|
|
|
// ---------------------------------------------------//
|
|
type boolLiteralExpression struct {
|
|
boolInterfaceImpl
|
|
literalExpressionImpl
|
|
}
|
|
|
|
// Bool creates new bool literal expression
|
|
func Bool(value bool) BoolExpression {
|
|
boolLiteralExpression := boolLiteralExpression{}
|
|
|
|
boolLiteralExpression.literalExpressionImpl = *literal(value)
|
|
boolLiteralExpression.boolInterfaceImpl.root = &boolLiteralExpression
|
|
|
|
return &boolLiteralExpression
|
|
}
|
|
|
|
// ---------------------------------------------------//
|
|
type floatLiteral struct {
|
|
floatInterfaceImpl
|
|
literalExpressionImpl
|
|
}
|
|
|
|
// Float creates new float literal from float64 value
|
|
func Float(value float64) FloatExpression {
|
|
floatLiteral := floatLiteral{}
|
|
floatLiteral.literalExpressionImpl = *literal(value)
|
|
|
|
floatLiteral.floatInterfaceImpl.root = &floatLiteral
|
|
|
|
return &floatLiteral
|
|
}
|
|
|
|
// Decimal creates new float literal from string value
|
|
func Decimal(value string) FloatExpression {
|
|
floatLiteral := floatLiteral{}
|
|
floatLiteral.literalExpressionImpl = *literal(value)
|
|
|
|
floatLiteral.floatInterfaceImpl.root = &floatLiteral
|
|
|
|
return &floatLiteral
|
|
}
|
|
|
|
// ---------------------------------------------------//
|
|
type stringLiteral struct {
|
|
stringInterfaceImpl
|
|
literalExpressionImpl
|
|
}
|
|
|
|
// String creates new string literal expression
|
|
func String(value string) StringExpression {
|
|
stringLiteral := stringLiteral{}
|
|
stringLiteral.literalExpressionImpl = *literal(value)
|
|
|
|
stringLiteral.stringInterfaceImpl.root = &stringLiteral
|
|
|
|
return &stringLiteral
|
|
}
|
|
|
|
//---------------------------------------------------//
|
|
|
|
type timeLiteral struct {
|
|
timeInterfaceImpl
|
|
literalExpressionImpl
|
|
}
|
|
|
|
// Time creates new time literal expression
|
|
func Time(hour, minute, second int, nanoseconds ...time.Duration) TimeExpression {
|
|
timeLiteral := &timeLiteral{}
|
|
timeStr := fmt.Sprintf("%02d:%02d:%02d", hour, minute, second)
|
|
timeStr += formatNanoseconds(nanoseconds...)
|
|
timeLiteral.literalExpressionImpl = *literal(timeStr)
|
|
|
|
timeLiteral.timeInterfaceImpl.root = timeLiteral
|
|
|
|
return timeLiteral
|
|
}
|
|
|
|
// TimeT creates new time literal expression from time.Time object
|
|
func TimeT(t time.Time) TimeExpression {
|
|
timeLiteral := &timeLiteral{}
|
|
timeLiteral.literalExpressionImpl = *literal(t)
|
|
timeLiteral.timeInterfaceImpl.root = timeLiteral
|
|
|
|
return timeLiteral
|
|
}
|
|
|
|
//---------------------------------------------------//
|
|
|
|
type timezLiteral struct {
|
|
timezInterfaceImpl
|
|
literalExpressionImpl
|
|
}
|
|
|
|
// Timez creates new time with time zone literal expression
|
|
func Timez(hour, minute, second int, nanoseconds time.Duration, timezone string) TimezExpression {
|
|
timezLiteral := timezLiteral{}
|
|
timeStr := fmt.Sprintf("%02d:%02d:%02d", hour, minute, second)
|
|
timeStr += formatNanoseconds(nanoseconds)
|
|
timeStr += " " + timezone
|
|
timezLiteral.literalExpressionImpl = *literal(timeStr)
|
|
|
|
return TimezExp(literal(timeStr))
|
|
}
|
|
|
|
// TimezT creates new time with time zone literal expression from time.Time object
|
|
func TimezT(t time.Time) TimezExpression {
|
|
timeLiteral := &timezLiteral{}
|
|
timeLiteral.literalExpressionImpl = *literal(t)
|
|
timeLiteral.timezInterfaceImpl.root = timeLiteral
|
|
|
|
return timeLiteral
|
|
}
|
|
|
|
//---------------------------------------------------//
|
|
|
|
type timestampLiteral struct {
|
|
timestampInterfaceImpl
|
|
literalExpressionImpl
|
|
}
|
|
|
|
// Timestamp creates new timestamp literal expression
|
|
func Timestamp(year int, month time.Month, day, hour, minute, second int, nanoseconds ...time.Duration) TimestampExpression {
|
|
timestamp := ×tampLiteral{}
|
|
timeStr := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
|
timeStr += formatNanoseconds(nanoseconds...)
|
|
timestamp.literalExpressionImpl = *literal(timeStr)
|
|
timestamp.timestampInterfaceImpl.root = timestamp
|
|
return timestamp
|
|
}
|
|
|
|
// TimestampT creates new timestamp literal expression from time.Time object
|
|
func TimestampT(t time.Time) TimestampExpression {
|
|
timestamp := ×tampLiteral{}
|
|
timestamp.literalExpressionImpl = *literal(t)
|
|
timestamp.timestampInterfaceImpl.root = timestamp
|
|
return timestamp
|
|
}
|
|
|
|
//---------------------------------------------------//
|
|
|
|
type timestampzLiteral struct {
|
|
timestampzInterfaceImpl
|
|
literalExpressionImpl
|
|
}
|
|
|
|
// Timestampz creates new timestamp with time zone literal expression
|
|
func Timestampz(year int, month time.Month, day, hour, minute, second int, nanoseconds time.Duration, timezone string) TimestampzExpression {
|
|
timestamp := ×tampzLiteral{}
|
|
timeStr := fmt.Sprintf("%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second)
|
|
timeStr += formatNanoseconds(nanoseconds)
|
|
timeStr += " " + timezone
|
|
|
|
timestamp.literalExpressionImpl = *literal(timeStr)
|
|
timestamp.timestampzInterfaceImpl.root = timestamp
|
|
return timestamp
|
|
}
|
|
|
|
// TimestampzT creates new timestamp literal expression from time.Time object
|
|
func TimestampzT(t time.Time) TimestampzExpression {
|
|
timestamp := ×tampzLiteral{}
|
|
timestamp.literalExpressionImpl = *literal(t)
|
|
timestamp.timestampzInterfaceImpl.root = timestamp
|
|
return timestamp
|
|
}
|
|
|
|
//---------------------------------------------------//
|
|
|
|
type dateLiteral struct {
|
|
dateInterfaceImpl
|
|
literalExpressionImpl
|
|
}
|
|
|
|
// Date creates new date literal expression
|
|
func Date(year int, month time.Month, day int) DateExpression {
|
|
dateLiteral := &dateLiteral{}
|
|
|
|
timeStr := fmt.Sprintf("%04d-%02d-%02d", year, month, day)
|
|
dateLiteral.literalExpressionImpl = *literal(timeStr)
|
|
dateLiteral.dateInterfaceImpl.root = dateLiteral
|
|
|
|
return dateLiteral
|
|
}
|
|
|
|
// DateT creates new date literal expression from time.Time object
|
|
func DateT(t time.Time) DateExpression {
|
|
dateLiteral := &dateLiteral{}
|
|
dateLiteral.literalExpressionImpl = *literal(t)
|
|
dateLiteral.dateInterfaceImpl.root = dateLiteral
|
|
|
|
return dateLiteral
|
|
}
|
|
|
|
func formatNanoseconds(nanoseconds ...time.Duration) string {
|
|
if len(nanoseconds) > 0 && nanoseconds[0] != 0 {
|
|
duration := fmt.Sprintf("%09d", nanoseconds[0])
|
|
i := len(duration) - 1
|
|
for ; i >= 3; i-- {
|
|
if duration[i] != '0' {
|
|
break
|
|
}
|
|
}
|
|
|
|
return "." + duration[0:i+1]
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
//--------------------------------------------------//
|
|
|
|
var (
|
|
// NULL is jet equivalent of SQL NULL
|
|
NULL = newNullLiteral()
|
|
// STAR is jet equivalent of SQL *
|
|
STAR = newStarLiteral()
|
|
// PLUS_INFINITY is jet equivalent for sql infinity
|
|
PLUS_INFINITY = String("infinity")
|
|
// MINUS_INFINITY is jet equivalent for sql -infinity
|
|
MINUS_INFINITY = String("-infinity")
|
|
)
|
|
|
|
type nullLiteral struct {
|
|
ExpressionInterfaceImpl
|
|
}
|
|
|
|
func newNullLiteral() Expression {
|
|
nullExpression := &nullLiteral{}
|
|
|
|
nullExpression.ExpressionInterfaceImpl.Root = nullExpression
|
|
|
|
return nullExpression
|
|
}
|
|
|
|
func (n *nullLiteral) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
|
out.WriteString("NULL")
|
|
}
|
|
|
|
// --------------------------------------------------//
|
|
type starLiteral struct {
|
|
ExpressionInterfaceImpl
|
|
}
|
|
|
|
func newStarLiteral() Expression {
|
|
starExpression := &starLiteral{}
|
|
|
|
starExpression.ExpressionInterfaceImpl.Root = starExpression
|
|
|
|
return starExpression
|
|
}
|
|
|
|
func (n *starLiteral) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
|
out.WriteString("*")
|
|
}
|
|
|
|
//---------------------------------------------------//
|
|
|
|
type rawExpression struct {
|
|
ExpressionInterfaceImpl
|
|
|
|
Raw string
|
|
NamedArgument map[string]interface{}
|
|
noWrap bool
|
|
}
|
|
|
|
func (n *rawExpression) serialize(statement StatementType, out *SQLBuilder, options ...SerializeOption) {
|
|
if !n.noWrap && !contains(options, NoWrap) {
|
|
out.WriteByte('(')
|
|
}
|
|
|
|
out.insertRawQuery(n.Raw, n.NamedArgument)
|
|
|
|
if !n.noWrap && !contains(options, NoWrap) {
|
|
out.WriteByte(')')
|
|
}
|
|
}
|
|
|
|
// Raw can be used for any unsupported functions, operators or expressions.
|
|
// For example: Raw("current_database()")
|
|
func Raw(raw string, namedArgs ...map[string]interface{}) Expression {
|
|
var namedArguments map[string]interface{}
|
|
|
|
if len(namedArgs) > 0 {
|
|
namedArguments = namedArgs[0]
|
|
}
|
|
|
|
rawExp := &rawExpression{
|
|
Raw: raw,
|
|
NamedArgument: namedArguments,
|
|
}
|
|
rawExp.ExpressionInterfaceImpl.Root = rawExp
|
|
|
|
return rawExp
|
|
}
|
|
|
|
// RawBool helper that for raw string boolean expressions
|
|
func RawBool(raw string, namedArgs ...map[string]interface{}) BoolExpression {
|
|
return BoolExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawInt helper that for integer expressions
|
|
func RawInt(raw string, namedArgs ...map[string]interface{}) IntegerExpression {
|
|
return IntExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawFloat helper that for float expressions
|
|
func RawFloat(raw string, namedArgs ...map[string]interface{}) FloatExpression {
|
|
return FloatExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawString helper that for string expressions
|
|
func RawString(raw string, namedArgs ...map[string]interface{}) StringExpression {
|
|
return StringExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawTime helper that for time expressions
|
|
func RawTime(raw string, namedArgs ...map[string]interface{}) TimeExpression {
|
|
return TimeExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawTimez helper that for time with time zone expressions
|
|
func RawTimez(raw string, namedArgs ...map[string]interface{}) TimezExpression {
|
|
return TimezExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawTimestamp helper that for timestamp expressions
|
|
func RawTimestamp(raw string, namedArgs ...map[string]interface{}) TimestampExpression {
|
|
return TimestampExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawTimestampz helper that for timestamp with time zone expressions
|
|
func RawTimestampz(raw string, namedArgs ...map[string]interface{}) TimestampzExpression {
|
|
return TimestampzExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawDate helper that for date expressions
|
|
func RawDate(raw string, namedArgs ...map[string]interface{}) DateExpression {
|
|
return DateExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawBlob is raw query helper that for blob expressions
|
|
func RawBlob(raw string, namedArgs ...map[string]interface{}) BlobExpression {
|
|
return BlobExp(Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// RawRange helper that for range expressions
|
|
func RawRange[T Expression](raw string, namedArgs ...map[string]interface{}) Range[T] {
|
|
return RangeExp[T](Raw(raw, namedArgs...))
|
|
}
|
|
|
|
// UUID is a helper function to create string literal expression from uuid object
|
|
// value can be any uuid type with a String method
|
|
func UUID(value fmt.Stringer) StringExpression {
|
|
return String(value.String())
|
|
}
|