Browse Source

完成解析

yjp 1 year ago
parent
commit
1f74e6b8cf
5 changed files with 159 additions and 30 deletions
  1. 1 1
      go.mod
  2. 2 2
      go.sum
  3. 27 21
      sql_parser.go
  4. 11 3
      test_sql.go
  5. 118 3
      v1_test.go

+ 1 - 1
go.mod

@@ -4,7 +4,7 @@ go 1.21.3
 
 require (
 	git.sxidc.com/go-tools/api_binding v1.3.22
-	git.sxidc.com/service-supports/dps-sdk v1.10.2
+	git.sxidc.com/service-supports/dps-sdk v1.10.3
 	github.com/auxten/postgresql-parser v1.0.1
 	github.com/go-resty/resty/v2 v2.11.0
 	github.com/satori/go.uuid v1.2.0

+ 2 - 2
go.sum

@@ -2,8 +2,8 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 git.sxidc.com/go-tools/api_binding v1.3.22 h1:4LPdcClfqM2bmCSrCe6HceSmAwr3rGhfxjVWn/4rliY=
 git.sxidc.com/go-tools/api_binding v1.3.22/go.mod h1:JoPU2jtPwbsAEjAuiSedKxuwu3bK4rrkZxyQ3mkU0XI=
-git.sxidc.com/service-supports/dps-sdk v1.10.2 h1:0eMoHk7cSAtvRUyavLDf7m7UXPiRtaERu5kzg6KS/VM=
-git.sxidc.com/service-supports/dps-sdk v1.10.2/go.mod h1:bR7PtL4x4QKc8ZRbszn8hLBaK6G/uZl4ZbU7/TZcJ94=
+git.sxidc.com/service-supports/dps-sdk v1.10.3 h1:1xQcSoXNZpE3pRieH2HNYd52LMC1tdiwqWBXjZydxPY=
+git.sxidc.com/service-supports/dps-sdk v1.10.3/go.mod h1:bR7PtL4x4QKc8ZRbszn8hLBaK6G/uZl4ZbU7/TZcJ94=
 git.sxidc.com/service-supports/fserr v0.3.2 h1:5/FCr8o2jd1kNsp5tH/ADjB9fr091JZXMMZ15ZvNZzs=
 git.sxidc.com/service-supports/fserr v0.3.2/go.mod h1:W54RoA71mfex+zARuH/iMnQPMnBXQ23qXXOkwUh2sVQ=
 git.sxidc.com/service-supports/fslog v0.5.9 h1:q2XIK2o/fk/qmByy4x5kKLC+k7kolT5LrXHcWRSffXQ=

+ 27 - 21
sql_parser.go

@@ -46,7 +46,7 @@ type selectClause struct {
 	fromSubQuery string
 	selectClause string
 	where        string
-	orderBy      []string
+	orderBy      string
 	groupBy      []string
 	having       string
 	pageNo       int
@@ -144,7 +144,7 @@ func insertWalk(sql string) (*insertClause, error) {
 				}
 			}
 
-			return false
+			return true
 		},
 	}
 
@@ -186,7 +186,7 @@ func deleteWalk(sql string) (*deleteClause, error) {
 			// 获取where
 			clause.where = parseWhere(realNode.Where)
 
-			return false
+			return true
 		},
 	}
 
@@ -240,7 +240,7 @@ func updateWalk(sql string) (*updateClause, error) {
 				clause.newTableRow[fmt.Sprint(expr.Names[0])] = *value
 			}
 
-			return false
+			return true
 		},
 	}
 
@@ -273,9 +273,17 @@ func selectWalk(sql string) (*selectClause, error) {
 
 			// select
 			clause.selectClause = parseSelect(nodeSelectClause.Exprs)
+			if clause.selectClause == "*" {
+				clause.selectClause = ""
+			}
 
 			// from
-			asFromSubQuery, from := parseFrom(&nodeSelectClause.From)
+			asFromSubQuery, from, err := parseFrom(&nodeSelectClause.From)
+			if err != nil {
+				walkFuncErr = err
+				return true
+			}
+
 			if asFromSubQuery {
 				clause.fromSubQuery = from
 			} else {
@@ -314,7 +322,7 @@ func selectWalk(sql string) (*selectClause, error) {
 				clause.having = parseWhere(nodeSelectClause.Having)
 			}
 
-			return false
+			return true
 		},
 	}
 
