fix: database query condition issue (#2004)

main
Zhj 1 month ago committed by GitHub
parent 04792aeb37
commit 88fd5f0bd7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 126
      backend/domain/memory/database/service/database_impl.go
  2. 46
      backend/domain/memory/database/service/database_impl_test.go
  3. 51
      backend/infra/impl/rdb/mysql.go

@ -1209,32 +1209,10 @@ func (d databaseService) executeSelectSQL(ctx context.Context, req *ExecuteSQLRe
selectReq.Fields = fields
}
var complexCond *rdb.ComplexCondition
var err error
if req.Condition != nil {
complexCond, err = convertCondition(ctx, req.Condition, fieldNameToPhysical, req.SQLParams)
if err != nil {
return nil, fmt.Errorf("convert condition failed: %v", err)
}
}
// add rw mode
if tableInfo.RwMode == table.BotTableRWMode_LimitedReadWrite && req.UserID != "" {
cond := &rdb.Condition{
Field: database.DefaultUidColName,
Operator: entity3.OperatorEqual,
Value: req.UserID,
}
if complexCond == nil {
complexCond = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
} else {
complexCond.Conditions = append(complexCond.Conditions, cond)
}
complexCond, err := generateComplexCond(ctx, req, tableInfo.RwMode, fieldNameToPhysical)
if err != nil {
return nil, err
}
if complexCond != nil {
selectReq.Where = complexCond
}
@ -1376,27 +1354,10 @@ func (d databaseService) executeUpdateSQL(ctx context.Context, req *ExecuteSQLRe
}
}
condParams := req.SQLParams[index:]
complexCond, err := convertCondition(ctx, req.Condition, fieldNameToPhysical, condParams)
req.SQLParams = req.SQLParams[index:]
complexCond, err := generateComplexCond(ctx, req, tableInfo.RwMode, fieldNameToPhysical)
if err != nil {
return -1, fmt.Errorf("convert condition failed: %v", err)
}
// add rw mode
if tableInfo.RwMode == table.BotTableRWMode_LimitedReadWrite && req.UserID != "" {
cond := &rdb.Condition{
Field: database.DefaultUidColName,
Operator: entity3.OperatorEqual,
Value: req.UserID,
}
if complexCond == nil {
complexCond = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
} else {
complexCond.Conditions = append(complexCond.Conditions, cond)
}
return -1, err
}
updateResp, err := d.rdb.UpdateData(ctx, &rdb.UpdateDataRequest{
@ -1417,26 +1378,9 @@ func (d databaseService) executeDeleteSQL(ctx context.Context, req *ExecuteSQLRe
return -1, fmt.Errorf("missing delete condition")
}
complexCond, err := convertCondition(ctx, req.Condition, fieldNameToPhysical, req.SQLParams)
complexCond, err := generateComplexCond(ctx, req, tableInfo.RwMode, fieldNameToPhysical)
if err != nil {
return -1, fmt.Errorf("convert condition failed: %v", err)
}
// add rw mode
if tableInfo.RwMode == table.BotTableRWMode_LimitedReadWrite && req.UserID != "" {
cond := &rdb.Condition{
Field: database.DefaultUidColName,
Operator: entity3.OperatorEqual,
Value: req.UserID,
}
if complexCond == nil {
complexCond = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
} else {
complexCond.Conditions = append(complexCond.Conditions, cond)
}
return -1, err
}
deleteResp, err := d.rdb.DeleteData(ctx, &rdb.DeleteDataRequest{
@ -1538,13 +1482,6 @@ func convertCondition(ctx context.Context, cond *database.ComplexCondition, fiel
}
result.Conditions = conditions
}
// if cond.NestedConditions != nil {
// nested, err := convertCondition(cond.NestedConditions, fieldMap, params)
// if err != nil {
// return nil, err
// }
// result.NestedConditions = []*rdb.ComplexCondition{nested}
// }
return result, nil
}
@ -2204,3 +2141,50 @@ func (d databaseService) GetAllDatabaseByAppID(ctx context.Context, req *GetAllD
Databases: onlineDBs,
}, nil
}
func generateComplexCond(ctx context.Context, req *ExecuteSQLRequest, mode table.BotTableRWMode, fieldNameToPhysical map[string]string) (*rdb.ComplexCondition, error) {
var (
err error
complexCond *rdb.ComplexCondition
extraCondition *rdb.ComplexCondition
)
if req.Condition != nil {
complexCond, err = convertCondition(ctx, req.Condition, fieldNameToPhysical, req.SQLParams)
if err != nil {
return nil, fmt.Errorf("convert condition failed: %v", err)
}
}
if mode == table.BotTableRWMode_LimitedReadWrite && req.UserID != "" {
cond := &rdb.Condition{
Field: database.DefaultUidColName,
Operator: entity3.OperatorEqual,
Value: req.UserID,
}
extraCondition = &rdb.ComplexCondition{
Conditions: []*rdb.Condition{cond},
}
}
if complexCond != nil && extraCondition != nil {
return &rdb.ComplexCondition{
NestedConditions: []*rdb.ComplexCondition{
complexCond,
extraCondition,
},
Operator: entity3.AND,
}, nil
}
if complexCond != nil {
return complexCond, nil
}
if extraCondition != nil {
return extraCondition, nil
}
return nil, nil
}

@ -634,6 +634,52 @@ func TestExecuteSQLWithOperations(t *testing.T) {
assert.NotNil(t, selectINResp)
assert.True(t, len(selectINResp.Records) == 2)
executeSelectWithOrOperationReq := &ExecuteSQLRequest{
DatabaseID: resp.Database.ID,
TableType: table.TableType_OnlineTable,
OperateType: database.OperateType_Select,
SelectFieldList: selectFields,
Limit: &limit,
UserID: "1001",
SpaceID: 1,
OrderByList: []database.OrderBy{
{
Field: "id_custom",
Direction: table.SortDirection_Desc,
},
},
SQLParams: []*database.SQLParamVal{
{
Value: ptr.Of("Alice"),
},
{
Value: ptr.Of("100"),
},
},
Condition: &database.ComplexCondition{
Conditions: []*database.Condition{
{
Left: "name",
Operation: database.Operation_EQUAL,
Right: "?",
},
{
Left: "score",
Operation: database.Operation_EQUAL,
Right: "?",
},
},
Logic: database.Logic_Or,
},
}
selectWithOrOperationResp, err := dbService.ExecuteSQL(context.Background(), executeSelectWithOrOperationReq)
assert.NoError(t, err)
assert.NotNil(t, selectWithOrOperationResp)
assert.Equal(t, string(selectWithOrOperationResp.Records[0]["name"].([]uint8)), "Alice")
assert.True(t, len(selectWithOrOperationResp.Records) == 1)
updateRows := []*database.UpsertRow{
{
Records: []*database.Record{

@ -930,14 +930,23 @@ func (m *mysqlService) buildWhereClause(condition *rdb.ComplexCondition) (string
if condition == nil {
return "", nil, nil
}
if condition.Operator == "" {
condition.Operator = entity2.AND
}
if len(condition.NestedConditions) > 0 {
return m.buildNestedConditions(condition)
} else if len(condition.Conditions) > 0 {
whereClauseString, values, err := m.buildWhereCondition(condition)
return " WHERE " + whereClauseString, values, err
} else {
return "", nil, fmt.Errorf("empty condition: no nested or direct conditions found")
}
}
func (m *mysqlService) buildWhereCondition(condition *rdb.ComplexCondition) (string, []interface{}, error) {
var whereClause strings.Builder
values := make([]interface{}, 0)
for i, cond := range condition.Conditions {
if i > 0 {
whereClause.WriteString(fmt.Sprintf(" %s ", condition.Operator))
@ -971,25 +980,35 @@ func (m *mysqlService) buildWhereClause(condition *rdb.ComplexCondition) (string
values = append(values, cond.Value)
}
}
if whereClause.Len() > 0 {
return whereClause.String(), values, nil
}
return "", values, nil
}
if len(condition.NestedConditions) > 0 {
whereClause.WriteString(" AND (")
for i, nested := range condition.NestedConditions {
if i > 0 {
whereClause.WriteString(fmt.Sprintf(" %s ", nested.Operator))
}
nestedClause, nestedValues, err := m.buildWhereClause(nested)
if err != nil {
return "", nil, err
}
whereClause.WriteString(nestedClause)
values = append(values, nestedValues...)
func (m *mysqlService) buildNestedConditions(condition *rdb.ComplexCondition) (string, []interface{}, error) {
var whereClause strings.Builder
values := make([]interface{}, 0)
whereClause.WriteString(" WHERE (")
for i, nested := range condition.NestedConditions {
if i > 0 {
whereClause.WriteString(fmt.Sprintf(" %s ", nested.Operator))
}
nestedClause, nestedValues, err := m.buildWhereCondition(nested)
if err != nil {
return "", nil, err
}
whereClause.WriteString(nestedClause)
if i < len(condition.NestedConditions)-1 {
whereClause.WriteString(" " + string(condition.Operator))
}
whereClause.WriteString(")")
values = append(values, nestedValues...)
}
whereClause.WriteString(")")
if whereClause.Len() > 0 {
return " WHERE " + whereClause.String(), values, nil
return whereClause.String(), values, nil
}
return "", values, nil
}

Loading…
Cancel
Save