Skip to content

Commit

Permalink
feat: simplify toSQL
Browse files Browse the repository at this point in the history
  • Loading branch information
pieterlukasse committed Jan 16, 2025
1 parent f3951c2 commit f790702
Show file tree
Hide file tree
Showing 2 changed files with 3 additions and 74 deletions.
2 changes: 1 addition & 1 deletion models/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func QueryFilterByConceptDefHelper2(query *gorm.DB, sourceId int, filterConceptD
// Returns the temp table name.
func TransformDataIntoTempTable(query *gorm.DB, filterConceptDef utils.CustomConceptVariableDef) (string, error) {
// Generate a unique hash key based on the query and transformation
querySQL, _ := utils.ToSQL(query)
querySQL := utils.ToSQL(query)
queryKey := fmt.Sprintf("%s|%s", querySQL, filterConceptDef.Transformation)
cacheKey := utils.GenerateHash(queryKey) // Assuming utils.GenerateHash exists for creating unique keys.

Expand Down
75 changes: 2 additions & 73 deletions utils/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ package utils

import (
"context"
"fmt"
"log"
"regexp"
"strings"
"time"

"gorm.io/driver/postgres"
"gorm.io/driver/sqlserver"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
)

Expand Down Expand Up @@ -83,79 +80,11 @@ func (h DbAndSchema) GetViewDirective() string {
return ""
}
}
func ToSQL2(query *gorm.DB) (string, error) {
func ToSQL(query *gorm.DB) string {
// Use db.ToSQL to generate the SQL string for the existing query
sql := query.ToSQL(func(tx *gorm.DB) *gorm.DB {
return tx.Session(&gorm.Session{DryRun: true}).Find([]interface{}{})
})

return sql, nil
}

func ToSQL(query *gorm.DB) (string, error) {
//var dummy []interface{}
//log.Printf("Statement.SQL: %s", query.Statement.SQL.String())
log.Printf("TableExpr.SQL: %s", query.Statement.TableExpr.SQL)
log.Printf("Clauses: %+v", query.Statement.Clauses) // TODO - REMOVE?
//sqlString := query.Session(&gorm.Session{DryRun: true}).Find(&dummy).Statement.SQL.String()
// if sqlString == "" {
// sqlString, _ = ToSQL2(query)
// }
sqlString2, _ := ToSQL2(query)
log.Printf("Statement.SQL: %s", sqlString2)

//interpolatedSQL, err := InterpolateSQL(query, sqlString2)

return sqlString2, nil
}

// Replaces placeholders in SQL with actual values,
// exploring all potential variable sources in the GORM query object.
func InterpolateSQL(query *gorm.DB, sqlString string) (string, error) {

// Collect variables from query.Statement.TableExpr.Vars
allVars := query.Statement.TableExpr.Vars

// Collect variables from query.Statement.Clauses
for _, c := range query.Statement.Clauses {
if len(c.Expression.(clause.Where).Exprs) > 0 {
for _, expr := range c.Expression.(clause.Where).Exprs {
switch v := expr.(type) {
case clause.Expr:
allVars = append(allVars, v.Vars...)
}
}
}
}

// Use regular expression to find all occurrences of placeholders like $1, $2, etc.
placeholderRegex := regexp.MustCompile(`\$(\d+)`)
placeholders := placeholderRegex.FindAllString(sqlString, -1)

// Check if the number of placeholders matches the length of allVars
if len(placeholders) != len(allVars) {
return "", fmt.Errorf("mismatch between number of placeholders (%d) and number of variables (%d)", len(placeholders), len(allVars))
}

// Replace placeholders ($1, $2, etc.) with actual variable values
resultSQL := sqlString
for i, v := range allVars {
placeholder := fmt.Sprintf("$%d", i+1)
var value string

// Handle different variable types
switch val := v.(type) {
case string:
value = fmt.Sprintf("'%s'", val) // Wrap strings in quotes
case int, int64, float64:
value = fmt.Sprintf("%v", val) // Numeric values
case nil:
value = "NULL" // NULL values
default:
value = fmt.Sprintf("'%v'", val) // Fallback for other types
}
// Replace the placeholder with the actual value
resultSQL = strings.Replace(resultSQL, placeholder, value, 1)
}
return resultSQL, nil
return sql
}

0 comments on commit f790702

Please sign in to comment.