Add support for blob expressions.

This commit is contained in:
go-jet 2025-02-28 18:23:15 +01:00
parent 26e478dc7e
commit c94216ab0e
37 changed files with 1296 additions and 81 deletions

View file

@ -101,9 +101,9 @@ func (b *cast) AS_DECIMAL() FloatExpression {
return FloatExp(b.AS("decimal"))
}
// AS_BYTEA casts expression AS text type
func (b *cast) AS_BYTEA() StringExpression {
return StringExp(b.AS("bytea"))
// AS_BYTEA casts expression AS bytea type
func (b *cast) AS_BYTEA() ByteaExpression {
return ByteaExp(b.AS("bytea"))
}
// AS_TIME casts expression AS date type

View file

@ -23,6 +23,12 @@ type ColumnString = jet.ColumnString
// StringColumn creates named string column.
var StringColumn = jet.StringColumn
// ColumnBytea is interface for bytea columns
type ColumnBytea = jet.ColumnBlob
// ByteaColumn creates new named bytea column.
var ByteaColumn = jet.BlobColumn
// ColumnInteger is interface for SQL smallint, integer, bigint columns.
type ColumnInteger = jet.ColumnInteger

View file

@ -1,6 +1,7 @@
package postgres
import (
"encoding/hex"
"fmt"
"strconv"
@ -26,7 +27,8 @@ func newDialect() jet.Dialect {
ArgumentPlaceholder: func(ord int) string {
return "$" + strconv.Itoa(ord)
},
ReservedWords: reservedWords,
ArgumentToString: argumentToString,
ReservedWords: reservedWords,
ValuesDefaultColumnName: func(index int) string {
return fmt.Sprintf("column%d", index+1)
},
@ -35,6 +37,15 @@ func newDialect() jet.Dialect {
return jet.NewDialect(dialectParams)
}
func argumentToString(value any) (string, bool) {
switch bindVal := value.(type) {
case []byte:
return fmt.Sprintf("'\\x%s'", hex.EncodeToString(bindVal)), true
}
return "", false
}
func postgresCAST(expressions ...jet.Serializer) jet.SerializerFunc {
return func(statement jet.StatementType, out *jet.SQLBuilder, options ...jet.SerializeOption) {
if len(expressions) < 2 {

View file

@ -12,6 +12,8 @@ type BoolExpression = jet.BoolExpression
// StringExpression interface
type StringExpression = jet.StringExpression
type ByteaExpression = jet.BlobExpression
// NumericExpression interface
type NumericExpression = jet.NumericExpression
@ -82,6 +84,11 @@ var TimeExp = jet.TimeExp
// Does not add sql cast to generated sql builder output.
var StringExp = jet.StringExp
// ByteaExp is blob expression wrapper around arbitrary expression.
// Allows go compiler to see any expression as string expression.
// Does not add sql cast to generated sql builder output.
var ByteaExp = jet.BlobExp
// TimezExp is time with time zone expression wrapper around arbitrary expression.
// Allows go compiler to see any expression as time with time zone expression.
// Does not add sql cast to generated sql builder output.
@ -134,15 +141,17 @@ type RawArgs = map[string]interface{}
var (
Raw = jet.Raw
RawBool = jet.RawBool
RawInt = jet.RawInt
RawFloat = jet.RawFloat
RawString = jet.RawString
RawTime = jet.RawTime
RawTimez = jet.RawTimez
RawTimestamp = jet.RawTimestamp
RawTimestampz = jet.RawTimestampz
RawDate = jet.RawDate
RawBool = jet.RawBool
RawInt = jet.RawInt
RawFloat = jet.RawFloat
RawString = jet.RawString
RawTime = jet.RawTime
RawTimez = jet.RawTimez
RawTimestamp = jet.RawTimestamp
RawTimestampz = jet.RawTimestampz
RawDate = jet.RawDate
RawBytea = jet.RawBlob
RawNumRange = jet.RawRange[jet.NumericExpression]
RawInt4Range = jet.RawRange[jet.Int4Expression]
RawInt8Range = jet.RawRange[jet.Int8Expression]

View file

@ -192,9 +192,27 @@ func CONCAT_WS(separator Expression, expressions ...Expression) StringExpression
return jet.CONCAT_WS(explicitLiteralCast(separator), explicitLiteralCasts(expressions...)...)
}
// Character encodings for CONVERT, CONVERT_FROM and CONVERT_TO functions
var (
UTF8 = String("UTF8")
LATIN1 = String("LATIN1")
LATIN2 = String("LATIN2")
LATIN3 = String("LATIN3")
LATIN4 = String("LATIN4")
WIN1252 = String("WIN1252")
ISO_8859_5 = String("ISO_8859_5")
ISO_8859_6 = String("ISO_8859_6")
ISO_8859_7 = String("ISO_8859_7")
ISO_8859_8 = String("ISO_8859_8")
KOI8R = String("KOI8R")
KOI8U = String("KOI8U")
)
// CONVERT converts string to dest_encoding. The original encoding is
// specified by src_encoding. The string must be valid in this encoding.
var CONVERT = jet.CONVERT
func CONVERT(str ByteaExpression, srcEncoding StringExpression, destEncoding StringExpression) ByteaExpression {
return jet.CONVERT(str, srcEncoding, destEncoding)
}
// CONVERT_FROM converts string to the database encoding. The original
// encoding is specified by src_encoding. The string must be valid in this encoding.
@ -203,6 +221,13 @@ var CONVERT_FROM = jet.CONVERT_FROM
// CONVERT_TO converts string to dest_encoding.
var CONVERT_TO = jet.CONVERT_TO
// ENCODE/DECODE textual formats
var (
Base64 StringExpression = String("base64")
Escape StringExpression = String("escape")
Hex StringExpression = String("hex")
)
// ENCODE encodes binary data into a textual representation.
// Supported formats are: base64, hex, escape. escape converts zero bytes and
// high-bit-set bytes to octal sequences (\nnn) and doubles backslashes.
@ -212,7 +237,7 @@ var ENCODE = jet.ENCODE
// Options for format are same as in encode.
var DECODE = jet.DECODE
// FORMAT formats a number to a format like "#,###,###.##", rounded to a specified number of decimal places, then it returns the result as a string.
// FORMAT formats the arguments according to a format string. This function is similar to the C function sprintf.
func FORMAT(formatStr StringExpression, formatArgs ...Expression) StringExpression {
return jet.FORMAT(formatStr, explicitLiteralCasts(formatArgs...)...)
}
@ -242,6 +267,49 @@ var LPAD = jet.LPAD
// fill (a space by default). If the string is already longer than length then it is truncated.
var RPAD = jet.RPAD
// BIT_COUNT returns the number of bits set in the binary string (also known as “popcount”).
var BIT_COUNT = jet.BIT_COUNT
// GET_BIT extracts n'th bit from binary string.
func GET_BIT(bytes ByteaExpression, n IntegerExpression) IntegerExpression {
return IntExp(Func("GET_BIT", bytes, n))
}
// GET_BYTE extracts n'th byte from binary string.
func GET_BYTE(bytes ByteaExpression, n IntegerExpression) IntegerExpression {
return IntExp(Func("GET_BYTE", bytes, n))
}
// SET_BIT sets n'th bit in binary string to newvalue.
func SET_BIT(bytes ByteaExpression, n IntegerExpression, newValue IntegerExpression) ByteaExpression {
return ByteaExp(Func("SET_BIT", bytes, n, newValue))
}
// SET_BYTE sets n'th byte in binary string to newvalue.
func SET_BYTE(bytes ByteaExpression, n IntegerExpression, newValue IntegerExpression) ByteaExpression {
return ByteaExp(Func("SET_BYTE", bytes, n, newValue))
}
// SHA224 computes the SHA-224 hash of the binary string.
func SHA224(bytes ByteaExpression) ByteaExpression {
return ByteaExp(Func("SHA224", bytes))
}
// SHA256 computes the SHA-256 hash of the binary string.
func SHA256(bytes ByteaExpression) ByteaExpression {
return ByteaExp(Func("SHA256", bytes))
}
// SHA384 computes the SHA-384 hash of the binary string.
func SHA384(bytes ByteaExpression) ByteaExpression {
return ByteaExp(Func("SHA384", bytes))
}
// SHA512 computes the SHA-512 hash of the binary string.
func SHA512(bytes ByteaExpression) ByteaExpression {
return ByteaExp(Func("SHA512", bytes))
}
// MD5 calculates the MD5 hash of string, returning the result in hexadecimal
var MD5 = jet.MD5

View file

@ -122,7 +122,7 @@ func Json(value interface{}) StringExpression {
var UUID = jet.UUID
// Bytea creates new bytea literal expression
func Bytea(value interface{}) StringExpression {
func Bytea(value interface{}) ByteaExpression {
switch value.(type) {
case string, []byte:
default: