@ -4,6 +4,7 @@ import (
"fmt"
"slices"
"strings"
"time"
"github.com/pkg/errors"
exprv1 "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
@ -36,15 +37,55 @@ func RestoreExprToSQL(expr *exprv1.Expr) (string, error) {
if len ( v . CallExpr . Args ) != 2 {
return "" , errors . Errorf ( "invalid number of arguments for %s" , v . CallExpr . Function )
}
// TODO(j): Implement this part.
identifier := v . CallExpr . Args [ 0 ] . GetIdentExpr ( ) . GetName ( )
if ! slices . Contains ( [ ] string { "create_time" , "update_time" } , identifier ) {
return "" , errors . Errorf ( "invalid identifier for %s" , v . CallExpr . Function )
}
value , err := filter . GetConstValue ( v . CallExpr . Args [ 1 ] )
if err != nil {
return "" , err
}
operator := "="
switch v . CallExpr . Function {
case "_==_" :
operator = "="
case "_!=_" :
operator = "!="
case "_<_" :
operator = "<"
case "_>_" :
operator = ">"
case "_<=_" :
operator = "<="
case "_>=_" :
operator = ">="
}
if identifier == "create_time" || identifier == "update_time" {
timestampStr , ok := value . ( string )
if ! ok {
return "" , errors . New ( "invalid timestamp value" )
}
timestamp , err := time . Parse ( time . RFC3339 , timestampStr )
if err != nil {
return "" , errors . Wrap ( err , "failed to parse timestamp" )
}
if identifier == "create_time" {
condition = fmt . Sprintf ( "`memo`.`created_ts` %s %d" , operator , timestamp . Unix ( ) )
} else if identifier == "update_time" {
condition = fmt . Sprintf ( "`memo`.`updated_ts` %s %d" , operator , timestamp . Unix ( ) )
}
}
case "@in" :
if len ( v . CallExpr . Args ) != 2 {
return "" , errors . Errorf ( "invalid number of arguments for %s" , v . CallExpr . Function )
}
factor := v . CallExpr . Args [ 0 ] . GetIdentExpr ( ) . Name
if ! slices . Contains ( [ ] string { "tag" } , factor ) {
return "" , errors . Errorf ( "invalid factor for %s" , v . CallExpr . Function )
identifie r := v . CallExpr . Args [ 0 ] . GetIdentExpr ( ) . GetName ( )
if ! slices . Contains ( [ ] string { "tag" , "visibility" } , identifie r) {
return "" , errors . Errorf ( "invalid identifie r for %s", v . CallExpr . Function )
}
values := [ ] any { }
for _ , element := range v . CallExpr . Args [ 1 ] . GetListExpr ( ) . Elements {
value , err := filter . GetConstValue ( element )
@ -53,33 +94,43 @@ func RestoreExprToSQL(expr *exprv1.Expr) (string, error) {
}
values = append ( values , value )
}
if factor == "tag" {
t := [ ] string { }
if identifier == "tag" {
subcodition := [ ] string { }
for _ , v := range values {
subcodition = append ( subcodition , fmt . Sprintf ( "JSON_EXTRACT(`memo`.`payload`, '$.tags') LIKE %s" , fmt . Sprintf ( ` %%"%s"%% ` , v ) ) )
}
if len ( subcodition ) == 1 {
condition = subcodition [ 0 ]
} else {
condition = fmt . Sprintf ( "(%s)" , strings . Join ( subcodition , " OR " ) )
}
} else if identifier == "visibility" {
vs := [ ] string { }
for _ , v := range values {
t = append ( t , fmt . Sprintf ( "JSON_EXTRACT(`memo`.`payload`, '$.tags') LIKE %s" , fmt . Sprintf ( ` %%"%s"%% ` , v ) ) )
vs = append ( vs , fmt . Sprintf ( ` "%s"` , v ) )
}
if len ( t ) == 1 {
condition = t [ 0 ]
if len ( vs ) == 1 {
condition = fm t.Sprintf ( "`memo`.`visibility` = %s" , vs [0 ] )
} else {
condition = fmt . Sprintf ( "(%s)" , strings . Join ( t , " OR " ) )
condition = fmt . Sprintf ( " `memo`.`visibility` IN (%s)", strings . Join ( vs, ", ") )
}
}
case "contains" :
if len ( v . CallExpr . Args ) != 1 {
return "" , errors . Errorf ( "invalid number of arguments for %s" , v . CallExpr . Function )
}
facto r, err := RestoreExprToSQL ( v . CallExpr . Target )
identifie r, err := RestoreExprToSQL ( v . CallExpr . Target )
if err != nil {
return "" , err
}
if facto r != "content" {
return "" , errors . Errorf ( "invalid facto r for %s", v . CallExpr . Function )
if identifie r != "content" {
return "" , errors . Errorf ( "invalid identifie r for %s", v . CallExpr . Function )
}
arg , err := filter . GetConstValue ( v . CallExpr . Args [ 0 ] )
if err != nil {
return "" , err
}
condition = fmt . Sprintf ( " JSON_EXTRACT(`memo`.`payload`, '$.content') LIKE %s", fmt . Sprintf ( ` %%"%s"%% ` , arg ) )
condition = fmt . Sprintf ( " `memo`.`content` LIKE %s", fmt . Sprintf ( ` %%"%s"%% ` , arg ) )
case "!_" :
if len ( v . CallExpr . Args ) != 1 {
return "" , errors . Errorf ( "invalid number of arguments for %s" , v . CallExpr . Function )