mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2025-12-13 17:10:36 +00:00
Fixed bugs in extractTableAndColumn
This commit is contained in:
parent
99307e31e6
commit
490ae37c6d
@ -430,7 +430,45 @@ func extractTableAndColumn(cond string) (table string, column string) {
|
|||||||
// Remove any quotes
|
// Remove any quotes
|
||||||
columnRef = strings.Trim(columnRef, "`\"'")
|
columnRef = strings.Trim(columnRef, "`\"'")
|
||||||
|
|
||||||
// Check if it contains a dot (qualified reference)
|
// Check if there's a function call (contains opening parenthesis)
|
||||||
|
openParenIdx := strings.Index(columnRef, "(")
|
||||||
|
|
||||||
|
if openParenIdx >= 0 {
|
||||||
|
// There's a function call - find the FIRST dot after the opening paren
|
||||||
|
// This handles cases like: ifblnk(users.status, orders.status) - extracts users.status
|
||||||
|
dotIdx := strings.Index(columnRef[openParenIdx:], ".")
|
||||||
|
if dotIdx > 0 {
|
||||||
|
dotIdx += openParenIdx // Adjust to absolute position
|
||||||
|
|
||||||
|
// Extract table name (between paren and dot)
|
||||||
|
// Find the last opening paren before this dot
|
||||||
|
lastOpenParen := strings.LastIndex(columnRef[:dotIdx], "(")
|
||||||
|
table = columnRef[lastOpenParen+1 : dotIdx]
|
||||||
|
|
||||||
|
// Find the column name - it ends at comma, closing paren, whitespace, or end of string
|
||||||
|
columnStart := dotIdx + 1
|
||||||
|
columnEnd := len(columnRef)
|
||||||
|
|
||||||
|
for i := columnStart; i < len(columnRef); i++ {
|
||||||
|
ch := columnRef[i]
|
||||||
|
if ch == ',' || ch == ')' || ch == ' ' || ch == '\t' {
|
||||||
|
columnEnd = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
column = columnRef[columnStart:columnEnd]
|
||||||
|
|
||||||
|
// Remove quotes from table and column if present
|
||||||
|
table = strings.Trim(table, "`\"'")
|
||||||
|
column = strings.Trim(column, "`\"'")
|
||||||
|
|
||||||
|
return table, column
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No function call - check if it contains a dot (qualified reference)
|
||||||
|
// Use LastIndex to handle schema.table.column properly
|
||||||
if dotIdx := strings.LastIndex(columnRef, "."); dotIdx > 0 {
|
if dotIdx := strings.LastIndex(columnRef, "."); dotIdx > 0 {
|
||||||
table = columnRef[:dotIdx]
|
table = columnRef[:dotIdx]
|
||||||
column = columnRef[dotIdx+1:]
|
column = columnRef[dotIdx+1:]
|
||||||
|
|||||||
@ -286,6 +286,48 @@ func TestExtractTableAndColumn(t *testing.T) {
|
|||||||
expectedTable: "",
|
expectedTable: "",
|
||||||
expectedCol: "",
|
expectedCol: "",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "function call with table.column - ifblnk",
|
||||||
|
input: "ifblnk(users.status,0) in (1,2,3,4)",
|
||||||
|
expectedTable: "users",
|
||||||
|
expectedCol: "status",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "function call with table.column - coalesce",
|
||||||
|
input: "coalesce(users.age, 0) = 25",
|
||||||
|
expectedTable: "users",
|
||||||
|
expectedCol: "age",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nested function calls",
|
||||||
|
input: "upper(trim(users.name)) = 'JOHN'",
|
||||||
|
expectedTable: "users",
|
||||||
|
expectedCol: "name",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "function with multiple args and table.column",
|
||||||
|
input: "substring(users.email, 1, 5) = 'admin'",
|
||||||
|
expectedTable: "users",
|
||||||
|
expectedCol: "email",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cast function with table.column",
|
||||||
|
input: "cast(orders.total as decimal) > 100",
|
||||||
|
expectedTable: "orders",
|
||||||
|
expectedCol: "total",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "complex nested functions",
|
||||||
|
input: "coalesce(nullif(users.status, ''), 'default') = 'active'",
|
||||||
|
expectedTable: "users",
|
||||||
|
expectedCol: "status",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "function with multiple table.column refs (extracts first)",
|
||||||
|
input: "greatest(users.created_at, users.updated_at) > '2024-01-01'",
|
||||||
|
expectedTable: "users",
|
||||||
|
expectedCol: "created_at",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -352,6 +394,14 @@ func TestSanitizeWhereClauseWithPreloads(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expected: "users.status = 'active' AND Department.name = 'Engineering'",
|
expected: "users.status = 'active' AND Department.name = 'Engineering'",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
name: "Function Call with correct table prefix - unchanged",
|
||||||
|
where: "ifblnk(users.status,0) in (1,2,3,4)",
|
||||||
|
tableName: "users",
|
||||||
|
options: nil,
|
||||||
|
expected: "ifblnk(users.status,0) in (1,2,3,4)",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "no options provided - works as before",
|
name: "no options provided - works as before",
|
||||||
where: "wrong_table.status = 'active'",
|
where: "wrong_table.status = 'active'",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user