3
0

Fix LIKE COLLATE param, improve filter/sort query generation

This commit is contained in:
Denis Arh
2019-01-16 17:10:53 +01:00
parent e2ea47e145
commit 7c87decc9f
2 changed files with 38 additions and 13 deletions

View File

@@ -85,7 +85,7 @@ func (n Operator) ToSql() (string, []interface{}, error) {
switch n.Kind {
case "LIKE", "NOT LIKE":
// Make sure we are doing case insensitive search
op = "COLLATE utf8mb4_general_ci " + n.Kind
op = "COLLATE utf8_general_ci " + n.Kind
}
return " " + op + " ", nil, nil

View File

@@ -3,7 +3,6 @@ package repository
import (
"context"
"fmt"
"strings"
"time"
"github.com/jmoiron/sqlx"
@@ -144,7 +143,7 @@ func (r *record) Find(module *types.Module, filter string, sort string, page int
// Assemble SQL for fetching record (where + sorting + paging)...
query = query.
Column("crm_record.*").
Column("r.*").
Limit(uint64(perPage)).
Offset(uint64(page))
@@ -165,9 +164,9 @@ func (r *record) Find(module *types.Module, filter string, sort string, page int
func (r *record) buildQuery(module *types.Module, filter string, sort string) (query sq.SelectBuilder, err error) {
// Create query for fetching and counting records.
query = sq.Select().
From("crm_record").
Where(sq.Eq{"module_id": module.ID}).
Where(sq.Eq{"deleted_at": nil})
From("crm_record AS r").
Where(sq.Eq{"r.module_id": module.ID}).
Where(sq.Eq{"r.deleted_at": nil})
// Do not translate/wrap these
var realColumns = []string{
@@ -178,7 +177,17 @@ func (r *record) buildQuery(module *types.Module, filter string, sort string) (q
"updated_at",
}
const colWrap = `(SELECT value FROM crm_record_value WHERE name = ? AND record_id = crm_record.id AND deleted_at IS NULL)`
var joinedFields = []string{}
var alreadyJoined = func(f string) bool {
for _, a := range joinedFields {
if a == f {
return true
}
}
joinedFields = append(joinedFields, f)
return false
}
// Parse filters.
if filter != "" {
@@ -202,19 +211,26 @@ func (r *record) buildQuery(module *types.Module, filter string, sort string) (q
return i, errors.Errorf("unknown field %q", i.Value)
}
// @todo switch value for ref when doing Record/User lookup
if !alreadyJoined(i.Value) {
query = query.LeftJoin(fmt.Sprintf(
"crm_record_value AS rv_%s ON (rv_%s.record_id = r.id AND rv_%s.name = ? AND rv_%s.deleted_at IS NULL)",
i.Value, i.Value, i.Value, i.Value,
), i.Value)
}
i.Args = []interface{}{i.Value}
i.Value = colWrap
// @todo switch value for ref when doing Record/User lookup
i.Value = fmt.Sprintf("rv_%s.value", i.Value)
return i, nil
}
if fn, err = fp.ParseExpression(filter); err != nil {
return
} else if filterSql, filterArgs, err := fn.ToSql(); err != nil {
return query, err
} else {
query = query.Where("("+filterSql+")", filterArgs...)
}
query = query.Where(fn)
}
if sort != "" {
@@ -238,7 +254,16 @@ func (r *record) buildQuery(module *types.Module, filter string, sort string) (q
return i, errors.Errorf("unknown field %q", i.Value)
}
i.Value = strings.Replace(colWrap, "?", fmt.Sprintf("'%s'", i.Value), 1) + " "
if !alreadyJoined(i.Value) {
query = query.LeftJoin(fmt.Sprintf(
"crm_record_value AS rv_%s ON (rv_%s.record_id = r.id AND rv_%s.name = ? AND rv_%s.deleted_at IS NULL)",
i.Value, i.Value, i.Value, i.Value,
), i.Value)
}
// @todo switch value for ref when doing Record/User lookup
i.Value = fmt.Sprintf("rv_%s.value ", i.Value)
return i, nil
}