From 7f137471f945e220a84dc155490223b5f9a8ab91 Mon Sep 17 00:00:00 2001
From: eson <474420502@qq.com>
Date: Sat, 14 Mar 2020 02:02:56 +0800
Subject: [PATCH] TODO: parse field

---
 base.go       |  16 +++++++
 field.go      |  84 +++++++++++++++++++++++++++++++++
 rocksdb.go    | 126 --------------------------------------------------
 table.go      |  81 ++++++++++++++++++++++++++++++++
 table_test.go |  91 ++++++++++++++++++++++++++++++++----
 5 files changed, 264 insertions(+), 134 deletions(-)
 create mode 100644 base.go
 create mode 100644 field.go
 create mode 100644 table.go

diff --git a/base.go b/base.go
new file mode 100644
index 0000000..8bfd4a9
--- /dev/null
+++ b/base.go
@@ -0,0 +1,16 @@
+package main
+
+// skipSpace
+func skipSpace(content *string, i *int) {
+
+	ct := *content
+	idx := *i
+
+	for ; idx < len(ct); idx++ {
+		if ct[idx] == ' ' {
+			continue
+		} else {
+			break
+		}
+	}
+}
diff --git a/field.go b/field.go
new file mode 100644
index 0000000..3db37f0
--- /dev/null
+++ b/field.go
@@ -0,0 +1,84 @@
+package main
+
+import (
+	"regexp"
+	"strings"
+)
+
+var fieldMap map[string]ValueType
+
+func init() {
+	fieldMap["bool"] = VT_BOOL
+
+	fieldMap["int"] = VT_INT
+	fieldMap["int16"] = VT_INT16
+	fieldMap["int32"] = VT_INT32
+	fieldMap["int64"] = VT_INT64
+
+	fieldMap["uint"] = VT_UINT
+	fieldMap["uint16"] = VT_UINT16
+	fieldMap["uint32"] = VT_UINT32
+	fieldMap["uint64"] = VT_UINT64
+
+	fieldMap["char"] = VT_CHAR
+	fieldMap["varchar"] = VT_VARCHAR
+	fieldMap["text"] = VT_TEXT
+
+	fieldMap["timestamp"] = VT_TIMESTAMP
+	fieldMap["date"] = VT_DATE
+}
+
+// ValueType 值 类型
+type ValueType int
+
+const (
+	// VT_BOOL 布尔类型
+	VT_BOOL ValueType = 00000 + iota
+)
+
+const (
+	VT_INT ValueType = 10000 + iota
+	VT_INT8
+	VT_INT16
+	VT_INT32
+	VT_INT64
+)
+
+const (
+	VT_UINT ValueType = 11000 + iota
+	VT_UINT8
+	VT_UINT16
+	VT_UINT32
+	VT_UINT64
+)
+
+const (
+	VT_CHAR ValueType = 12000 + iota
+	VT_VARCHAR
+	VT_TEXT
+)
+
+const (
+	VT_TIMESTAMP ValueType = 13000 + iota
+	VT_DATE
+)
+
+// Field 字段
+type Field struct {
+	Key []byte
+
+	VT ValueType
+
+	ID uint16
+
+	ArrayNumber int
+	IsIndex     bool
+	IsUnique    bool
+}
+
+// Parse 从字符串中解析 var a int; a = 0; a < 0 && a > 5 ;
+func (field *Field) Parse(code string) {
+	codes := strings.Split(code, ";")
+	re := regexp.MustCompile("var +([a-zA-Z_]+) +[a-zA-Z]+[8|16|32|64]{0,1}")
+	re.FindStringSubmatch(codes[0])
+}
diff --git a/rocksdb.go b/rocksdb.go
index d323064..513b0d9 100644
--- a/rocksdb.go
+++ b/rocksdb.go
@@ -4,10 +4,6 @@ import (
 	"fmt"
 	"log"
 	"os"
-	"regexp"
-	"strings"
-	"sync"
-	"sync/atomic"
 	"time"
 
 	"github.com/tecbot/gorocksdb"
@@ -31,128 +27,6 @@ func init() {
 	EDB = NewEasyDataBase()
 }
 
-func NewEasyDataBase() *EasyDataBase {
-
-	edb := &EasyDataBase{}
-	db, cfs := OpenDataBase()
-	edb.DB = db
-	edb.CFS = cfs
-	return edb
-
-}
-
-type EasyDataBase struct {
-	DB  *gorocksdb.DB
-	CFS gorocksdb.ColumnFamilyHandles
-
-	Tables    map[uint32]*Table
-	TableDict map[string]uint32
-
-	Metadata
-}
-
-type Metadata struct {
-	tidCount uint32 // int16
-}
-
-type ValueType int
-
-const (
-	VT_BOOL ValueType = 00000 + iota
-)
-
-const (
-	VT_INT ValueType = 10000 + iota
-	VT_INT8
-	VT_INT16
-	VT_INT32
-	VT_INT64
-)
-
-const (
-	VT_UINT ValueType = 11000 + iota
-	VT_UINT8
-	VT_UINT16
-	VT_UINT32
-	VT_UINT64
-)
-
-const (
-	VT_CHAR ValueType = 12000 + iota
-	VT_VARCHAR
-	VT_TEXT
-)
-
-const (
-	VT_TIMESTAMP ValueType = 13000 + iota
-	VT_DATE
-)
-
-type Field struct {
-	Key []byte
-
-	VT ValueType
-	ID uint16
-
-	IsIndex  bool
-	IsUnique bool
-}
-
-// Parse 从字符串中解析 var a int; a = 0; a < 0 && a > 5 ;
-func (field *Field) Parse(code string) {
-	codes := strings.Split(code, ";")
-	re := regexp.MustCompile("var +([a-zA-Z_]+) +[a-zA-Z]+[8|16|32|64]{0,1}")
-	re.FindStringSubmatch(codes[0])
-}
-
-// Table 表结构
-type Table struct {
-	tableLock *sync.Mutex
-
-	Name string
-	Type int
-
-	ID uint32 // uint16
-
-	IsAllKey bool
-	Fields   []*Field
-
-	fidCount uint16 // uint16
-	idxCount uint64
-	rawCount uint64
-	delCount uint64
-}
-
-// CreateField 创建字段
-func (table *Table) CreateField(key []byte, vt ValueType, isIndex bool, isUnique bool) *Field {
-
-	table.tableLock.Lock()
-	defer table.tableLock.Unlock()
-
-	field := &Field{}
-	field.ID = table.fidCount
-	field.IsIndex = isIndex
-	field.IsUnique = isUnique
-	field.Key = key
-	field.VT = vt
-
-	table.fidCount++
-
-	return field
-}
-
-// CreateTable 创建表
-func CreateTable(name string, fields []*Field) {
-	if _, ok := EDB.TableDict[name]; !ok {
-		ntid := atomic.AddUint32(&EDB.Metadata.tidCount, 1)
-		table := &Table{Name: name, ID: ntid, Type: 1}
-		table.Fields = fields
-	} else {
-		log.Println("table name is exists")
-	}
-
-}
-
 // OpenDataBase (cf-key.{tableid(2)}{fieldid(2)}) {value}{indexid(6)} = {rowid(6)} (cf-row.{tableid(2)} {row-sharding-id}){rowid(6)} = {values}
 func OpenDataBase() (*gorocksdb.DB, []*gorocksdb.ColumnFamilyHandle) {
 
diff --git a/table.go b/table.go
new file mode 100644
index 0000000..a260681
--- /dev/null
+++ b/table.go
@@ -0,0 +1,81 @@
+package main
+
+import (
+	"log"
+	"sync"
+	"sync/atomic"
+
+	"github.com/tecbot/gorocksdb"
+)
+
+func NewEasyDataBase() *EasyDataBase {
+
+	edb := &EasyDataBase{}
+	db, cfs := OpenDataBase()
+	edb.DB = db
+	edb.CFS = cfs
+	return edb
+
+}
+
+type EasyDataBase struct {
+	DB  *gorocksdb.DB
+	CFS gorocksdb.ColumnFamilyHandles
+
+	Tables    map[uint32]*Table
+	TableDict map[string]uint32
+
+	Metadata
+}
+
+type Metadata struct {
+	tidCount uint32 // int16
+}
+
+// Table 表结构
+type Table struct {
+	tableLock *sync.Mutex
+
+	Name string
+	Type int
+
+	ID uint32 // uint16
+
+	IsAllKey bool
+	Fields   []*Field
+
+	fidCount uint16 // uint16
+	idxCount uint64
+	rawCount uint64
+	delCount uint64
+}
+
+// CreateField 创建字段
+func (table *Table) CreateField(key []byte, vt ValueType, isIndex bool, isUnique bool) *Field {
+
+	table.tableLock.Lock()
+	defer table.tableLock.Unlock()
+
+	field := &Field{}
+	field.ID = table.fidCount
+	field.IsIndex = isIndex
+	field.IsUnique = isUnique
+	field.Key = key
+	field.VT = vt
+
+	table.fidCount++
+
+	return field
+}
+
+// CreateTable 创建表
+func CreateTable(name string, fields []*Field) {
+	if _, ok := EDB.TableDict[name]; !ok {
+		ntid := atomic.AddUint32(&EDB.Metadata.tidCount, 1)
+		table := &Table{Name: name, ID: ntid, Type: 1}
+		table.Fields = fields
+	} else {
+		log.Println("table name is exists")
+	}
+
+}
diff --git a/table_test.go b/table_test.go
index 4618d3c..a7bbc46 100644
--- a/table_test.go
+++ b/table_test.go
@@ -2,6 +2,7 @@ package main
 
 import (
 	"regexp"
+	"strconv"
 	"strings"
 	"testing"
 )
@@ -18,30 +19,104 @@ func TestParseRe(t *testing.T) {
 	var parseCollection []parseTest
 	parseCollection = append(parseCollection,
 		parseTest{
-			PS:     "var a int; a = 0 ; a >= 1 && a <= 4",
+			PS:     "var a int = 0; ($ >= 1 && $ <= 4)?$+1:$-1 ; $+=1",
 			Result: []string{"a", "int"},
 		},
 		parseTest{
-			PS:     "var das_das int64; das_das = 0 ; das_das >= 1 && das_das <= 4",
+			PS:     "var das_das int64; $ = 0 ; if $ >= 1 && $ <= 4 { push() }",
 			Result: []string{"das_das", "int64"},
 		},
 		parseTest{
-			PS:     "var BitTkoen text; BitTkoen = 0 ; BitTkoen >= 1 && BitTkoen <= 4",
+			PS:     "var BitTkoen []text; BitTkoen = 0 ; BitTkoen >= 1 && BitTkoen <= 4",
 			Result: []string{"BitTkoen", "text"},
 		},
 		parseTest{
-			PS:     "var BitTkoen char(24); BitTkoen = 0 ; BitTkoen >= 1 && BitTkoen <= 4",
+			PS:     "var BitTkoen [24]char; BitTkoen = 0 ; BitTkoen >= 1 && BitTkoen <= 4",
 			Result: []string{"BitTkoen", "text"},
 		},
 	)
 
+	field := &Field{}
+
 	for _, parse := range parseCollection {
 		codes := strings.Split(parse.PS, ";")
-		result := ReKeyDefined.FindStringSubmatch(codes[0])
-		if len(result) >= 3 && !(result[1] == parse.Result[0] && result[2] == parse.Result[1]) {
-			t.Error(result)
+		definestr := codes[0]
+		i := 0
+
+		// 检查定义头是否存在
+		for ; i < len(definestr); i++ {
+			if definestr[i] == 'v' && definestr[i+1] == 'a' && definestr[i+2] == 'r' {
+				i += 2
+
+				skipSpace(&definestr, &i)
+
+			GET_KEY:
+				for ; i < len(definestr); i++ {
+					switch c := definestr[i]; {
+					case (c <= 'Z' && c >= 'A' && c <= 'z' && c >= 'a') || c == '_':
+						field.Key = append(field.Key, c)
+					case c == ' ':
+						break GET_KEY
+					default:
+						t.Error("错误")
+					}
+				}
+
+				skipSpace(&definestr, &i)
+
+				for ; i < len(definestr); i++ {
+					switch c := definestr[i]; {
+					case c == ' ':
+						continue
+					case (c <= 'Z' && c >= 'A' && c <= 'z' && c >= 'a'):
+
+						var valueType []byte
+						for ; i < len(definestr); i++ {
+							cc := definestr[i]
+							if cc == ';' {
+								break
+							}
+							valueType = append(valueType, cc)
+						}
+
+					case c == '[':
+						i++
+
+						var arrayNum []byte
+					GET_ARRAY:
+						for ; i < len(definestr); i++ {
+							switch cc := definestr[i]; {
+							case cc == ']':
+								break GET_ARRAY
+							default:
+								arrayNum = append(arrayNum, cc)
+
+							}
+						}
+
+						if arrayNum == nil {
+							field.ArrayNumber = -1
+						} else {
+							num, err := strconv.Atoi(string(arrayNum))
+							if err != nil {
+								panic(err)
+							}
+							field.ArrayNumber = num
+						}
+
+					default:
+						t.Error("错误")
+					}
+				}
+
+			} else {
+				t.Error("错误")
+				break
+			}
 		}
-		t.Error(result)
+
 	}
 
+	t.Error(field)
+
 }