diff --git a/backends.go b/backends.go index 16253f3..4b0eafa 100644 --- a/backends.go +++ b/backends.go @@ -123,6 +123,8 @@ type IBackend interface { DATE_FORMAT(name string, field IQueryField, format string) IQueryField // INET_ATON INET_ATON(field IQueryField) IQueryField + // INET6_ATON + INET6_ATON(field IQueryField) IQueryField // AND_Val AND_Val(name string, field IQueryField, v interface{}) IQueryField // OR_Val diff --git a/backends/dameng/functions.go b/backends/dameng/functions.go index ed534cc..46d161b 100644 --- a/backends/dameng/functions.go +++ b/backends/dameng/functions.go @@ -31,7 +31,7 @@ func (dameng *SDamengBackend) GROUP_CONCAT2(name string, sep string, field sqlch // INET_ATON represents the SQL function INET_ATON func (dameng *SDamengBackend) INET_ATON(field sqlchemy.IQueryField) sqlchemy.IQueryField { - expr := "" + /*expr := "" vars := make([]sqlchemy.IQueryField, 0) expr += `TO_NUMBER(SUBSTR(%s,1,INSTR(%s,'.')-1))*POWER(256,3)+` vars = append(vars, field, field) @@ -41,7 +41,8 @@ func (dameng *SDamengBackend) INET_ATON(field sqlchemy.IQueryField) sqlchemy.IQu vars = append(vars, field, field, field, field) expr += `TO_NUMBER(SUBSTR(%s,INSTR(%s,'.',1,3)+1))` vars = append(vars, field, field) - return sqlchemy.NewFunctionField("", false, expr, vars...) + return sqlchemy.NewFunctionField("", false, expr, vars...)*/ + return sqlchemy.NewFunctionField("", false, `HEX(SF_INET_SORT(%s))`, field) } // cast field to string @@ -58,3 +59,8 @@ func (dameng *SDamengBackend) CASTInt(field sqlchemy.IQueryField, fieldname stri func (dameng *SDamengBackend) CASTFloat(field sqlchemy.IQueryField, fieldname string) sqlchemy.IQueryField { return sqlchemy.NewFunctionField(fieldname, false, `CAST(%s AS REAL)`, field) } + +// INET6_ATON represents a SQL function INET6_ATON +func (dameng *SDamengBackend) INET6_ATON(field sqlchemy.IQueryField) sqlchemy.IQueryField { + return sqlchemy.NewFunctionField("", false, `HEX(SF_INET_SORT(%s))`, field) +} diff --git a/backends/dameng/query_test.go b/backends/dameng/query_test.go index 96a0bab..8462df5 100644 --- a/backends/dameng/query_test.go +++ b/backends/dameng/query_test.go @@ -103,14 +103,21 @@ func TestQuery(t *testing.T) { t.Run("query INET_ATON func", func(t *testing.T) { testReset() q := testTable.Query(testTable.Field("col1"), sqlchemy.INET_ATON(testTable.Field("col0")).Label("ipaddr")) - want := `SELECT "t1"."col1" AS "col1", TO_NUMBER(SUBSTR("t1"."col0",1,INSTR("t1"."col0",'.')-1))*POWER(256,3)+TO_NUMBER(SUBSTR("t1"."col0",INSTR("t1"."col0",'.')+1,INSTR("t1"."col0",'.',1,2)-INSTR("t1"."col0",'.')-1))*POWER(256,2)+TO_NUMBER(SUBSTR("t1"."col0",INSTR("t1"."col0",'.',1,2)+1,INSTR("t1"."col0",'.',1,3)-INSTR("t1"."col0",'.',1,2)-1))*256+TO_NUMBER(SUBSTR("t1"."col0",INSTR("t1"."col0",'.',1,3)+1)) AS "ipaddr" FROM "test" AS "t1"` + want := `SELECT "t1"."col1" AS "col1", HEX(SF_INET_SORT("t1"."col0")) AS "ipaddr" FROM "test" AS "t1"` testGotWant(t, q.String(), want) }) t.Run("query INET_ATON func by group", func(t *testing.T) { testReset() q := testTable.Query(testTable.Field("col1").Label("number"), sqlchemy.INET_ATON(testTable.Field("col0")).Label("ipaddr"), sqlchemy.NewConstField(123456).Label("gateway")).GroupBy(testTable.Field("col0")) - want := `SELECT MAX("t1"."col1") AS "number", MAX(TO_NUMBER(SUBSTR("t1"."col0",1,INSTR("t1"."col0",'.')-1))*POWER(256,3)+TO_NUMBER(SUBSTR("t1"."col0",INSTR("t1"."col0",'.')+1,INSTR("t1"."col0",'.',1,2)-INSTR("t1"."col0",'.')-1))*POWER(256,2)+TO_NUMBER(SUBSTR("t1"."col0",INSTR("t1"."col0",'.',1,2)+1,INSTR("t1"."col0",'.',1,3)-INSTR("t1"."col0",'.',1,2)-1))*256+TO_NUMBER(SUBSTR("t1"."col0",INSTR("t1"."col0",'.',1,3)+1))) AS "ipaddr", 123456 AS "gateway" FROM "test" AS "t1" GROUP BY "t1"."col0"` + want := `SELECT MAX("t1"."col1") AS "number", MAX(HEX(SF_INET_SORT("t1"."col0"))) AS "ipaddr", 123456 AS "gateway" FROM "test" AS "t1" GROUP BY "t1"."col0"` + testGotWant(t, q.String(), want) + }) + + t.Run("query INET6_ATON func", func(t *testing.T) { + testReset() + q := testTable.Query(testTable.Field("col1"), sqlchemy.INET6_ATON(testTable.Field("col0")).Label("ipaddr")) + want := `SELECT "t1"."col1" AS "col1", HEX(SF_INET_SORT("t1"."col0")) AS "ipaddr" FROM "test" AS "t1"` testGotWant(t, q.String(), want) }) } diff --git a/backends_base.go b/backends_base.go index 3855e21..92f95e3 100644 --- a/backends_base.go +++ b/backends_base.go @@ -154,6 +154,11 @@ func (bb *SBaseBackend) INET_ATON(field IQueryField) IQueryField { return NewFunctionField("", false, `INET_ATON(%s)`, field) } +// INET6_ATON represents a SQL function INET6_ATON +func (bb *SBaseBackend) INET6_ATON(field IQueryField) IQueryField { + return NewFunctionField("", false, `INET6_ATON(%s)`, field) +} + // SubStr represents a SQL function SUBSTR func (bb *SBaseBackend) SUBSTR(name string, field IQueryField, pos, length int) IQueryField { var rightStr string diff --git a/functions.go b/functions.go index 9542b67..4bd8ca7 100644 --- a/functions.go +++ b/functions.go @@ -228,6 +228,8 @@ func REPLACE(name string, field IQueryField, old string, new string) IQueryField type SConstField struct { constVar interface{} alias string + + db *SDatabase } // Expression implementation of SConstField for IQueryField @@ -260,7 +262,7 @@ func (s *SConstField) ConvertFromValue(val interface{}) interface{} { // database implementation of SConstField for IQueryField func (s *SConstField) database() *SDatabase { - return nil + return s.db } // Variables implementation of SConstField for IQueryField @@ -278,10 +280,24 @@ func NewConstField(variable interface{}) *SConstField { return &SConstField{constVar: variable} } +// database implementation of SStringField for IQueryField +func (s *SConstField) WithField(f IQueryField) *SConstField { + s.db = f.database() + return s +} + +func (q *SQuery) ConstField(variable interface{}) *SConstField { + f := NewConstField(variable) + f.db = q.db + return f +} + // SStringField is a query field of a string constant type SStringField struct { strConst string alias string + + db *SDatabase } // Expression implementation of SStringField for IQueryField @@ -314,7 +330,7 @@ func (s *SStringField) ConvertFromValue(val interface{}) interface{} { // database implementation of SStringField for IQueryField func (s *SStringField) database() *SDatabase { - return nil + return s.db } // Variables implementation of SStringField for IQueryField @@ -327,11 +343,23 @@ func (s *SStringField) IsAggregate() bool { return true } +// database implementation of SStringField for IQueryField +func (s *SStringField) WithField(f IQueryField) *SStringField { + s.db = f.database() + return s +} + // NewStringField returns an instance of SStringField func NewStringField(strConst string) *SStringField { return &SStringField{strConst: strConst} } +func (q *SQuery) StringField(strConst string) *SStringField { + f := NewStringField(strConst) + f.db = q.db + return f +} + // CONCAT represents a SQL function CONCAT func CONCAT(name string, fields ...IQueryField) IQueryField { return getFieldBackend(fields...).CONCAT(name, fields...) @@ -363,6 +391,11 @@ func INET_ATON(field IQueryField) IQueryField { return getFieldBackend(field).INET_ATON(field) } +// INET6_ATON represents a SQL function INET_ATON +func INET6_ATON(field IQueryField) IQueryField { + return getFieldBackend(field).INET6_ATON(field) +} + // TimestampAdd represents a SQL function TimestampAdd func TimestampAdd(name string, field IQueryField, offsetSeconds int) IQueryField { return TIMESTAMPADD(name, field, offsetSeconds)