@@ -347,32 +355,30 @@ func parseSelect(selectExprs tree.SelectExprs) string {
 	return selectFmtCtx.String()
 }
 
-func parseFrom(from *tree.From) (bool, string) {
-	asFromSubQuery := false
-
+func parseFrom(from *tree.From) (bool, string, error) {
 	switch fromTable := from.Tables[0].(type) {
 	case *tree.JoinTableExpr:
-		asFromSubQuery = true
+		return true, fromTable.String(), nil
 	case *tree.AliasedTableExpr:
 		_, ok := fromTable.Expr.(*tree.Subquery)
-		asFromSubQuery = ok
+		if ok {
+			return true, fromTable.String(), nil
+		} else {
+			return false, fromTable.String(), nil
+		}
+	default:
+		return false, "", errors.New("不支持的From类型")
 	}
-
-	return asFromSubQuery, fmt.Sprint(from.Tables)
 }
 
 func parseWhere(where *tree.Where) string {
 	return where.Expr.String()
 }
 
-func parseOrderBy(orderBy tree.OrderBy) []string {
-	orderBySlice := make([]string, 0)
-
-	for _, o := range orderBy {
-		orderBySlice = append(orderBySlice, o.Expr.String())
-	}
-
-	return orderBySlice
+func parseOrderBy(orderBy tree.OrderBy) string {
+	orderByFmtCtx := tree.NewFmtCtx(tree.FmtBareStrings)
+	orderBy[0].Format(orderByFmtCtx)
+	return orderByFmtCtx.String()
 }
 
 func parseLimit(limit *tree.Limit) (int, int, error) {

+ 11 - 3
test_sql.go

@@ -6,9 +6,17 @@ import (
 )
 
 const (
-	parseSqlInsert = `insert into students (id, name, age, rate, time, is_right) values ('aaa', 'yjp', 5, 92.5, parse_time('2024-01-01 00:00:00', '2006-01-02 15:04:05'), false)`
-	parseSqlDelete = `delete from students where id = 'aaa' AND name = 'yjp' AND age < 100 AND describe IN ('yjp')`
-	parseSqlUpdate = `update students set name = 'yjp', age = 5, age = 5, rate = 92.5, time = parse_time('2024-01-01 00:00:00', '2006-01-02 15:04:05'), is_right = false where id = 'aaa' AND name = 'yjp' AND age < 100 AND describe IN ('yjp')`
+	parseSqlInsert         = `insert into students (id, name, age, rate, time, is_right) values ('aaa', 'yjp', 5, 92.5, parse_time('2024-01-01 00:00:00', '2006-01-02 15:04:05'), false)`
+	parseSqlDelete         = `delete from students where id = 'aaa' AND name = 'yjp' AND age < 100 AND describe IN ('yjp')`
+	parseSqlUpdate         = `update students set name = 'yjp', age = 5, age = 5, rate = 92.5, time = parse_time('2024-01-01 00:00:00', '2006-01-02 15:04:05'), is_right = false where id = 'aaa' AND name = 'yjp' AND age < 100 AND describe IN ('yjp')`
+	parseSqlSelectWithJoin = `select id, name, age from students 
+	left join classes on students.id = classes.student_id
+	left join identities on students.id = identities.student_id
+	where students.id = 'aaa'
+	order by students.name desc 
+	limit 20 offset 2`
+	parseSqlSelectWithSubQuery = `select * from (select * from class where id = 'bbb') where students.id = 'aaa' and students.age = 3`
+	parseSqlSelectWithGroupBy  = `select count(*) from students group by name, age having name = 'aaa' and age = 5`
 )
 
 const (

+ 118 - 3
v1_test.go

@@ -35,7 +35,7 @@ func TestApiV1OperateParse(t *testing.T) {
 
 	parsed := operateParse(t, parseSqlInsert)
 
-	if parsed["table"].(string) != tableName {
+	if parsed["table"] != tableName {
 		t.Fatal("表名不正确")
 	}
 
@@ -47,7 +47,7 @@ func TestApiV1OperateParse(t *testing.T) {
 
 	parsed = operateParse(t, parseSqlUpdate)
 
-	if parsed["table"].(string) != tableName {
+	if parsed["table"] != tableName {
 		t.Fatal("表名不正确")
 	}
 
@@ -63,13 +63,128 @@ func TestApiV1OperateParse(t *testing.T) {
 
 	parsed = operateParse(t, parseSqlDelete)
 
-	if parsed["table"].(string) != tableName {
+	if parsed["table"] != tableName {
 		t.Fatal("表名不正确")
 	}
 
 	if parsed["where"] != `(((id = 'aaa') AND (name = 'yjp')) AND (age < 100)) AND (describe IN ('yjp',))` {
 		t.Fatal("where不正确")
 	}
+
+	parsed = operateParse(t, parseSqlSelectWithJoin)
+
+	if parsed["table"] != "" {
+		t.Fatal("table不正确")
+	}
+
+	if parsed["fromSubQuery"] != `students LEFT JOIN classes ON students.id = classes.student_id LEFT JOIN identities ON students.id = identities.student_id` {
+		t.Fatal("fromSubQuery不正确")
+	}
+
+	if parsed["selectClause"] != "id, name, age" {
+		t.Fatal("select语句不正确")
+	}
+
+	if parsed["where"] != `students.id = 'aaa'` {
+		t.Fatal("where不正确")
+	}
+
+	if parsed["orderBy"] != "students.name DESC" {
+		t.Fatal("orderBy不正确")
+	}
+
+	if parsed["groupBy"] != nil {
+		t.Fatal("groupBy不正确")
+	}
+
+	if parsed["having"] != "" {
+		t.Fatal("having不正确")
+	}
+
+	if parsed["pageNo"] != float64(2) {
+		t.Fatal("pageNo不正确")
+	}
+
+	if parsed["pageSize"] != float64(20) {
+		t.Fatal("pageSize不正确")
+	}
+
+	parsed = operateParse(t, parseSqlSelectWithSubQuery)
+
+	if parsed["table"] != "" {
+		t.Fatal("table不正确")
+	}
+
+	if parsed["fromSubQuery"] != `(SELECT * FROM class WHERE id = 'bbb')` {
+		t.Fatal("fromSubQuery不正确")
+	}
+
+	if parsed["selectClause"] != "" {
+		t.Fatal("select语句不正确")
+	}
+
+	if parsed["where"] != `(students.id = 'aaa') AND (students.age = 3)` {
+		t.Fatal("where不正确")
+	}
+
+	if parsed["orderBy"] != "" {
+		t.Fatal("orderBy不正确")
+	}
+
+	if parsed["groupBy"] != nil {
+		t.Fatal("groupBy不正确")
+	}
+
+	if parsed["having"] != "" {
+		t.Fatal("having不正确")
+	}
+
+	if parsed["pageNo"] != float64(0) {
+		t.Fatal("pageNo不正确")
+	}
+
+	if parsed["pageSize"] != float64(0) {
+		t.Fatal("pageSize不正确")
+	}
+
+	parsed = operateParse(t, parseSqlSelectWithGroupBy)
+
+	if parsed["table"] != tableName {
+		t.Fatal("table不正确")
+	}
+
+	if parsed["fromSubQuery"] != "" {
+		t.Fatal("fromSubQuery不正确")
+	}
+
+	if parsed["selectClause"] != "count(*)" {
+		t.Fatal("select语句不正确")
+	}
+
+	if parsed["where"] != "" {
+		t.Fatal("where不正确")
+	}
+
+	if parsed["orderBy"] != "" {
+		t.Fatal("orderBy不正确")
+	}
+
+	groupBy := parsed["groupBy"].([]any)
+	if groupBy[0] != "name" || groupBy[1] != "age" {
+		t.Fatal("groupBy不正确")
+	}
+
+	if parsed["having"] != "(name = 'aaa') AND (age = 5)" {
+		t.Fatal("having不正确")
+	}
+
+	if parsed["pageNo"] != float64(0) {
+		t.Fatal("pageNo不正确")
+	}
+
+	if parsed["pageSize"] != float64(0) {
+		t.Fatal("pageSize不正确")
+	}
 }
 
 func TestApiV1Operate(t *testing.T) {