/vendor/github.com/Knetic/govaluate/EvaluableExpression_sql.go
https://bitbucket.org/jyotiswarp/ppc · Go · 167 lines · 120 code · 36 blank · 11 comment · 19 complexity · 98e28ed7846e92034762a4c23dce2f28 MD5 · raw file
- package govaluate
- import (
- "errors"
- "fmt"
- "regexp"
- "time"
- )
- /*
- Returns a string representing this expression as if it were written in SQL.
- This function assumes that all parameters exist within the same table, and that the table essentially represents
- a serialized object of some sort (e.g., hibernate).
- If your data model is more normalized, you may need to consider iterating through each actual token given by `Tokens()`
- to create your query.
- Boolean values are considered to be "1" for true, "0" for false.
- Times are formatted according to this.QueryDateFormat.
- */
- func (this EvaluableExpression) ToSQLQuery() (string, error) {
- var stream *tokenStream
- var transactions *expressionOutputStream
- var transaction string
- var err error
- stream = newTokenStream(this.tokens)
- transactions = new(expressionOutputStream)
- for stream.hasNext() {
- transaction, err = this.findNextSQLString(stream, transactions)
- if err != nil {
- return "", err
- }
- transactions.add(transaction)
- }
- return transactions.createString(" "), nil
- }
- func (this EvaluableExpression) findNextSQLString(stream *tokenStream, transactions *expressionOutputStream) (string, error) {
- var token ExpressionToken
- var ret string
- token = stream.next()
- switch token.Kind {
- case STRING:
- ret = fmt.Sprintf("'%v'", token.Value)
- case PATTERN:
- ret = fmt.Sprintf("'%s'", token.Value.(*regexp.Regexp).String())
- case TIME:
- ret = fmt.Sprintf("'%s'", token.Value.(time.Time).Format(this.QueryDateFormat))
- case LOGICALOP:
- switch logicalSymbols[token.Value.(string)] {
- case AND:
- ret = "AND"
- case OR:
- ret = "OR"
- }
- case BOOLEAN:
- if token.Value.(bool) {
- ret = "1"
- } else {
- ret = "0"
- }
- case VARIABLE:
- ret = fmt.Sprintf("[%s]", token.Value.(string))
- case NUMERIC:
- ret = fmt.Sprintf("%g", token.Value.(float64))
- case COMPARATOR:
- switch comparatorSymbols[token.Value.(string)] {
- case EQ:
- ret = "="
- case NEQ:
- ret = "<>"
- case REQ:
- ret = "RLIKE"
- case NREQ:
- ret = "NOT RLIKE"
- default:
- ret = fmt.Sprintf("%s", token.Value.(string))
- }
- case TERNARY:
- switch ternarySymbols[token.Value.(string)] {
- case COALESCE:
- left := transactions.rollback()
- right, err := this.findNextSQLString(stream, transactions)
- if err != nil {
- return "", err
- }
- ret = fmt.Sprintf("COALESCE(%v, %v)", left, right)
- case TERNARY_TRUE:
- fallthrough
- case TERNARY_FALSE:
- return "", errors.New("Ternary operators are unsupported in SQL output")
- }
- case PREFIX:
- switch prefixSymbols[token.Value.(string)] {
- case INVERT:
- ret = fmt.Sprintf("NOT")
- default:
- right, err := this.findNextSQLString(stream, transactions)
- if err != nil {
- return "", err
- }
- ret = fmt.Sprintf("%s%s", token.Value.(string), right)
- }
- case MODIFIER:
- switch modifierSymbols[token.Value.(string)] {
- case EXPONENT:
- left := transactions.rollback()
- right, err := this.findNextSQLString(stream, transactions)
- if err != nil {
- return "", err
- }
- ret = fmt.Sprintf("POW(%s, %s)", left, right)
- case MODULUS:
- left := transactions.rollback()
- right, err := this.findNextSQLString(stream, transactions)
- if err != nil {
- return "", err
- }
- ret = fmt.Sprintf("MOD(%s, %s)", left, right)
- default:
- ret = fmt.Sprintf("%s", token.Value.(string))
- }
- case CLAUSE:
- ret = "("
- case CLAUSE_CLOSE:
- ret = ")"
- case SEPARATOR:
- ret = ","
- default:
- errorMsg := fmt.Sprintf("Unrecognized query token '%s' of kind '%s'", token.Value, token.Kind)
- return "", errors.New(errorMsg)
- }
- return ret, nil
- }