TODO: parse field

This commit is contained in:
eson 2020-03-14 02:02:56 +08:00
parent 28fce16157
commit 7f137471f9
5 changed files with 264 additions and 134 deletions

16
base.go Normal file
View File

@ -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
}
}
}

84
field.go Normal file
View File

@ -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])
}

View File

@ -4,10 +4,6 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"regexp"
"strings"
"sync"
"sync/atomic"
"time" "time"
"github.com/tecbot/gorocksdb" "github.com/tecbot/gorocksdb"
@ -31,128 +27,6 @@ func init() {
EDB = NewEasyDataBase() 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} // 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) { func OpenDataBase() (*gorocksdb.DB, []*gorocksdb.ColumnFamilyHandle) {

81
table.go Normal file
View File

@ -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")
}
}

View File

@ -2,6 +2,7 @@ package main
import ( import (
"regexp" "regexp"
"strconv"
"strings" "strings"
"testing" "testing"
) )
@ -18,30 +19,104 @@ func TestParseRe(t *testing.T) {
var parseCollection []parseTest var parseCollection []parseTest
parseCollection = append(parseCollection, parseCollection = append(parseCollection,
parseTest{ 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"}, Result: []string{"a", "int"},
}, },
parseTest{ 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"}, Result: []string{"das_das", "int64"},
}, },
parseTest{ 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"}, Result: []string{"BitTkoen", "text"},
}, },
parseTest{ 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"}, Result: []string{"BitTkoen", "text"},
}, },
) )
field := &Field{}
for _, parse := range parseCollection { for _, parse := range parseCollection {
codes := strings.Split(parse.PS, ";") codes := strings.Split(parse.PS, ";")
result := ReKeyDefined.FindStringSubmatch(codes[0]) definestr := codes[0]
if len(result) >= 3 && !(result[1] == parse.Result[0] && result[2] == parse.Result[1]) { i := 0
t.Error(result)
// 检查定义头是否存在
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)
} }