├── .gitignore ├── .vscode ├── launch.json └── settings.json ├── 2.0.1 ├── Monkeydb2.0.1.exe ├── install.cmd ├── monkeydb2.0.1.zip └── readme.docx ├── 2.0.2 ├── monkey.exe ├── monkeyd.exe └── shell.exe ├── beta1 ├── install.cmd ├── monkeyDB2-beta1.zip ├── monkey_beta1.exe └── readme.docx ├── common ├── common.go └── out2.go ├── config └── config.go ├── data └── log │ └── sys.log ├── delete ├── exe ├── bitset.go ├── bitset.md ├── print.go ├── project.go ├── relation.go └── row.go ├── index ├── csbt │ ├── csbt.go │ ├── cursor.go │ ├── delete.go │ ├── insert.go │ ├── insert_test.go │ ├── list.go │ ├── recovery.go │ └── select.go ├── cursor │ └── cursor.go ├── hash.go ├── index.go ├── mem │ ├── copy.go │ ├── header.go │ ├── header_test.go │ ├── leaf.go │ ├── leaf_test.go │ ├── list.go │ ├── list_test.go │ ├── malloc.go │ ├── malloc_test.go │ ├── node.go │ ├── readme.md │ ├── recovery.go │ └── util.go └── recovery.go ├── input.sql ├── install.cmd ├── install.sh ├── log ├── log.go └── log_test.go ├── memory ├── copy.go ├── error.go ├── image.go ├── image.md ├── image_test.go ├── memory.go ├── recovery.go └── recovery_test.go ├── mempool ├── a.img ├── a.txt ├── cgo_m.go ├── cgo_m_test.go ├── heap │ ├── LICENSE │ └── heap.go ├── malloc.go ├── map_windows.go.dup ├── map_windows_test.go.dup ├── recovery.go.dup └── recovery.md ├── monkey ├── monkey.go ├── monkeyd ├── monkeyd.exe~ ├── monkeyd.go ├── network ├── encode.go └── tcp.go ├── nodejs ├── example │ ├── monkey.js │ └── server.js ├── monkey.js ├── readme.md └── test.js ├── plan ├── create.go ├── createindex.go ├── createkv.go ├── delete.go ├── drop.go ├── dropindex.go ├── dump.go ├── getkv.go ├── identical.go ├── insert.go ├── plan.go ├── removekv.go ├── result.go ├── select.go ├── setkv.go ├── show.go ├── string.go ├── update.go └── where.go ├── python ├── monkey.py ├── monkey.pyc └── test.py ├── readme.md ├── recovery ├── exit.go ├── frame.go └── load.go ├── shell ├── shell.go ├── sql ├── lex │ ├── buffer.go │ ├── common.go │ ├── dfa.go │ ├── lex.go │ ├── nfa.go │ ├── stateddfa.go │ ├── statednfa.go │ ├── test │ │ ├── token.exe │ │ └── token.go │ └── tokens.go ├── lex_old │ ├── buffer.go │ ├── dfa.go │ ├── dfa_test.go │ ├── identical.go │ ├── lex.go │ ├── lex_test.go │ ├── nfa.go │ ├── nfa_test.go │ ├── reverse.go │ ├── test │ │ ├── token.exe │ │ └── token.go │ └── tokens.go └── syntax │ ├── calculate.go │ ├── checkend.go │ ├── create.go │ ├── createindex.go │ ├── createkv.go │ ├── delete.go │ ├── drop.go │ ├── dropindex.go │ ├── dump.go │ ├── filed.go │ ├── get.go │ ├── insert.go │ ├── insert_test.go │ ├── parser.go │ ├── parser_test.go │ ├── query.go │ ├── reader.go │ ├── refer.go │ ├── remove.go │ ├── select.go │ ├── set.go │ ├── show.go │ ├── string.go │ ├── update.go │ ├── value.go │ ├── value_test.go │ └── where.go ├── table ├── create.go ├── delete.go ├── drop.go ├── insert.go ├── kvtable.go ├── page.go ├── pageRecovery.go ├── reader.go ├── recovery.go ├── table.go └── util.go └── test.go /.gitignore: -------------------------------------------------------------------------------- 1 | /data 2 | /debug 3 | /*.exe 4 | /2.0.2 5 | /2.0.1 6 | /beta1 7 | /*.zip -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Launch", 6 | "type": "go", 7 | "request": "launch", 8 | "mode": "debug", 9 | "program": "${workspaceRoot}", 10 | "env": {}, 11 | "args": [] 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | } -------------------------------------------------------------------------------- /2.0.1/Monkeydb2.0.1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/2.0.1/Monkeydb2.0.1.exe -------------------------------------------------------------------------------- /2.0.1/install.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/2.0.1/install.cmd -------------------------------------------------------------------------------- /2.0.1/monkeydb2.0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/2.0.1/monkeydb2.0.1.zip -------------------------------------------------------------------------------- /2.0.1/readme.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/2.0.1/readme.docx -------------------------------------------------------------------------------- /2.0.2/monkey.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/2.0.2/monkey.exe -------------------------------------------------------------------------------- /2.0.2/monkeyd.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/2.0.2/monkeyd.exe -------------------------------------------------------------------------------- /2.0.2/shell.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/2.0.2/shell.exe -------------------------------------------------------------------------------- /beta1/install.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/beta1/install.cmd -------------------------------------------------------------------------------- /beta1/monkeyDB2-beta1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/beta1/monkeyDB2-beta1.zip -------------------------------------------------------------------------------- /beta1/monkey_beta1.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/beta1/monkey_beta1.exe -------------------------------------------------------------------------------- /beta1/readme.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/beta1/readme.docx -------------------------------------------------------------------------------- /common/common.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "os" 5 | "path/filepath" 6 | "runtime" 7 | "strings" 8 | ) 9 | 10 | var ( 11 | COMMON_DIR = "c:\\monkeydb2\\data" 12 | ) 13 | 14 | func GetCurrentDirectory() string { 15 | dir, err := filepath.Abs(filepath.Dir(os.Args[0])) 16 | if err != nil { 17 | dir = "." 18 | } 19 | return FixPath(dir) 20 | } 21 | 22 | func FixPath(s string) string { 23 | if runtime.GOOS == "windows" { 24 | return s 25 | } 26 | return strings.Replace(s, "\\", "/", -1) 27 | } 28 | 29 | func init() { 30 | if runtime.GOOS != "windows" { 31 | COMMON_DIR = "/var/local/monkeydb2/data" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/out2.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | var PRINT2 = false 8 | 9 | func Print2(str string) { 10 | if !PRINT2 { 11 | return 12 | } 13 | fmt.Println("[PERFORMANCE TEST]:", str) 14 | } 15 | -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | 7 | "../log" 8 | 9 | "../common" 10 | ) 11 | 12 | func LoadConfig(c string) map[string]interface{} { 13 | b, err := ioutil.ReadFile(common.FixPath(common.COMMON_DIR + "/" + c + ".json")) 14 | if err != nil { 15 | return nil 16 | } 17 | var m map[string]interface{} 18 | err = json.Unmarshal(b, &m) 19 | if err != nil { 20 | return nil 21 | } 22 | log.WriteLog("sys", m) 23 | return m 24 | } 25 | -------------------------------------------------------------------------------- /delete: -------------------------------------------------------------------------------- 1 | monkeyd 2 | -------------------------------------------------------------------------------- /exe/bitset.md: -------------------------------------------------------------------------------- 1 | # BitSet data structure 2 | *bitset* is a library written in [golang](http://golang.org) implementing a BitSet data structure. 3 | 4 | # Usage 5 | First install the library with 6 | ``` 7 | go get xojoc.pw/bitset 8 | ``` 9 | 10 | As an example let's list all the composite numbers below 10: 11 | ``` 12 | package main 13 | 14 | import ( 15 | "fmt" 16 | "xojoc.pw/bitset" 17 | ) 18 | 19 | func main() { 20 | c := &bitset.BitSet{} 21 | // Set all prime numbers to true. 22 | c.Set(2) 23 | c.Set(3) 24 | c.Set(5) 25 | c.Set(7) 26 | c.ToggleRange(1,10+1) 27 | for i := 1; i < c.Len(); i++ { 28 | if c.Get(i) { 29 | fmt.Printf("%d is composite\n", i) 30 | } 31 | } 32 | } 33 | ``` 34 | Output: 35 | ``` 36 | 1 is composite 37 | 4 is composite 38 | 6 is composite 39 | 8 is composite 40 | 9 is composite 41 | 10 is composite 42 | ``` 43 | see [godoc](http://godoc.org/xojoc.pw/bitset) for the complete documentation. 44 | 45 | # Why? 46 | 47 | * Great API 48 | * 100% test coverage 49 | * [Great documentation](http://godoc.org/xojoc.pw/bitset) 50 | 51 | Also see [why use xojoc/bitset and not math/big](http://typed.pw/a/29). 52 | 53 | # Who? 54 | *bitset* was written by Alexandru Cojocaru (http://xojoc.pw). 55 | 56 | # License 57 | *bitset* is in the Public Domain. 58 | 59 | # [Donate](http://xojoc.pw/donate.html) -------------------------------------------------------------------------------- /exe/print.go: -------------------------------------------------------------------------------- 1 | package exe 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "unsafe" 7 | ) 8 | 9 | func (v *Value) Print() { 10 | switch v.Kind { 11 | case INT: 12 | i := *(*int)(unsafe.Pointer(&v.Raw[0])) 13 | fmt.Print(i) 14 | case FLOAT: 15 | f := *(*float64)(unsafe.Pointer(&v.Raw[0])) 16 | fmt.Print(f) 17 | case STRING: 18 | s := (string)(v.Raw) 19 | fmt.Print(s) 20 | } 21 | } 22 | 23 | func (v *Value) StrLen() int { 24 | switch v.Kind { 25 | case INT: 26 | i := *(*int)(unsafe.Pointer(&v.Raw[0])) 27 | return len((strconv.Itoa(i))) 28 | case FLOAT: 29 | f := *(*float64)(unsafe.Pointer(&v.Raw[0])) 30 | return len((strconv.FormatFloat(f, 'f', -1, 64))) 31 | case STRING: 32 | runeLen := len([]rune(string(v.Raw))) 33 | rawLen := len(v.Raw) 34 | return (runeLen + rawLen) / 2 35 | } 36 | return 8 37 | } 38 | 39 | func (r *Relation) Print() { 40 | 41 | if r == nil { 42 | return 43 | } 44 | var maxLen []int 45 | var colN int 46 | 47 | if r.ColumnNames != nil && len(r.ColumnNames) != 0 { 48 | colN = len(r.ColumnNames) 49 | } else if r.Rows != nil && len(r.Rows) != 0 { 50 | colN = len(r.Rows[0]) 51 | } else { 52 | return 53 | } 54 | if r.Rows != nil && len(r.Rows) != 0 { 55 | maxLen = make([]int, colN) 56 | for i := 0; i < len(r.Rows); i++ { 57 | for j := 0; j < colN; j++ { 58 | if l := r.Rows[i][j].StrLen(); l > maxLen[j] { 59 | maxLen[j] = l 60 | } 61 | } 62 | } 63 | 64 | } 65 | if r.ColumnNames != nil && len(r.ColumnNames) != 0 { 66 | if maxLen == nil || len(maxLen) == 0 { 67 | maxLen = make([]int, colN) 68 | } 69 | for i := 0; i < colN; i++ { 70 | if l := len([]byte(r.ColumnNames[i])); l > maxLen[i] { 71 | maxLen[i] = l 72 | } 73 | } 74 | } 75 | if r.ColumnNames != nil && len(r.ColumnNames) != 0 { 76 | fmt.Print("_") 77 | for i := 0; i < colN; i++ { 78 | for j := 0; j < maxLen[i]; j++ { 79 | fmt.Print("_") 80 | } 81 | fmt.Print("_") 82 | } 83 | fmt.Print("\n") 84 | 85 | fmt.Print("|") 86 | for i := 0; i < colN; i++ { 87 | fmt.Printf("%s", r.ColumnNames[i]) 88 | for k := 0; k < maxLen[i]-len([]byte(r.ColumnNames[i])); k++ { 89 | fmt.Print(" ") 90 | } 91 | fmt.Print("|") 92 | } 93 | fmt.Print("\n|") 94 | for i := 0; i < colN; i++ { 95 | for j := 0; j < maxLen[i]; j++ { 96 | fmt.Print("-") 97 | } 98 | fmt.Print("|") 99 | } 100 | fmt.Print("\n") 101 | } 102 | 103 | if r != nil && len(r.Rows) != 0 { 104 | for rw := 0; rw < len(r.Rows); rw++ { 105 | fmt.Print("|") 106 | for i := 0; i < colN; i++ { 107 | r.Rows[rw][i].Print() 108 | for k := 0; k < maxLen[i]-r.Rows[rw][i].StrLen(); k++ { 109 | fmt.Print(" ") 110 | } 111 | fmt.Print("|") 112 | } 113 | fmt.Print("\n|") 114 | for i := 0; i < colN; i++ { 115 | for j := 0; j < maxLen[i]; j++ { 116 | fmt.Print("-") 117 | } 118 | fmt.Print("|") 119 | } 120 | fmt.Print("\n") 121 | } 122 | } 123 | 124 | // for i := 0; i < colN; i++ { 125 | // for j := 0; j < maxLen[i]; j++ { 126 | // fmt.Print("-") 127 | // } 128 | // fmt.Print("|") 129 | // } 130 | // fmt.Print("|\n") 131 | } 132 | -------------------------------------------------------------------------------- /exe/project.go: -------------------------------------------------------------------------------- 1 | package exe 2 | 3 | func (r *Relation) Project(columnNames []string) *Relation { 4 | 5 | ids := make([]int, 0) 6 | for i := 0; i < len(columnNames); i++ { 7 | for k, v := range r.ColumnNames { 8 | if v == columnNames[i] { 9 | ids = append(ids, k) 10 | } 11 | } 12 | } 13 | newR := NewRelation() 14 | newR.SetColumnNames(columnNames) 15 | for _, r := range r.Rows { 16 | row := []Value{} 17 | for i := 0; i < len(ids); i++ { 18 | row = append(row, r[ids[i]]) 19 | } 20 | newR.AddRow(row) 21 | } 22 | return newR 23 | } 24 | -------------------------------------------------------------------------------- /exe/relation.go: -------------------------------------------------------------------------------- 1 | package exe 2 | 3 | const ( 4 | INT = iota 5 | FLOAT 6 | STRING 7 | ARRAY 8 | OBJECT 9 | ) 10 | 11 | type Relation struct { 12 | ColumnNames []string 13 | Rows []Row 14 | } 15 | 16 | type Row []Value 17 | 18 | type Value struct { 19 | Kind int 20 | Raw []byte 21 | } 22 | 23 | func NewRelation() *Relation { 24 | return &Relation{} 25 | } 26 | 27 | func (r *Relation) AddRow(row Row) { 28 | r.Rows = append(r.Rows, row) 29 | } 30 | 31 | func (r *Relation) SetColumnNames(strs []string) { 32 | r.ColumnNames = append([]string{}, strs...) 33 | } 34 | 35 | func (r *Relation) SetColumnNameAlias(n int, alias string) { 36 | if n < len(r.ColumnNames) { 37 | r.ColumnNames[n] = alias 38 | } 39 | } 40 | 41 | func (r *Relation) RowNum() int { 42 | return len(r.Rows) 43 | } 44 | 45 | func (r *Relation) ColumnNum() int { 46 | if r.ColumnNames != nil { 47 | return len(r.ColumnNames) 48 | } 49 | if len(r.Rows) == 0 { 50 | return 0 51 | } 52 | return len(r.Rows[0]) 53 | } 54 | 55 | func NewRow(values []Value) Row { 56 | return Row(values) 57 | } 58 | 59 | func NewValue(kind int, raw []byte) Value { 60 | return Value{ 61 | Kind: kind, 62 | Raw: raw, 63 | } 64 | } 65 | 66 | func StringToType(s string) int { 67 | switch s { 68 | case "INT", "int": 69 | return INT 70 | case "FLOAT", "float": 71 | return FLOAT 72 | case "STRING", "string": 73 | return STRING 74 | case "ARRAY", "array": 75 | return ARRAY 76 | case "OBJECT", "object": 77 | return OBJECT 78 | } 79 | return STRING 80 | } 81 | 82 | func TypeToString(i int) string { 83 | switch i { 84 | case INT: 85 | return "INT" 86 | case FLOAT: 87 | return "FLOAT" 88 | case STRING: 89 | return "STRING" 90 | case ARRAY: 91 | return "ARRAY" 92 | case OBJECT: 93 | return "OBJECT" 94 | } 95 | return "UNKOWN" 96 | } 97 | -------------------------------------------------------------------------------- /exe/row.go: -------------------------------------------------------------------------------- 1 | package exe 2 | 3 | func (r *Relation) GetRow(n int) *Row { 4 | return &r.Rows[0] 5 | } 6 | 7 | func (r *Row) GetFieldById(n int) *Value { 8 | return &((*r)[n]) 9 | } 10 | 11 | func (r *Relation) GetFieldByName(i int, n string) *Value { 12 | if r.ColumnNames == nil { 13 | return nil 14 | } 15 | for k, v := range r.ColumnNames { 16 | if v == n { 17 | return &r.Rows[i][k] 18 | } 19 | } 20 | return nil 21 | } 22 | 23 | func (r *Relation) GetFieldById(i int, n int) *Value { 24 | return r.Rows[i].GetFieldById(n) 25 | } 26 | -------------------------------------------------------------------------------- /index/csbt/csbt.go: -------------------------------------------------------------------------------- 1 | // DCSBT Index @InsZVA 2015 2 | // Based on WANG Sheng, QIN Xiaolin, SHEN Yao, et al. Research on durable CSB+-tree indexing technology. Journal of Frontiers of Computer Science and Technology, 2015, 9(2): 182-192. 3 | 4 | package csbt 5 | 6 | import ( 7 | "../mem" 8 | ) 9 | 10 | type leaf struct { 11 | isLeaf byte 12 | keyNum byte 13 | reserved uint16 14 | key [3]uint32 15 | value [3]uintptr 16 | left, right uint 17 | reserved2 uint 18 | } 19 | 20 | type Node struct { 21 | IsLeaf byte 22 | Reversed byte 23 | KeyNum uint16 24 | Key [13]uint32 25 | Child uint 26 | } 27 | 28 | type Header struct { 29 | Root uint 30 | Min, Max uint 31 | } 32 | 33 | type DCSBT struct { 34 | MB *mem.ManagedBlock 35 | } 36 | 37 | func NewDCSBT() *DCSBT { 38 | t := &DCSBT{ 39 | MB: mem.NewManagedBlock(), 40 | } 41 | leaf := t.MB.NewLeaves(1) 42 | t.MB.SetRoot(leaf) 43 | t.MB.SetMin(leaf) 44 | t.MB.SetMax(leaf) 45 | return t 46 | } 47 | -------------------------------------------------------------------------------- /index/csbt/cursor.go: -------------------------------------------------------------------------------- 1 | package csbt 2 | 3 | import ( 4 | "../cursor" 5 | ) 6 | 7 | type Cursor struct { 8 | tree *DCSBT 9 | leaf uint 10 | offset int 11 | } 12 | 13 | func (c *Cursor) Next() cursor.Cursor { 14 | keyNum := c.tree.MB.GetLeafKeyNum(c.leaf) 15 | if c.offset < keyNum { 16 | return &Cursor{ 17 | tree: c.tree, 18 | leaf: c.leaf, 19 | offset: c.offset + 1, 20 | } 21 | } 22 | l := c.tree.MB.GetLeafRight(c.leaf) 23 | if l == 0 { 24 | return nil 25 | } 26 | return &Cursor{ 27 | tree: c.tree, 28 | leaf: l, 29 | offset: 0, 30 | } 31 | } 32 | 33 | func (c *Cursor) Prev() cursor.Cursor { 34 | if c.offset > 0 { 35 | return &Cursor{ 36 | tree: c.tree, 37 | leaf: c.leaf, 38 | offset: c.offset - 1, 39 | } 40 | } 41 | l := c.tree.MB.GetLeafLeft(c.leaf) 42 | if l == 0 { 43 | return nil 44 | } 45 | return &Cursor{ 46 | tree: c.tree, 47 | leaf: l, 48 | offset: 0, 49 | } 50 | } 51 | 52 | // Return uintptr or 0 if deleted 53 | func (c *Cursor) Read() (uintptr, uint) { 54 | 55 | i := uint(c.tree.MB.GetLeafValue(c.leaf, c.offset)) 56 | p := uint(uintptr(i >> 24)) 57 | offset := i & 0x0000000000ffffff // < 16MB 58 | return uintptr(p), offset 59 | } 60 | 61 | func (c *Cursor) Delete() { 62 | c.tree.MB.SetLeafValue(c.leaf, c.offset, 0) 63 | } 64 | 65 | func (c *Cursor) Write(p uintptr, offset uint) { 66 | v := uint(0) 67 | v = uint(p) << 24 68 | v = v | offset 69 | c.tree.MB.SetLeafValue(c.leaf, c.offset, uintptr(v)) 70 | } 71 | -------------------------------------------------------------------------------- /index/csbt/delete.go: -------------------------------------------------------------------------------- 1 | package csbt 2 | 3 | //Delete is only to set the value to 0 4 | func (t *DCSBT) Delete(key uint32) { 5 | c := t.Select(key) 6 | if c != nil { 7 | c.Write(0, 0) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /index/csbt/insert_test.go: -------------------------------------------------------------------------------- 1 | package csbt 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestInsert(t *testing.T) { 9 | tree := NewDCSBT() 10 | for i := 0; i < 100; i++ { 11 | tree.Insert(uint32(i), uintptr(i)) 12 | } 13 | nd95 := tree.FindLeaf(94, false) 14 | l95 := tree.MB.GetChild(nd95.node, nd95.offset) 15 | l95Next := tree.MB.GetLeafRight(l95) 16 | fmt.Println(tree.MB.GetLeafKey(l95Next, 0)) 17 | } 18 | -------------------------------------------------------------------------------- /index/csbt/list.go: -------------------------------------------------------------------------------- 1 | package csbt 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func (t *DCSBT) ListByLevel() { 8 | root := t.MB.GetRoot() 9 | if t.MB.IsLeaf(root) { 10 | t.PrintLeaf(root, "") 11 | } else { 12 | t.PrintNode(root, "") 13 | } 14 | } 15 | 16 | func (t *DCSBT) PrintLeaf(leaf uint, tabs string) { 17 | fmt.Println(tabs + "Leaf {") 18 | keyNum := t.MB.GetLeafKeyNum(leaf) 19 | fmt.Println(tabs+"\tKeyNum:", keyNum) 20 | fmt.Print(tabs + "\tKeys: ") 21 | for i := 0; i < keyNum; i++ { 22 | fmt.Print(t.MB.GetLeafKey(leaf, i), " ") 23 | } 24 | fmt.Print("\n") 25 | fmt.Println(tabs + "}") 26 | } 27 | 28 | func (t *DCSBT) PrintNode(node uint, tabs string) { 29 | fmt.Println(tabs + "Node {") 30 | keyNum := t.MB.GetNodeKeyNum(node) 31 | fmt.Println(tabs+"\tKeyNum:", keyNum) 32 | fmt.Println(tabs + "\tKeys: ") 33 | for i := 0; i < keyNum; i++ { 34 | c := t.MB.GetChild(node, i) 35 | if t.MB.IsLeaf(c) { 36 | t.PrintLeaf(c, tabs+"\t") 37 | } else { 38 | t.PrintNode(t.MB.GetChild(node, i), tabs+"\t") 39 | } 40 | fmt.Println(tabs+"\t", t.MB.GetNodeKey(node, i)) 41 | } 42 | t.PrintLeaf(t.MB.GetChild(node, keyNum), tabs+"\t") 43 | fmt.Print("\n") 44 | fmt.Println(tabs + "}") 45 | } 46 | -------------------------------------------------------------------------------- /index/csbt/recovery.go: -------------------------------------------------------------------------------- 1 | package csbt 2 | 3 | import ( 4 | "strconv" 5 | 6 | "../../log" 7 | "../../memory" 8 | ) 9 | 10 | func (t *DCSBT) Recovery() { 11 | for l := t.MB.GetMin(); l != 0; l = t.MB.GetLeafRight(l) { 12 | keyNum := t.MB.GetLeafKeyNum(l) 13 | for i := 0; i < keyNum; i++ { 14 | oldPtr := t.MB.GetLeafValue(l, i) 15 | p := uint(oldPtr) >> 24 16 | offset := uint(oldPtr) & 0x0000000000ffffff 17 | newPtr, ok := memory.RecoveryTable[uintptr(p)] 18 | if !ok { 19 | log.WriteLog("err", "Recovery index error: "+strconv.Itoa(int(oldPtr))) 20 | t.MB.SetLeafValue(l, i, 0) 21 | continue 22 | } 23 | newV := uint(newPtr.RawPtr) << 24 24 | newV |= offset 25 | t.MB.SetLeafValue(l, i, uintptr(newV)) 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /index/csbt/select.go: -------------------------------------------------------------------------------- 1 | package csbt 2 | 3 | import ( 4 | "../cursor" 5 | ) 6 | 7 | // Select will return a cursor if found and return nil else 8 | func (t *DCSBT) Select(k uint32) cursor.Cursor { 9 | var l uint 10 | n := t.FindLeaf(k, false) 11 | if n.level == 0 { 12 | l = t.MB.GetRoot() 13 | } else { 14 | l = t.MB.GetChild(n.node, n.offset) 15 | } 16 | if l == 0 { 17 | return nil 18 | } 19 | for i := 0; i < t.MB.GetLeafKeyNum(l); i++ { 20 | if t.MB.GetLeafKey(l, i) == k { 21 | return &Cursor{ 22 | tree: t, 23 | leaf: l, 24 | offset: i, 25 | } 26 | } 27 | } 28 | return nil 29 | } 30 | -------------------------------------------------------------------------------- /index/cursor/cursor.go: -------------------------------------------------------------------------------- 1 | package cursor 2 | 3 | type Cursor interface { 4 | Next() Cursor 5 | Prev() Cursor 6 | Read() (uintptr, uint) 7 | Delete() 8 | Write(uintptr, uint) 9 | } 10 | -------------------------------------------------------------------------------- /index/hash.go: -------------------------------------------------------------------------------- 1 | package index 2 | 3 | func BKDRHash(bytes []byte) uint32 { 4 | seed := uint32(13131313) 5 | hash := uint32(0) 6 | for i := 0; i < len(bytes); i++ { 7 | hash = hash*seed + uint32(bytes[i]) 8 | } 9 | return hash & 0x7fffffff 10 | } 11 | -------------------------------------------------------------------------------- /index/index.go: -------------------------------------------------------------------------------- 1 | package index 2 | 3 | import ( 4 | "./csbt" 5 | "./cursor" 6 | ) 7 | 8 | const ( 9 | PRIMARY = iota 10 | UNIQUE 11 | HASH //TODO 12 | ) 13 | 14 | var IndexList []*Index 15 | 16 | type Indexer interface { 17 | Select(key uint32) cursor.Cursor 18 | Insert(k uint32, v uintptr) error 19 | Delete(k uint32) 20 | Recovery() 21 | } 22 | 23 | type Index struct { 24 | Name string 25 | Kind int 26 | Database string 27 | Table string 28 | Key string 29 | I Indexer 30 | } 31 | 32 | func CreateIndex(kind int, database string, table string, key string) *Index { 33 | if kind == -1 { 34 | return nil 35 | } 36 | i := &Index{ 37 | Kind: kind, 38 | Database: database, 39 | Table: table, 40 | Key: key, 41 | } 42 | switch i.Kind { 43 | case PRIMARY: 44 | i.I = csbt.NewDCSBT() 45 | case UNIQUE: 46 | i.I = csbt.NewDCSBT() 47 | } 48 | IndexList = append(IndexList, i) 49 | return i 50 | } 51 | 52 | func (i *Index) Delete() { 53 | for k, v := range IndexList { 54 | if v.Database == i.Database && v.Key == i.Key && v.Table == i.Table { 55 | IndexList = append(IndexList[0:k], IndexList[k+1:]...) 56 | v.I.(*csbt.DCSBT).MB.Delete() //HASH 57 | return 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /index/mem/copy.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | func (mb *ManagedBlock) Copy(dst uint, src uint, length int) { 4 | data, _ := mb.Read(src, uint(length)) 5 | mb.Write(dst, data) 6 | } 7 | -------------------------------------------------------------------------------- /index/mem/header.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import ( 4 | "../../log" 5 | ) 6 | 7 | const ( 8 | // These constant shows where the indexheader was storaged 9 | ROOT_POINTER_OFFSET = 0 10 | MIN_POINTER_OFFSET = 8 11 | MAX_POINTER_OFFSET = 16 12 | FREE_LIST_OFFSET = 24 //duplicated 13 | FREE_OFFSET = 24 14 | ) 15 | 16 | func (mb *ManagedBlock) GetRoot() uint { 17 | data, err := mb.Read(ROOT_POINTER_OFFSET, 8) 18 | if err != nil { 19 | log.WriteLog("err", err.Error()) 20 | } 21 | return bytes2uint(data) 22 | } 23 | 24 | func (mb *ManagedBlock) SetRoot(r uint) { 25 | data := uint2bytes(r) 26 | _, err := mb.Write(ROOT_POINTER_OFFSET, data) 27 | if err != nil { 28 | log.WriteLog("err", err.Error()) 29 | } 30 | } 31 | 32 | func (mb *ManagedBlock) GetFreePos() uint { 33 | data, err := mb.Read(FREE_LIST_OFFSET, 8) 34 | if err != nil { 35 | log.WriteLog("err", err.Error()) 36 | } 37 | return bytes2uint(data) 38 | } 39 | 40 | func (mb *ManagedBlock) AddFreePos(i uint) { 41 | p := mb.GetFreePos() 42 | p += i 43 | _, err := mb.Write(FREE_LIST_OFFSET, uint2bytes(p)) 44 | if err != nil { 45 | log.WriteLog("err", err.Error()) 46 | } 47 | } 48 | 49 | func (mb *ManagedBlock) GetMin() uint { 50 | data, err := mb.Read(MIN_POINTER_OFFSET, 8) 51 | if err != nil { 52 | log.WriteLog("err", err.Error()) 53 | } 54 | return bytes2uint(data) 55 | } 56 | 57 | func (mb *ManagedBlock) SetMin(p uint) { 58 | data := uint2bytes(p) 59 | _, err := mb.Write(MIN_POINTER_OFFSET, data) 60 | if err != nil { 61 | log.WriteLog("err", err.Error()) 62 | } 63 | } 64 | 65 | func (mb *ManagedBlock) GetMax() uint { 66 | data, err := mb.Read(MAX_POINTER_OFFSET, 8) 67 | if err != nil { 68 | log.WriteLog("err", err.Error()) 69 | } 70 | return bytes2uint(data) 71 | } 72 | 73 | func (mb *ManagedBlock) SetMax(p uint) { 74 | data := uint2bytes(p) 75 | _, err := mb.Write(MAX_POINTER_OFFSET, data) 76 | if err != nil { 77 | log.WriteLog("err", err.Error()) 78 | } 79 | } 80 | 81 | func (mb *ManagedBlock) GetFreeList(i int) uint { 82 | data, err := mb.Read(FREE_LIST_OFFSET+8*uint(i), 8) 83 | if err != nil { 84 | log.WriteLog("err", err.Error()) 85 | } 86 | return bytes2uint(data) 87 | } 88 | -------------------------------------------------------------------------------- /index/mem/header_test.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import "testing" 4 | 5 | func Test_bytes2int(t *testing.T) { 6 | tmp := uint(7898855204580) 7 | r := bytes2uint(uint2bytes(tmp)) 8 | if r != tmp { 9 | t.Error(r) 10 | } 11 | } -------------------------------------------------------------------------------- /index/mem/leaf.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import ( 4 | "../../log" 5 | ) 6 | 7 | // This struct is only to refrence to programer 8 | type leaf struct { 9 | isLeaf byte 10 | keyNum byte 11 | reserved uint16 12 | key [3]uint32 13 | value [3]uintptr 14 | left, right uint 15 | reserved2 uint 16 | } 17 | 18 | func (mb *ManagedBlock) InitLeaf(p uint) { 19 | mb.Write(p, make([]byte, 64)) 20 | mb.Write(p, []byte{1}) 21 | } 22 | 23 | func (mb *ManagedBlock) SetLeaf(p uint) { 24 | mb.Write(p, []byte{1}) 25 | } 26 | 27 | func (mb *ManagedBlock) IsLeaf(p uint) bool { 28 | data, err := mb.Read(p, 1) 29 | if err != nil { 30 | log.WriteLog("err", err.Error()) 31 | } 32 | return data[0] > 0 33 | } 34 | 35 | func (mb *ManagedBlock) NewLeaves(n int) uint { 36 | leaves := mb.Malloc(n) 37 | for i := 0; i < n; i++ { 38 | mb.InitLeaf(leaves + uint(i)*64) 39 | } 40 | return leaves 41 | } 42 | 43 | func (mb *ManagedBlock) GetLeafKeyNum(leaf uint) int { 44 | data, err := mb.Read(leaf+1, 1) 45 | if err != nil { 46 | log.WriteLog("err", err.Error()) 47 | } 48 | return int(data[0]) 49 | } 50 | 51 | func (mb *ManagedBlock) SetLeafKeyNum(leaf uint, keyNum int) { 52 | mb.Write(leaf+1, []byte{byte(keyNum)}) 53 | } 54 | 55 | func (mb *ManagedBlock) GetLeafKey(leaf uint, index int) uint32 { 56 | data, err := mb.Read(leaf+4+uint(index)*4, 4) 57 | if err != nil { 58 | log.WriteLog("err", err.Error()) 59 | } 60 | return bytes2uint32(data) 61 | } 62 | 63 | func (mb *ManagedBlock) SetLeafKey(leaf uint, index int, key uint32) { 64 | mb.Write(leaf+4+uint(index)*4, uint322bytes(key)) 65 | } 66 | 67 | func (mb *ManagedBlock) GetLeafValue(leaf uint, index int) uintptr { 68 | data, err := mb.Read(leaf+16+uint(index)*8, 8) 69 | if err != nil { 70 | log.WriteLog("err", err.Error()) 71 | } 72 | return uintptr(bytes2uint(data)) 73 | } 74 | 75 | func (mb *ManagedBlock) SetLeafValue(leaf uint, index int, value uintptr) { 76 | mb.Write(leaf+16+uint(index)*8, uint2bytes(uint(value))) 77 | } 78 | 79 | func (mb *ManagedBlock) GetLeafLeft(leaf uint) uint { 80 | data, err := mb.Read(leaf+40, 8) 81 | if err != nil { 82 | log.WriteLog("err", err.Error()) 83 | } 84 | return bytes2uint(data) 85 | } 86 | 87 | func (mb *ManagedBlock) SetLeafLeft(leaf, left uint) { 88 | mb.Write(leaf+40, uint2bytes(uint(left))) 89 | } 90 | 91 | func (mb *ManagedBlock) GetLeafRight(leaf uint) uint { 92 | data, err := mb.Read(leaf+48, 8) 93 | if err != nil { 94 | log.WriteLog("err", err.Error()) 95 | } 96 | return bytes2uint(data) 97 | } 98 | 99 | func (mb *ManagedBlock) SetLeafRight(leaf, right uint) { 100 | mb.Write(leaf+48, uint2bytes(uint(right))) 101 | } 102 | -------------------------------------------------------------------------------- /index/mem/leaf_test.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestNewLeaves(t *testing.T) { 8 | mb := NewManagedBlock() 9 | leaf := mb.NewLeaves(1) 10 | mb.SetLeafKeyNum(leaf, 1) 11 | mb.SetLeafKey(leaf, 0, 156) 12 | if mb.GetLeafKey(leaf, 0) != 156 { 13 | t.Error(mb.GetLeafKey(leaf, 0)) 14 | } 15 | } -------------------------------------------------------------------------------- /index/mem/list.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import ( 4 | "../../log" 5 | "../../memory" 6 | ) 7 | 8 | const ( 9 | MAX_POWER = 14 10 | NORMAL_SIZE = 16 * 1024 * 32 11 | NORMAL_SIZE_2X = 2 * NORMAL_SIZE 12 | ) 13 | 14 | type ManagedBlock struct { 15 | memory.DataBlock 16 | } 17 | 18 | // This struct is only to refrence to programer 19 | type header struct { 20 | root uint 21 | min uint 22 | max uint //Not used now 23 | //freeList [MAX_POWER]uint //duplicated 24 | fp uint 25 | } 26 | 27 | type freeListElement struct { 28 | next uint 29 | data interface{} 30 | } 31 | 32 | func NewManagedBlockWithSize(size int) *ManagedBlock { 33 | db, err := memory.CreateImage(size) 34 | if err != nil { 35 | log.WriteLog("err", err.Error()) 36 | } 37 | mb := &ManagedBlock{ //This struct actually save 8 byte pointer only 38 | DataBlock: *db, 39 | } 40 | mb.SetRoot(0) 41 | mb.Write(FREE_OFFSET, uint2bytes(64)) 42 | //mb.Init() Full CSBTree will make no garbage 43 | return mb 44 | } 45 | 46 | func NewManagedBlock() *ManagedBlock { 47 | return NewManagedBlockWithSize(NORMAL_SIZE) 48 | } 49 | 50 | func (mb *ManagedBlock) ListGetNext(e uint) uint { 51 | data, err := mb.Read(e, 8) 52 | if err != nil { 53 | log.WriteLog("err", err.Error()) 54 | } 55 | return bytes2uint(data) 56 | } 57 | 58 | func (mb *ManagedBlock) ListGetBack(list uint) uint { 59 | ret := list 60 | for e := list; e != 0; e = mb.ListGetNext(e) { 61 | ret = e 62 | } 63 | return ret 64 | } 65 | 66 | func (mb *ManagedBlock) ListGetLength(n int) int { 67 | i := 0 68 | for e := mb.GetFreeList(n); e != 0; e = mb.ListGetNext(e) { 69 | i++ 70 | } 71 | return i 72 | } 73 | 74 | func (mb *ManagedBlock) ListPushBack(n int, e uint) { 75 | list := mb.GetFreeList(n) 76 | back := mb.ListGetBack(list) 77 | if back == 0 { 78 | mb.Write(FREE_LIST_OFFSET+8*uint(n), uint2bytes(e)) 79 | } else { 80 | mb.Write(back, uint2bytes(e)) 81 | } 82 | mb.Write(e, uint2bytes(0)) 83 | } 84 | 85 | func (mb *ManagedBlock) ListPopBack(n int) uint { 86 | list := mb.GetFreeList(n) 87 | next := list 88 | p := next 89 | if p == 0 { 90 | return 0 91 | } 92 | i := 0 93 | next = mb.ListGetNext(next) 94 | if next == 0 { // Only one element 95 | mb.Write(FREE_LIST_OFFSET+8*uint(n), uint2bytes(0)) 96 | return list 97 | } 98 | for ; next != 0; next = mb.ListGetNext(next) { 99 | if i > 0 { 100 | p = mb.ListGetNext(p) 101 | } 102 | i++ 103 | } 104 | ret := mb.ListGetNext(p) 105 | mb.Write(p, uint2bytes(0)) 106 | return ret 107 | } 108 | 109 | func (mb *ManagedBlock) ListPopFront(n int) uint { 110 | front := mb.GetFreeList(n) 111 | if front == 0 { 112 | return 0 113 | } 114 | next := mb.ListGetNext(front) 115 | mb.Write(FREE_LIST_OFFSET+8*uint(n), uint2bytes(next)) 116 | return front 117 | } 118 | 119 | func (mb *ManagedBlock) ListPushFront(n int, e uint) { 120 | front := mb.GetFreeList(n) 121 | if front == 0 { 122 | mb.Write(e, uint2bytes(0)) 123 | mb.Write(FREE_LIST_OFFSET+8*uint(n), uint2bytes(e)) 124 | return 125 | } 126 | mb.Write(e, uint2bytes(front)) 127 | mb.Write(FREE_LIST_OFFSET+8*uint(n), uint2bytes(e)) 128 | return 129 | } 130 | 131 | func (mb *ManagedBlock) Init() { 132 | used := uint(24 + 8*MAX_POWER) 133 | for { 134 | for i := 0; i < MAX_POWER; i++ { 135 | if mb.DataBlock.Size-used < 64*uint(i+1) { 136 | return 137 | } 138 | mb.ListPushFront(i, used) 139 | used += 64 * uint(i+1) 140 | } 141 | } 142 | mb.SetRoot(0) 143 | } 144 | -------------------------------------------------------------------------------- /index/mem/list_test.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import ( 4 | "testing" 5 | "fmt" 6 | ) 7 | 8 | var mb = NewManagedBlock() 9 | 10 | func TestNewManagedBlock(t *testing.T) { 11 | for i := 0;i < MAX_POWER;i++ { 12 | fmt.Println(mb.ListGetLength(i)) 13 | } 14 | // memory.SyncAllImageToFile() 15 | } 16 | 17 | func TestListPopBack(t *testing.T) { 18 | old := mb.ListGetLength(1) 19 | mb.ListPopBack(1) 20 | if old - mb.ListGetLength(1) != 1 { 21 | t.Error(old) 22 | } 23 | for i := 0;i < old - 2;i++ { 24 | (mb.ListPopBack(1)) 25 | } 26 | if mb.ListGetBack(mb.GetFreeList(1)) == 0 { 27 | t.Error(mb.ListGetBack(mb.GetFreeList(1))) 28 | } 29 | mb.ListPopBack(1) 30 | if mb.ListGetBack(mb.GetFreeList(1)) != 0 { 31 | t.Error(mb.ListGetBack(mb.GetFreeList(1))) 32 | } 33 | } 34 | 35 | func TestListPopFront(t *testing.T) { 36 | mb = NewManagedBlock() 37 | old := mb.ListGetLength(1) 38 | mb.ListPopFront(1) 39 | if old - mb.ListGetLength(1) != 1 { 40 | t.Error(old) 41 | } 42 | for i := 0;i < old - 2;i++ { 43 | (mb.ListPopFront(1)) 44 | } 45 | if mb.ListGetBack(mb.GetFreeList(1)) == 0 { 46 | t.Error(mb.ListGetBack(mb.GetFreeList(1))) 47 | } 48 | mb.ListPopFront(1) 49 | if mb.ListGetBack(mb.GetFreeList(1)) != 0 { 50 | t.Error(mb.ListGetBack(mb.GetFreeList(1))) 51 | } 52 | } -------------------------------------------------------------------------------- /index/mem/malloc.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | // nSize start by 1 4 | func (mb *ManagedBlock) Malloc(nSize int) uint { 5 | ret := mb.GetFreePos() 6 | mb.AddFreePos(uint(nSize) * 64) 7 | return ret 8 | // TODO: add copy and realloc 9 | return 0 10 | } 11 | -------------------------------------------------------------------------------- /index/mem/malloc_test.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestMalloc(t *testing.T) { 8 | // mb := NewManagedBlock() 9 | // mb.Malloc(12) 10 | } -------------------------------------------------------------------------------- /index/mem/node.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import ( 4 | "../../log" 5 | ) 6 | 7 | // This struct is only to refrence to programer 8 | type Node struct { 9 | IsLeaf byte 10 | Reversed byte 11 | KeyNum uint16 12 | Key [13]uint32 13 | Child uint 14 | } 15 | 16 | func (mb *ManagedBlock) InitNode(p uint) { 17 | mb.Write(p, make([]byte, 64)) 18 | } 19 | 20 | func (mb *ManagedBlock) NewNodes(n int) uint { 21 | nodes := mb.Malloc(n) 22 | for i := 0; i < n; i++ { 23 | mb.InitNode(nodes + uint(i)*64) 24 | } 25 | return nodes 26 | } 27 | 28 | func (mb *ManagedBlock) SetNodeKey(node uint, index int, key uint32) { 29 | mb.Write(node+4+uint(index)*4, uint322bytes(key)) 30 | } 31 | 32 | func (mb *ManagedBlock) GetNodeKey(node uint, index int) uint32 { 33 | data, err := mb.Read(node+4+uint(index)*4, 4) 34 | if err != nil { 35 | log.WriteLog("err", err.Error()) 36 | } 37 | return bytes2uint32(data) 38 | } 39 | 40 | func (mb *ManagedBlock) GetNodeKeyNum(node uint) int { 41 | data, err := mb.Read(uint(node+2), 2) 42 | if err != nil { 43 | log.WriteLog("err", err.Error()) 44 | } 45 | return int(bytes2uint16(data)) 46 | } 47 | 48 | func (mb *ManagedBlock) SetNodeKeyNum(node uint, keyNum int) { 49 | data := uint162bytes(uint16(keyNum)) 50 | mb.Write(uint(node+2), data) 51 | } 52 | 53 | func (mb *ManagedBlock) GetChild(node uint, index int) uint { 54 | data, err := mb.Read(node+56, 8) 55 | if err != nil { 56 | log.WriteLog("err", err.Error()) 57 | } 58 | return bytes2uint(data) + 64*uint(index) 59 | } 60 | 61 | func (mb *ManagedBlock) SetChildren(node uint, p uint) { 62 | mb.Write(node+56, uint2bytes(p)) 63 | } 64 | -------------------------------------------------------------------------------- /index/mem/readme.md: -------------------------------------------------------------------------------- 1 | ## MemPool 2 | MemPool use a pool to storage many size of multiple cache blocksize,
3 | so that when the index tree need to expand, it can use the approciate block in the pool list.
4 | Details in `Journal of Frontiers of Computer Science and Technology 计算机科学与探索 2015, 9(2)` 5 | 6 | -------------------------------------------------------------------------------- /index/mem/recovery.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | import ( 4 | "../../memory" 5 | ) 6 | 7 | func LoadManagedBlockFromDataBlock(db *memory.DataBlock) *ManagedBlock { 8 | return &ManagedBlock{ 9 | DataBlock: *db, 10 | } 11 | } 12 | 13 | func LoadManagedBlockFromOldUintptr(p uintptr) *ManagedBlock { 14 | return &ManagedBlock{ 15 | DataBlock: *memory.RecoveryTable[p], 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /index/mem/util.go: -------------------------------------------------------------------------------- 1 | package mem 2 | 3 | func uint162bytes(u uint16) []byte { 4 | b := make([]byte, 2) 5 | for i := 0;i < 2;i++ { 6 | b[i] = (byte)(u) 7 | u >>= 8 8 | } 9 | return b 10 | } 11 | 12 | func bytes2uint16(b []byte) uint16 { 13 | p := uint16(0) 14 | for i := 1;i >= 0;i-- { 15 | p <<= 8 16 | p |= uint16(b[i]) 17 | } 18 | return p 19 | } 20 | 21 | func uint322bytes(u uint32) []byte { 22 | b := make([]byte, 4) 23 | for i := 0;i < 4;i++ { 24 | b[i] = (byte)(u) 25 | u >>= 8 26 | } 27 | return b 28 | } 29 | 30 | func bytes2uint32(b []byte) uint32 { 31 | p := uint32(0) 32 | for i := 3;i >= 0;i-- { 33 | p <<= 8 34 | p |= uint32(b[i]) 35 | } 36 | return p 37 | } 38 | 39 | func uint2bytes(p uint) []byte { 40 | b := make([]byte, 8) 41 | for i := 0;i < 8;i++ { 42 | b[i] = (byte)(p) 43 | p >>= 8 44 | } 45 | return b 46 | } 47 | 48 | func bytes2uint(b []byte) uint { 49 | p := uint(0) 50 | for i := 7;i >= 0;i-- { 51 | p <<= 8 52 | p |= uint(b[i]) 53 | } 54 | return p 55 | } 56 | -------------------------------------------------------------------------------- /index/recovery.go: -------------------------------------------------------------------------------- 1 | package index 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "unsafe" 7 | 8 | "../memory" 9 | 10 | "./csbt" 11 | "./mem" 12 | 13 | "../common" 14 | ) 15 | 16 | var RecoveryTable = make(map[uintptr]*Index) 17 | 18 | type savedIndex struct { 19 | Kind int 20 | Database string 21 | Table string 22 | Key string 23 | Name string 24 | I uint 25 | Implement string 26 | OldPtr uint 27 | } 28 | 29 | func Restore() { 30 | sis := make([]savedIndex, 0) 31 | for _, v := range IndexList { 32 | si := savedIndex{ 33 | Kind: v.Kind, 34 | Database: v.Database, 35 | Table: v.Table, 36 | Name: v.Name, 37 | Key: v.Key, 38 | OldPtr: uint(uintptr(unsafe.Pointer(v))), 39 | } 40 | if csb, ok := v.I.(*csbt.DCSBT); ok { 41 | si.Implement = "dcsbt" 42 | si.I = uint(csb.MB.RawPtr) 43 | } 44 | //TODO:Hash 45 | 46 | sis = append(sis, si) 47 | } 48 | data, _ := json.Marshal(sis) 49 | ioutil.WriteFile(common.COMMON_DIR+"\\index.json", data, 0666) 50 | } 51 | 52 | //Must run memory.Recovery before 53 | func Recovery() { 54 | var sis []map[string]interface{} 55 | data, _ := ioutil.ReadFile(common.COMMON_DIR + "\\index.json") 56 | json.Unmarshal(data, &sis) 57 | for _, v := range sis { 58 | i := &Index{ 59 | Kind: int(v["Kind"].(float64)), 60 | Database: v["Database"].(string), 61 | Table: v["Table"].(string), 62 | Key: v["Key"].(string), 63 | Name: v["Name"].(string), 64 | } 65 | if v["Implement"].(string) == "dcsbt" { 66 | i.I = &csbt.DCSBT{ 67 | MB: &mem.ManagedBlock{ 68 | DataBlock: *(memory.RecoveryTable[uintptr(uint(v["I"].(float64)))]), 69 | }, 70 | } 71 | i.I.Recovery() 72 | } 73 | RecoveryTable[uintptr(uint(v["OldPtr"].(float64)))] = i 74 | IndexList = append(IndexList, i) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /input.sql: -------------------------------------------------------------------------------- 1 | create table bat1( 2 | bat_id int, 3 | bat_name string 4 | ); 5 | insert into bat1 values(1,'bat1'),(2,'bat2'),(3,'bat3'); 6 | insert into bat1 values(4,'bat1'),(5,'bat2'),(6,'bat3'); 7 | update bat1 set bat_name = 'bat33' where bat_name='bat3'; 8 | select * from bat1; 9 | quit; 10 | -------------------------------------------------------------------------------- /install.cmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/install.cmd -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir /var/local/monkeydb2 3 | mkdir /var/local/monkeydb2/data 4 | mkdir /var/local/monkeydb2/data/log 5 | mkdir /var/local/monkeydb2/data/image 6 | echo "Install ok!" 7 | echo . -------------------------------------------------------------------------------- /log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | "time" 7 | "../common" 8 | ) 9 | 10 | type msg struct { 11 | kind string 12 | content interface{} 13 | abort bool 14 | } 15 | 16 | var queue = make(chan msg, 10) 17 | 18 | func checkFileIsExist(filename string) (bool) { 19 | var exist = true; 20 | if _, err := os.Stat(filename); os.IsNotExist(err) { 21 | exist = false; 22 | } 23 | return exist; 24 | } 25 | 26 | func writeLog(kind string, content interface{}) { 27 | var f *os.File 28 | var err error 29 | filename := common.COMMON_DIR + "/log/" + kind + ".log" 30 | if checkFileIsExist(filename) { 31 | f, err = os.OpenFile(filename, os.O_APPEND, 0666) 32 | }else { 33 | f, err = os.Create(filename) 34 | } 35 | if err != nil { 36 | panic("open " + filename + " fail!") 37 | } 38 | defer f.Close() 39 | datetime := time.Now().String() 40 | fmt.Fprintf(f, "[ %s ] ", datetime) 41 | fmt.Fprintln(f, content) 42 | } 43 | 44 | func run() { 45 | for { 46 | m := <- queue 47 | //fmt.Println(m.kind) 48 | if m.abort { 49 | return 50 | } 51 | writeLog(m.kind, m.content) 52 | } 53 | } 54 | 55 | func init() { 56 | go run() 57 | } 58 | 59 | func WriteLog(kind string, content interface{}) { 60 | queue <- msg { 61 | kind: kind, 62 | content: content, 63 | abort: false, 64 | } 65 | } 66 | 67 | func Stop() { 68 | queue <- msg { 69 | abort: true, 70 | } 71 | } 72 | 73 | func WriteLogSync(kind string, content interface{}) { 74 | writeLog(kind, content) 75 | } 76 | 77 | //TODO: Test 78 | -------------------------------------------------------------------------------- /log/log_test.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import "testing" 4 | 5 | func TestWirteLog(t *testing.T) { 6 | writeLog("test", "123") 7 | } -------------------------------------------------------------------------------- /memory/copy.go: -------------------------------------------------------------------------------- 1 | package memory 2 | 3 | import ( 4 | "reflect" 5 | "unsafe" 6 | ) 7 | 8 | var CopyTable = make(map[*DataBlock]*DataBlock) //Src -> Dst 9 | 10 | func (b *DataBlock) read(offset, size uint) ([]byte, error) { 11 | if offset+size > b.Size { 12 | return nil, OUT_OF_SIZE 13 | } 14 | var header reflect.SliceHeader 15 | header.Data = uintptr(b.RawPtr + uintptr(offset)) 16 | header.Len = int(size) 17 | header.Cap = int(size) 18 | return *(*[]byte)(unsafe.Pointer(&header)), nil 19 | } 20 | 21 | func (b *DataBlock) Read(offset, size uint) ([]byte, error) { 22 | b.RWMutex.RLock() 23 | defer b.RWMutex.RUnlock() 24 | return b.read(offset, size) 25 | } 26 | 27 | func (b *DataBlock) write(offset uint, data []byte) (int, error) { 28 | var header reflect.SliceHeader 29 | if offset == 0 && len(data) != 8 { 30 | panic("WAR:Write to 0:") 31 | } 32 | size := len(data) 33 | header.Data = uintptr(b.RawPtr + uintptr(offset)) 34 | header.Len = size 35 | header.Cap = size 36 | d := *(*[]byte)(unsafe.Pointer(&header)) 37 | var n int 38 | if offset+uint(size) > b.Size { 39 | n = int(b.Size - offset) 40 | } else { 41 | n = size 42 | } 43 | copy(d, data[:n]) 44 | return n, nil 45 | } 46 | 47 | func (b *DataBlock) Write(offset uint, data []byte) (int, error) { 48 | b.RWMutex.Lock() 49 | defer b.RWMutex.Unlock() 50 | var copies *DataBlock 51 | copies, ok := CopyTable[b] 52 | if !ok { 53 | return b.write(offset, data) 54 | } 55 | copies.write(offset, data) 56 | return b.write(offset, data) 57 | } 58 | 59 | func Copy(dst, src *DataBlock) (int, error) { 60 | CopyTable[src] = dst 61 | data, err := src.Read(0, src.Size) 62 | if err != nil { 63 | return 0, err 64 | } 65 | delete(CopyTable, src) 66 | return dst.Write(0, data) 67 | } 68 | 69 | func (b *DataBlock) Delete() { 70 | ReleaseImage(b) 71 | } 72 | -------------------------------------------------------------------------------- /memory/error.go: -------------------------------------------------------------------------------- 1 | package memory 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | var ( 8 | NOT_FOUND_ADDRESS = errors.New("Not found address.") 9 | OUT_OF_SIZE = errors.New("Out of block size.") 10 | ) -------------------------------------------------------------------------------- /memory/image.go: -------------------------------------------------------------------------------- 1 | package memory 2 | 3 | //#include 4 | import "C" 5 | 6 | import ( 7 | "container/list" 8 | "os" 9 | "strconv" 10 | "unsafe" 11 | 12 | "../common" 13 | ) 14 | 15 | var DataBlockTable = make(map[uintptr]*DataBlock) 16 | var DataBlockList list.List 17 | var commonBuffer = make([]byte, 1024*1024) // To clear the file quickly 18 | var count = 0 // Windows only support 100ns level 19 | 20 | // CreateImage creates a image file and returns the address 21 | func CreateImage(size int) (ip *DataBlock, err error) { 22 | defer SignalBackup() 23 | filename := common.COMMON_DIR + "/image/" + strconv.Itoa(count) 24 | count++ 25 | ip = &DataBlock{ 26 | RawPtr: uintptr(C.malloc(C.size_t(size))), 27 | Size: uint(size), 28 | } 29 | file, err := os.Create(filename) 30 | defer file.Close() 31 | for i := size; i > 0; i -= 1024 * 1024 { 32 | if i < 1024*1024 { 33 | file.Write(commonBuffer[:i]) 34 | } else { 35 | file.Write(commonBuffer) 36 | } 37 | } 38 | ImageTable[ip.RawPtr] = filename 39 | DataBlockTable[ip.RawPtr] = ip 40 | DataBlockList.PushBack(ip) 41 | return 42 | } 43 | 44 | // ReallocImage creates a new bigger image file and returns the new address with copying data 45 | func ReallocImage(ip *DataBlock, size int) (*DataBlock, error) { 46 | defer SignalBackup() 47 | filename := common.COMMON_DIR + "/image/" + strconv.Itoa(count) 48 | count++ 49 | os.Remove(ImageTable[ip.RawPtr]) 50 | ipNew := &DataBlock{ 51 | RawPtr: uintptr(C.malloc(C.size_t(size))), 52 | Size: uint(size), 53 | } 54 | file, err := os.Create(filename) 55 | defer file.Close() 56 | if err != nil { 57 | return nil, err 58 | } 59 | for i := size; i > 0; i -= 1024 * 1024 { 60 | if i < 1024*1024 { 61 | file.Write(commonBuffer[:i]) 62 | } else { 63 | file.Write(commonBuffer) 64 | } 65 | } 66 | Copy(ipNew, ip) 67 | delete(ImageTable, ip.RawPtr) 68 | C.free(unsafe.Pointer(ip.RawPtr)) 69 | ImageTable[ipNew.RawPtr] = filename 70 | DataBlockTable[ipNew.RawPtr] = ip 71 | RemoveBlock(ip) 72 | DataBlockList.PushBack(ipNew) 73 | return ipNew, nil 74 | } 75 | 76 | // ReleaseImage release the image and delete its related file 77 | func ReleaseImage(ip *DataBlock) (err error) { 78 | defer SignalBackup() 79 | _, ok := ImageTable[ip.RawPtr] 80 | if !ok { 81 | err = NOT_FOUND_ADDRESS 82 | return 83 | } 84 | 85 | err = os.Remove(ImageTable[ip.RawPtr]) 86 | RemoveBlock(ip) 87 | C.free(unsafe.Pointer(ip.RawPtr)) 88 | delete(ImageTable, ip.RawPtr) 89 | delete(DataBlockTable, ip.RawPtr) 90 | for l := DataBlockList.Front(); l != nil; l = l.Next() { 91 | if l.Value.(*DataBlock) == ip { 92 | DataBlockList.Remove(l) 93 | } 94 | } 95 | return 96 | } 97 | 98 | func RemoveBlock(ip *DataBlock) { 99 | var l *list.Element 100 | for l = DataBlockList.Front(); l != nil; l = l.Next() { 101 | if l.Value.(*DataBlock).RawPtr == ip.RawPtr { 102 | break 103 | } 104 | } 105 | if l != nil { 106 | DataBlockList.Remove(l) 107 | } 108 | delete(DataBlockTable, ip.RawPtr) 109 | } 110 | -------------------------------------------------------------------------------- /memory/image.md: -------------------------------------------------------------------------------- 1 | ## Image.go 2 | 3 | ### ImageTable 4 | 5 | The design of ImageTable is only to recovery images. 6 | 7 | ### CopyTable 8 | 9 | When you allocate a image, the copytable will be insert a row to descripe which dst will be copied from which src, 10 | and when another thread writes to the one, it will writes the same thing to copies, too. 11 | 12 | ### Usage 13 | 14 | Create a image and use the datablock it returns, read and write it using the thread-safe functions Read, Write. 15 | When you want to reallocate its size, use RellocImage before you change your pointer, e.g. 16 | ``` 17 | PrimaryKey.A.Datablock = p 18 | ... 19 | pNew := ReallocImage(p) // This would use some time while other thread may access the block with code: 20 | // PrimaryKey.A.datablock.Write(15, []byte{6, 9, 5, 7}) 21 | PrimaryKey.A.Datablock = pNew 22 | ``` 23 | 24 | ### Backup 25 | 26 | When you create, realloc or release a image, a signal to sync all image will be sent to backup. 27 | It will also be called when the system is shutdown or you mantually call `SyncAllImageFile` 28 | 29 | ### Recovery 30 | 31 | When the system launch, it will detect the `imageTable.json` and reload every image file to a new address. 32 | After this, an RecoveryTable old -> new will be created. -------------------------------------------------------------------------------- /memory/image_test.go: -------------------------------------------------------------------------------- 1 | package memory 2 | 3 | import ( 4 | "testing" 5 | "unsafe" 6 | ) 7 | 8 | var I *DataBlock 9 | 10 | func TestCreateImage(t *testing.T) { 11 | oldLen := DataBlockList.Len() 12 | I, err := CreateImage(1024) 13 | if err != nil { 14 | t.Error(err) 15 | } 16 | I.Write(0, []byte{5}) 17 | if _, ok := ImageTable[I.RawPtr];!ok { 18 | t.Error("Not in map") 19 | } 20 | if DataBlockList.Len() != oldLen + 1 { 21 | t.Error("Not in list") 22 | } 23 | ReleaseImage(I) 24 | } 25 | 26 | func TestReallocImage(t *testing.T) { 27 | oldLen := DataBlockList.Len() 28 | I, err := CreateImage(1024) 29 | if err != nil { 30 | t.Error(err) 31 | } 32 | I.Write(0, []byte{5}) 33 | if _, ok := ImageTable[I.RawPtr];!ok { 34 | t.Error("Not in map") 35 | } 36 | newI, err := ReallocImage(I, 2048) 37 | if err != nil { 38 | t.Error(err) 39 | } 40 | r, err := newI.Read(0, 1) 41 | if err != nil { 42 | t.Error(err) 43 | } 44 | if r[0] != 5 { 45 | t.Error("Not copy in realloc") 46 | } 47 | if _, ok := ImageTable[I.RawPtr];ok && I.RawPtr != newI.RawPtr { 48 | t.Error("Old in map") 49 | } 50 | if _, ok := ImageTable[newI.RawPtr];!ok { 51 | t.Error("New not in map") 52 | } 53 | if DataBlockList.Len() != oldLen + 1 { 54 | t.Error("Not in list") 55 | } 56 | ReleaseImage(newI) 57 | I = newI 58 | } 59 | 60 | func TestReleaseImage(t *testing.T) { 61 | I, err := CreateImage(1024) 62 | if err != nil { 63 | t.Error(err) 64 | } 65 | (*[5]int)(unsafe.Pointer(I))[2] = 5 66 | if _, ok := ImageTable[I.RawPtr];!ok { 67 | t.Error("Not in map") 68 | } 69 | oldLen := DataBlockList.Len() 70 | ReleaseImage(I) 71 | if DataBlockList.Len() != oldLen - 1 { 72 | t.Error("Released in list") 73 | } 74 | if _, ok := ImageTable[I.RawPtr];ok { 75 | t.Error("In map") 76 | } 77 | } -------------------------------------------------------------------------------- /memory/memory.go: -------------------------------------------------------------------------------- 1 | package memory 2 | 3 | import ( 4 | "sync" 5 | ) 6 | 7 | var ImageTable = make(map[uintptr]string) 8 | 9 | type DataBlock struct { 10 | RawPtr uintptr 11 | Size uint 12 | RWMutex sync.RWMutex 13 | } 14 | -------------------------------------------------------------------------------- /memory/recovery.go: -------------------------------------------------------------------------------- 1 | package memory 2 | 3 | //#include 4 | import "C" 5 | import ( 6 | "encoding/json" 7 | "io/ioutil" 8 | "reflect" 9 | "strconv" 10 | "unsafe" 11 | 12 | "../common" 13 | "../log" 14 | ) 15 | 16 | const ( 17 | MAX_BAK_CHAN_SIZE = 10 18 | ) 19 | 20 | var startBackup = make(chan bool, MAX_BAK_CHAN_SIZE) 21 | 22 | var RecoveryTable = make(map[uintptr]*DataBlock) 23 | 24 | func (b *DataBlock) SyncToFile() error { 25 | data, err := b.Read(0, b.Size) 26 | if err != nil { 27 | return err 28 | } 29 | filename, ok := ImageTable[b.RawPtr] 30 | if !ok { 31 | return NOT_FOUND_ADDRESS 32 | } 33 | log.WriteLog("sys", "Sync "+strconv.Itoa(int(b.RawPtr))+" to file.") 34 | return ioutil.WriteFile(filename, data, 0666) 35 | } 36 | 37 | func SyncAllImageToFile() { 38 | for l := DataBlockList.Front(); l != nil; l = l.Next() { 39 | b, ok := l.Value.(*DataBlock) 40 | if !ok { 41 | continue 42 | } 43 | data, _ := b.Read(0, b.Size) 44 | filename, ok := ImageTable[b.RawPtr] 45 | if !ok { 46 | continue 47 | } 48 | ioutil.WriteFile(filename, data, 0666) 49 | } 50 | } 51 | 52 | func SaveImageTable() { 53 | tempTable := make(map[string]string) 54 | for k, v := range ImageTable { 55 | tempTable[strconv.Itoa(int(k))] = v 56 | } 57 | data, _ := json.Marshal(tempTable) 58 | ioutil.WriteFile(common.COMMON_DIR+"\\image\\imageTable.json", data, 0666) 59 | ioutil.WriteFile(common.COMMON_DIR+"\\image\\count", []byte(strconv.Itoa(count)), 0666) 60 | log.WriteLog("sys", "Save image table to file.") 61 | } 62 | 63 | func SignalBackup() { 64 | //startBackup <- true 65 | } 66 | 67 | func BackupRoutine() { 68 | for { 69 | <-startBackup 70 | SaveImageTable() 71 | SyncAllImageToFile() 72 | } 73 | } 74 | 75 | func init() { 76 | // Recovery() 77 | // go BackupRoutine() 78 | } 79 | 80 | func Restore() { 81 | SaveImageTable() 82 | SyncAllImageToFile() 83 | } 84 | 85 | func LoadImage(filename string) *DataBlock { 86 | data, _ := ioutil.ReadFile(filename) 87 | size := len(data) 88 | ip := &DataBlock{ 89 | RawPtr: uintptr(C.malloc(C.size_t(size))), 90 | Size: uint(size), 91 | } 92 | var header reflect.SliceHeader 93 | header.Data = uintptr(ip.RawPtr) 94 | header.Len = size 95 | header.Cap = size 96 | d := *(*[]byte)(unsafe.Pointer(&header)) 97 | copy(d, data) 98 | ImageTable[ip.RawPtr] = filename 99 | DataBlockTable[ip.RawPtr] = ip 100 | DataBlockList.PushBack(ip) 101 | return ip 102 | } 103 | 104 | func Recovery() { 105 | countS, err := ioutil.ReadFile(common.COMMON_DIR + "\\image\\count") 106 | if err != nil { 107 | log.WriteLog("sys", "Recovery abort:"+err.Error()) 108 | return 109 | } 110 | count, _ = strconv.Atoi(string(countS)) 111 | data, err := ioutil.ReadFile(common.COMMON_DIR + "\\image\\imageTable.json") 112 | if err != nil { 113 | log.WriteLog("sys", "Recovery abort:"+err.Error()) 114 | return 115 | } 116 | var tempTable map[string]interface{} 117 | json.Unmarshal(data, &tempTable) 118 | for k, v := range tempTable { 119 | ipOld, _ := strconv.Atoi(k) 120 | ipNew := LoadImage(v.(string)) 121 | RecoveryTable[uintptr(ipOld)] = ipNew 122 | } 123 | log.WriteLog("sys", "Recovery "+strconv.Itoa(len(RecoveryTable))+" image files.") 124 | } 125 | 126 | func ShutDown() { 127 | SaveImageTable() 128 | SyncAllImageToFile() 129 | log.WriteLog("sys", "memory manager system shutdown.") 130 | } 131 | -------------------------------------------------------------------------------- /memory/recovery_test.go: -------------------------------------------------------------------------------- 1 | package memory 2 | 3 | import ( 4 | //"testing" 5 | //"time" 6 | //"fmt" 7 | ) 8 | /* 9 | func Test_signalBackup(t *testing.T) { 10 | CreateImage(1024) 11 | CreateImage(512) 12 | signalBackup() 13 | time.Sleep(time.Second) 14 | } 15 | 16 | func TestRecovery(t *testing.T) { 17 | Recovery() 18 | time.Sleep(time.Second) 19 | if len(RecoveryTable) != 2 { 20 | t.Error("Recovery num error!") 21 | } 22 | fmt.Println(RecoveryTable) 23 | fmt.Println(ImageTable) 24 | }*/ -------------------------------------------------------------------------------- /mempool/a.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/mempool/a.txt -------------------------------------------------------------------------------- /mempool/cgo_m.go: -------------------------------------------------------------------------------- 1 | package mempool 2 | 3 | import ( 4 | "unsafe" 5 | "reflect" 6 | "./heap" 7 | "time" 8 | "syscall" 9 | ) 10 | 11 | const MAX_LEVEL = 20 //It means we can use 1, 2, ... , 2^14 * 64Bytes 12 | 13 | const MAX_BLOCKS_LIMIT = 2 //When free max blocks more than MAX_BLOCKS_LIMIT, when release memory, we will free them 14 | 15 | type blocks [][]byte 16 | 17 | func (b *blocks) Swap(i, j int) { 18 | header_i := (*reflect.SliceHeader)(unsafe.Pointer(&(*b)[i])) 19 | header_j := (*reflect.SliceHeader)(unsafe.Pointer(&(*b)[j])) 20 | var header_t reflect.SliceHeader 21 | assign(&header_t, *header_i) 22 | assign(header_i, *header_j) 23 | assign(header_j, header_t) 24 | } 25 | 26 | func (b *blocks) Len() int { 27 | return len(*b) 28 | } 29 | 30 | func (b *blocks) Less(i, j int) bool { 31 | header_i := (*reflect.SliceHeader)(unsafe.Pointer(&(*b)[i])) 32 | header_j := (*reflect.SliceHeader)(unsafe.Pointer(&(*b)[j])) 33 | return header_i.Data < header_j.Data 34 | } 35 | 36 | func (b *blocks) Push(x interface{}) { 37 | if bs, ok := x.([]byte);ok { 38 | *b = append(*b, bs) 39 | } 40 | } 41 | 42 | func (b *blocks) Pop() interface{} { 43 | p := (*b)[len(*b) - 1] 44 | *b = (*b)[:len(*b) - 1] 45 | return p 46 | } 47 | 48 | func assign(header_t *reflect.SliceHeader, header_i reflect.SliceHeader) { 49 | header_t.Data = header_i.Data 50 | header_t.Len = header_i.Len 51 | header_t.Cap = header_i.Cap 52 | } 53 | 54 | type Pool struct { 55 | list [MAX_LEVEL]blocks 56 | } 57 | 58 | var pool Pool 59 | 60 | type fileImage struct { 61 | FileHandle syscall.Handle 62 | ImageHandle syscall.Handle 63 | FileName string 64 | } 65 | 66 | 67 | func init() { 68 | for i := 0;i < MAX_LEVEL;i++ { 69 | heap.Push(&pool.list[i], Malloc(64 << uint(i))) 70 | time.Sleep(time.Second) 71 | } 72 | } 73 | 74 | func canMerge(b1, b2 []byte) bool { 75 | header1 := (*reflect.SliceHeader)(unsafe.Pointer(&b1)) 76 | header2 := (*reflect.SliceHeader)(unsafe.Pointer(&b2)) 77 | return int(header1.Data) + header1.Cap == int(header2.Data) || 78 | int(header2.Data) + header2.Cap == int(header2.Data) 79 | } 80 | 81 | func merge(prev, back []byte) []byte { 82 | var header reflect.SliceHeader 83 | header1 := (*reflect.SliceHeader)(unsafe.Pointer(&prev)) 84 | header2 := (*reflect.SliceHeader)(unsafe.Pointer(&back)) 85 | header.Cap = header1.Cap + header2.Cap 86 | header.Len = header.Cap 87 | header.Data = header1.Data 88 | return *(*[]byte)(unsafe.Pointer(&header)) 89 | } 90 | 91 | /* 92 | InsertFree function insert a free space buffer to list[n] 93 | */ 94 | func InsertFree(n int, b []byte) { 95 | if n >= MAX_LEVEL { 96 | return 97 | } 98 | // Max blocks remain little num 99 | if n == MAX_LEVEL - 1 && pool.list[MAX_LEVEL - 1].Len() >= MAX_BLOCKS_LIMIT { 100 | Free(b) 101 | return 102 | } 103 | //Merge 104 | p := heap.Push(&pool.list[n], b) 105 | if p > 0 && canMerge(pool.list[n][p - 1], pool.list[n][p]) { 106 | big := merge(pool.list[n][p - 1], pool.list[n][p]) 107 | heap.Remove(&pool.list[n], p) 108 | InsertFree(n + 1, big) 109 | } else if p < pool.list[n].Len() - 1 && canMerge(pool.list[n][p], pool.list[n][p + 1]) { 110 | big := merge(pool.list[n][p], pool.list[n][p + 1]) 111 | heap.Remove(&pool.list[n], p) 112 | InsertFree(n + 1, big) 113 | } 114 | 115 | } 116 | 117 | func slice(full []byte) ([]byte, []byte) { 118 | header := (*reflect.SliceHeader)(unsafe.Pointer(&full)) 119 | var header1, header2 reflect.SliceHeader 120 | header1.Cap = header.Cap / 2 121 | header1.Len = header1.Cap 122 | header1.Data = header.Data 123 | header2.Cap = header1.Cap 124 | header2.Len = header2.Cap 125 | header2.Data = uintptr(int(header1.Data) + header1.Len) 126 | return *(*[]byte)(unsafe.Pointer(&header1)), 127 | *(*[]byte)(unsafe.Pointer(&header2)) 128 | } 129 | 130 | /* 131 | Slice function slice a big block of n to 2 parts, then insert one to list[n-1] and return another 132 | */ 133 | func Slice(n int) []byte { 134 | if n > MAX_LEVEL || n <= 0 { 135 | panic("Unexpected block applied to slice!") 136 | } 137 | if n == MAX_LEVEL { 138 | return Malloc(64 << (MAX_LEVEL - 1)) 139 | } 140 | full := getFree(n) 141 | half1, half2 := slice(full) 142 | InsertFree(n - 1, half2) 143 | return half1 144 | } 145 | 146 | func getFree(n int) []byte { 147 | if pool.list[n].Len() != 0 { 148 | return heap.Pop(&pool.list[n]).([]byte) 149 | } 150 | return Slice(n + 1) 151 | } 152 | 153 | func GetFree(size int) []byte { 154 | n := size >> 5 155 | i := 0 156 | for n > 0 { 157 | n >>= 1 158 | i++ 159 | } 160 | return getFree(i) 161 | } 162 | 163 | // Warning: DONOT release a []byte created by Go 164 | func Release(buffer []byte) { 165 | header := (*reflect.SliceHeader)(unsafe.Pointer(&buffer)) 166 | n := header.Cap >> 5 167 | i := 0 168 | for n > 0 { 169 | n >>= 1 170 | i++ 171 | } 172 | InsertFree(i, buffer) 173 | } -------------------------------------------------------------------------------- /mempool/cgo_m_test.go: -------------------------------------------------------------------------------- 1 | package mempool 2 | 3 | import "testing" 4 | import "time" 5 | 6 | func TestGetFree(t *testing.T) { 7 | sum := 0 8 | for i := 0;i < 100;i++ { 9 | r := GetFree(64 << uint(i % 14)) 10 | r[25] = byte(i) 11 | sum += int(r[25]) 12 | time.Sleep(time.Millisecond) //If too fast then it will failed! 13 | Release(r) 14 | } 15 | t.Error(int(sum)) 16 | // r := Malloc(10) 17 | // r[5] = 5 18 | // k := Malloc(20) 19 | // k[4] = 4 20 | //Release(r) 21 | } -------------------------------------------------------------------------------- /mempool/heap/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /mempool/heap/heap.go: -------------------------------------------------------------------------------- 1 | //Because of the heap in the Go language ommited much details in rolling, 2 | //So I wrote an alternative 3 | 4 | // Copyright 2009 The Go Authors. All rights reserved. 5 | // Use of this source code is governed by a BSD-style 6 | // license that can be found in the LICENSE file. 7 | 8 | // Package heap provides heap operations for any type that implements 9 | // heap.Interface. A heap is a tree with the property that each node is the 10 | // minimum-valued node in its subtree. 11 | // 12 | // The minimum element in the tree is the root, at index 0. 13 | // 14 | // A heap is a common way to implement a priority queue. To build a priority 15 | // queue, implement the Heap interface with the (negative) priority as the 16 | // ordering for the Less method, so Push adds items while Pop removes the 17 | // highest-priority item from the queue. The Examples include such an 18 | // implementation; the file example_pq_test.go has the complete source. 19 | // 20 | package heap 21 | 22 | import "sort" 23 | 24 | // Any type that implements heap.Interface may be used as a 25 | // min-heap with the following invariants (established after 26 | // Init has been called or if the data is empty or sorted): 27 | // 28 | // !h.Less(j, i) for 0 <= i < h.Len() and 2*i+1 <= j <= 2*i+2 and j < h.Len() 29 | // 30 | // Note that Push and Pop in this interface are for package heap's 31 | // implementation to call. To add and remove things from the heap, 32 | // use heap.Push and heap.Pop. 33 | type Interface interface { 34 | sort.Interface 35 | Push(x interface{}) // add x as element Len() 36 | Pop() interface{} // remove and return element Len() - 1. 37 | } 38 | 39 | // A heap must be initialized before any of the heap operations 40 | // can be used. Init is idempotent with respect to the heap invariants 41 | // and may be called whenever the heap invariants may have been invalidated. 42 | // Its complexity is O(n) where n = h.Len(). 43 | // 44 | func Init(h Interface) { 45 | // heapify 46 | n := h.Len() 47 | for i := n/2 - 1; i >= 0; i-- { 48 | down(h, i, n) 49 | } 50 | } 51 | 52 | // Push pushes the element x onto the heap. The complexity is 53 | // O(log(n)) where n = h.Len(). 54 | // 55 | //* I make Push return a position 56 | func Push(h Interface, x interface{}) int { 57 | h.Push(x) 58 | return up(h, h.Len()-1) 59 | } 60 | 61 | // Pop removes the minimum element (according to Less) from the heap 62 | // and returns it. The complexity is O(log(n)) where n = h.Len(). 63 | // It is equivalent to Remove(h, 0). 64 | // 65 | func Pop(h Interface) interface{} { 66 | n := h.Len() - 1 67 | h.Swap(0, n) 68 | down(h, 0, n) 69 | return h.Pop() 70 | } 71 | 72 | // Remove removes the element at index i from the heap. 73 | // The complexity is O(log(n)) where n = h.Len(). 74 | // 75 | func Remove(h Interface, i int) interface{} { 76 | n := h.Len() - 1 77 | if n != i { 78 | h.Swap(i, n) 79 | down(h, i, n) 80 | up(h, i) 81 | } 82 | return h.Pop() 83 | } 84 | 85 | // Fix re-establishes the heap ordering after the element at index i has changed its value. 86 | // Changing the value of the element at index i and then calling Fix is equivalent to, 87 | // but less expensive than, calling Remove(h, i) followed by a Push of the new value. 88 | // The complexity is O(log(n)) where n = h.Len(). 89 | func Fix(h Interface, i int) { 90 | down(h, i, h.Len()) 91 | up(h, i) 92 | } 93 | 94 | func up(h Interface, j int) int { 95 | for { 96 | i := (j - 1) / 2 // parent 97 | if i == j || !h.Less(j, i) { 98 | break 99 | } 100 | h.Swap(i, j) 101 | j = i 102 | } 103 | return j 104 | } 105 | 106 | func down(h Interface, i, n int) { 107 | for { 108 | j1 := 2*i + 1 109 | if j1 >= n || j1 < 0 { // j1 < 0 after int overflow 110 | break 111 | } 112 | j := j1 // left child 113 | if j2 := j1 + 1; j2 < n && !h.Less(j1, j2) { 114 | j = j2 // = 2*i + 2 // right child 115 | } 116 | if !h.Less(j, i) { 117 | break 118 | } 119 | h.Swap(i, j) 120 | i = j 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /mempool/malloc.go: -------------------------------------------------------------------------------- 1 | package mempool 2 | 3 | import ( 4 | "../log" 5 | "../memory" 6 | ) 7 | 8 | // Please use GetFree instead or you might make an error 9 | func Malloc(size int) *memory.DataBlock{ 10 | db, err := memory.CreateImage(size) 11 | if err != nil { 12 | log.WriteLog("err", "Malloc with an error : " + err.Error()) 13 | } 14 | return db 15 | } 16 | 17 | // Please use Release instead or you might make an error 18 | func Free(db *memory.DataBlock) { 19 | err := memory.ReleaseImage(db) 20 | if err != nil { 21 | log.WriteLog("err", "Malloc with an error : " + err.Error()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /mempool/map_windows.go.dup: -------------------------------------------------------------------------------- 1 | package mempool 2 | 3 | import ( 4 | "syscall" 5 | "unsafe" 6 | ) 7 | 8 | var ( 9 | kernel32, _ = syscall.LoadLibrary("kernel32.dll") 10 | ) 11 | 12 | var ( 13 | createFileMapping, _ = syscall.GetProcAddress(kernel32, "CreateFileMappingW") 14 | mapViewOfFile, _ = syscall.GetProcAddress(kernel32, "MapViewOfFile") 15 | createFile, _ = syscall.GetProcAddress(kernel32, "CreateFileW") 16 | closeHandle, _ = syscall.GetProcAddress(kernel32, "CloseHandle") 17 | flushViewOfFile, _ = syscall.GetProcAddress(kernel32, "FlushViewOfFile") 18 | unmapViewOfFile, _ = syscall.GetProcAddress(kernel32, "UnmapViewOfFile") 19 | ) 20 | 21 | const ( 22 | //CreateFile 23 | GENERIC_READ = 0x80000000 24 | GENERIC_WRITE = 0x40000000 25 | CREATE_ALWAYS = 2 26 | CREATE_NEW = 1 //Exist will fail 27 | OPEN_ALWAYS = 4 28 | OPEN_EXISTING = 3 29 | TRUNCATE_EXISTING = 5 30 | FILE_ATTRIBUTE_ARCHIVE = 32 31 | FILE_ATTRIBUTE_ENCRYPTED = 16384 32 | FILE_ATTRIBUTE_HIDDEN = 2 33 | FILE_ATTRIBUTE_NORMAL = 128 34 | FILE_ATTRIBUTE_OFFLINE = 4096 35 | FILE_ATTRIBUTE_READONLY = 1 36 | FILE_ATTRIBUTE_SYSTEM = 4 37 | FILE_ATTRIBUTE_TEMPORARY = 256 38 | //CreateFileMapping 39 | PAGE_READWRITE = 4 40 | //MapViewOfFile 41 | FILE_MAP_WRITE = 2 42 | ) 43 | 44 | func CreateFileMapping(hFile syscall.Handle, dwMaxiumSizeHigh, dwMaxiumSizeLow uint, name string) syscall.Handle { 45 | r, _, _ := syscall.Syscall6(createFileMapping, 6, uintptr(hFile), 0, uintptr(PAGE_READWRITE), uintptr(dwMaxiumSizeHigh), uintptr(dwMaxiumSizeLow), uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(name)))) 46 | return syscall.Handle(r) 47 | } 48 | 49 | func CreateFile(fileName string, dwCreationDisposition uint) syscall.Handle { 50 | r, _, _ := syscall.Syscall9(createFile, 7, uintptr(unsafe.Pointer(syscall.StringToUTF16Ptr(fileName))), uintptr(GENERIC_READ | GENERIC_WRITE), 0, 0, uintptr(dwCreationDisposition), uintptr(FILE_ATTRIBUTE_NORMAL), 0, 0, 0) 51 | return syscall.Handle(r) 52 | } 53 | 54 | func CloseHandle(handle syscall.Handle) { 55 | syscall.Syscall(closeHandle, 1, uintptr(handle), 0, 0) 56 | } 57 | 58 | func MapViewOfFile(hFileMappingObject syscall.Handle, dwNumberOfBytesToMap uint) uintptr { 59 | r, _, _ := syscall.Syscall6(mapViewOfFile, 5, uintptr(hFileMappingObject), uintptr(FILE_MAP_WRITE), 0, 0, uintptr(dwNumberOfBytesToMap), 0) 60 | return r 61 | } 62 | 63 | func FlushViewOfFile(lpBaseAddress uintptr, dwNumberOfBytesToFlush uint) { 64 | syscall.Syscall(flushViewOfFile, 2, lpBaseAddress, uintptr(dwNumberOfBytesToFlush), 0) 65 | } 66 | 67 | func UnmapViewOfFile(lpBaseAddress uintptr) { 68 | syscall.Syscall(unmapViewOfFile, 1, lpBaseAddress, 0, 0) 69 | } -------------------------------------------------------------------------------- /mempool/map_windows_test.go.dup: -------------------------------------------------------------------------------- 1 | package mempool 2 | 3 | import "testing" 4 | import "unsafe" 5 | 6 | func TestCreateFile(t *testing.T) { 7 | h := CreateFile("./a.txt", OPEN_ALWAYS) 8 | if h == 0 { 9 | t.Error(0) 10 | } 11 | CloseHandle(h) 12 | } 13 | 14 | func TestCreateFileMapping(t *testing.T) { 15 | h := CreateFile("./a.img", OPEN_ALWAYS) 16 | hI := CreateFileMapping(h, 0, 32768, "img") 17 | ip := MapViewOfFile(hI, 4) 18 | p := (*int)(unsafe.Pointer(ip)) 19 | *p = 5 20 | FlushViewOfFile(ip, 4) 21 | UnmapViewOfFile(ip) 22 | CloseHandle(hI) 23 | CloseHandle(h) 24 | h = CreateFile("./a.img", OPEN_ALWAYS) 25 | hI = CreateFileMapping(h, 0, 32768, "img") 26 | ip = MapViewOfFile(hI, 4) 27 | p = (*int)(unsafe.Pointer(ip)) 28 | 29 | 30 | if *p != 5 { 31 | t.Error("Failed to check img file and RAM.\n") 32 | } 33 | *p = 6 34 | UnmapViewOfFile(ip) 35 | FlushViewOfFile(ip, 8) 36 | CloseHandle(hI) 37 | CloseHandle(h) 38 | } -------------------------------------------------------------------------------- /mempool/recovery.go.dup: -------------------------------------------------------------------------------- 1 | package mempool 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "../log" 7 | "strconv" 8 | "syscall" 9 | ) 10 | 11 | const ( 12 | RECOVERY = true 13 | ) 14 | 15 | var RecoveryTable = make(map[uintptr]uintptr) 16 | var recovered = false 17 | 18 | func syncTableToFile() { 19 | ready := make(map[string]fileImage) 20 | for k, v := range MallocTable { 21 | str := strconv.Itoa(int(k)) 22 | ready[str] = v 23 | } 24 | data, err := json.Marshal(ready) 25 | if err != nil { 26 | log.WriteLog("sys", "JSON stringfy malloc table with an error : " + err.Error()) 27 | return 28 | } 29 | ioutil.WriteFile(".\\malloc.json", data, 0666) 30 | } 31 | 32 | func Recovery() bool { 33 | if recovered { 34 | return false 35 | } 36 | data, err := ioutil.ReadFile(".\\malloc.json") 37 | if err != nil { 38 | return false 39 | } 40 | var mallocTable map[string]interface{} 41 | err = json.Unmarshal(data, &mallocTable) 42 | if err != nil { 43 | return false 44 | } 45 | newmap := make(map[uintptr]fileImage) 46 | for k, v := range mallocTable { 47 | kn, _ := strconv.Atoi(k) 48 | vn := v.(map[string]interface{}) 49 | fh, ih, ip := LoadFileImage(vn["FileName"].(string)) 50 | newmap[ip] = fileImage { 51 | FileHandle: fh, 52 | FileName: vn["FileName"].(string), 53 | ImageHandle: ih, 54 | } 55 | RecoveryTable[uintptr(kn)] = ip 56 | log.WriteLog("sys", "Recovery from " + strconv.Itoa(int(kn)) + " to " + strconv.Itoa(int(ip))) 57 | } 58 | MallocTable = newmap 59 | return true 60 | } 61 | 62 | func LoadFileImage(file string) (fileHandle, imageHandle syscall.Handle, ip uintptr) { 63 | fileHandle = CreateFile(file, OPEN_ALWAYS) 64 | imageHandle = CreateFileMapping(fileHandle, 0, 0, file) 65 | ip = MapViewOfFile(imageHandle, 0) 66 | //Use the sync File IO appears to make OS refresh map view 67 | log.WriteLogSync("sys", "MapViewOfFile return:" + strconv.Itoa(int(ip))) 68 | return 69 | } -------------------------------------------------------------------------------- /mempool/recovery.md: -------------------------------------------------------------------------------- 1 | ## About the recovery system 2 | 3 | ### Index 4 | 5 | #### Backup 6 | 7 | 1. Index was sync to file with an IndexContent struct recording its address in database and its baseaddr 8 | 2. All data of CSBT was sync to image file before 9 | 10 | #### Recovery 11 | 12 | 1. Read `index.json` to load IndexContent table 13 | 2. For each index read related malloc information in `malloc.json` 14 | 3. Load the raw image file to read all data of CSBT from the root and use a recursion 15 | 4. Allocate a new block to storage all data of CSBT 16 | 17 | ### DataRow 18 | 19 | #### Backup 20 | 21 | 1. When any allocate occurs, including Index and DataRow, write malloc table with baseaddr and its file image to `malloc.json` 22 | 2. Each DataRow has a special struct that defines how much size it used 23 | 3. When insert DataRows, we allocate a large block and put them one by one, if there exist a index, tell index the address of the head of this row 24 | 25 | #### Recovery 26 | 27 | 1. When we need to recovery a table, we recovery its primary index tree and recovery every data 28 | 2. We allocate a new block to storage them -------------------------------------------------------------------------------- /monkey: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/monkey -------------------------------------------------------------------------------- /monkey.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "flag" 6 | "fmt" 7 | "os" 8 | "strings" 9 | 10 | "./network" 11 | ) 12 | 13 | var port = flag.String("port", "2016", "Dial port") 14 | 15 | func loop(tcpSession *network.TCPSession) bool { 16 | fmt.Print("Monkey>>") 17 | command := "" 18 | inReader := bufio.NewReader(os.Stdin) 19 | i := 0 20 | for !strings.Contains(command, ";") { 21 | if i > 0 { 22 | fmt.Print(" ->") 23 | } 24 | cmd, _ := inReader.ReadString('\n') 25 | command += cmd 26 | i++ 27 | } 28 | if strings.Contains(command, "quit;") { 29 | return false 30 | } 31 | tcpSession.SendPack(network.MakePack(network.DIRECT_QUERY, []byte(command))) 32 | pack := tcpSession.RecvPack() 33 | switch pack.Type { 34 | case network.RESPONSE: 35 | fmt.Println(string(pack.Data)) 36 | } 37 | return true 38 | } 39 | 40 | func main() { 41 | flag.Parse() 42 | tcpSession := network.Dial("127.0.0.1:" + *port) 43 | for loop(tcpSession) { 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /monkeyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/monkeyd -------------------------------------------------------------------------------- /monkeyd.exe~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/monkeyd.exe~ -------------------------------------------------------------------------------- /monkeyd.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | 7 | "./recovery" 8 | 9 | "./network" 10 | ) 11 | 12 | var port = flag.String("port", "2016", "Listen port.") 13 | 14 | func bye() { 15 | recovery.SafeExit() 16 | fmt.Println("Bye!") 17 | } 18 | 19 | func main() { 20 | flag.Parse() 21 | network.Listen(*port) 22 | bye() 23 | } 24 | -------------------------------------------------------------------------------- /network/encode.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "fmt" 5 | "strconv" 6 | "unsafe" 7 | 8 | "../exe" 9 | "../plan" 10 | ) 11 | 12 | type Pack struct { 13 | Head uint32 14 | Len uint32 15 | Type uint32 16 | Data []byte 17 | } 18 | 19 | const ( 20 | CREATE_CONNECTION = iota 21 | CLOSE_CONNECTION 22 | DIRECT_QUERY 23 | RESPONSE 24 | ) 25 | 26 | func Encode(rel *exe.Relation, res *plan.Result, err error) *Pack { 27 | relJson := "[" 28 | if rel != nil && len(rel.Rows) != 0 { 29 | for r := 0; r < len(rel.Rows); r++ { 30 | if r != 0 { 31 | relJson += "," 32 | } 33 | relJson += "{" 34 | for i := 0; i < len(rel.Rows[r]); i++ { 35 | if i != 0 { 36 | relJson += "," 37 | } 38 | if i < len(rel.ColumnNames) { 39 | relJson += "\"" + rel.ColumnNames[i] + "\":" 40 | } else { 41 | relJson += "\"" + strconv.Itoa(i) + "\":" 42 | } 43 | switch rel.Rows[r][i].Kind { 44 | case exe.INT: 45 | i := *(*int)((unsafe.Pointer)(&rel.Rows[r][i].Raw[0])) 46 | relJson += strconv.Itoa(i) 47 | case exe.FLOAT: 48 | f := *(*float64)((unsafe.Pointer)(&rel.Rows[r][i].Raw[0])) 49 | relJson += strconv.FormatFloat(f, 'f', -1, 64) 50 | default: //exe.STRING 51 | relJson += "\"" + escape(string(rel.Rows[r][i].Raw)) + "\"" 52 | } 53 | } 54 | relJson += "}" 55 | } 56 | } 57 | relJson += "]" 58 | resJson := "{\"affectedRows\":%d,\"usedTime\":%d}" 59 | if res == nil { 60 | resJson = fmt.Sprintf(resJson, 0, 0) 61 | } else { 62 | resJson = fmt.Sprintf(resJson, res.AffectedRows, res.UsedTime) 63 | } 64 | 65 | errStr := "null" 66 | if err != nil { 67 | errStr = "\"" + escape(err.Error()) + "\"" 68 | } 69 | json := []byte(fmt.Sprintf("{\"relation\":%s,\"result\":%s,\"error\":%s}", relJson, resJson, errStr)) 70 | return &Pack{ 71 | Head: 2016, 72 | Len: uint32(len(json) + 12), 73 | Type: RESPONSE, 74 | Data: json, 75 | } 76 | } 77 | 78 | func MakePack(tp uint32, data []byte) *Pack { 79 | return &Pack{ 80 | Head: 2016, 81 | Len: uint32(len(data) + 12), 82 | Type: tp, 83 | Data: data, 84 | } 85 | } 86 | 87 | func escape(raw string) string { 88 | var ret string 89 | bytes := []byte(raw) 90 | for i := 0; i < len(bytes); i++ { 91 | switch bytes[i] { 92 | case 10: 93 | ret += "\\n" 94 | case 13: 95 | ret += "\\r" 96 | case '\t': 97 | ret += "\\t" 98 | case '"': 99 | ret += "\"" 100 | default: 101 | ret += string(bytes[i]) 102 | } 103 | } 104 | return ret 105 | } 106 | -------------------------------------------------------------------------------- /network/tcp.go: -------------------------------------------------------------------------------- 1 | package network 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "fmt" 7 | "net" 8 | 9 | "../plan" 10 | "../sql/lex" 11 | "../sql/syntax" 12 | ) 13 | 14 | func uint322bytes(u uint32) []byte { 15 | b := make([]byte, 4) 16 | for i := 0; i < 4; i++ { 17 | b[i] = (byte)(u) 18 | u >>= 8 19 | } 20 | return b 21 | } 22 | 23 | func bytes2uint32(b []byte) uint32 { 24 | p := uint32(0) 25 | for i := 3; i >= 0; i-- { 26 | p <<= 8 27 | p |= uint32(b[i]) 28 | } 29 | return p 30 | } 31 | 32 | type TCPSession struct { 33 | Conn *net.TCPConn 34 | Closed bool //是否已经关闭 35 | } 36 | 37 | func (s *TCPSession) SendPack(p *Pack) { 38 | var buff []byte 39 | head := uint322bytes(p.Head) 40 | leng := uint322bytes(p.Len) 41 | typp := uint322bytes(p.Type) 42 | buff = append(head, leng...) 43 | buff = append(buff, typp...) 44 | _, err := s.Conn.Write(buff) 45 | if err != nil { 46 | s.Closed = true 47 | return 48 | } 49 | if p.Data == nil { 50 | return 51 | } 52 | offset := 0 53 | for len(p.Data)-offset > 1024 { 54 | _, err = s.Conn.Write(p.Data[offset : offset+1024]) 55 | if err != nil { 56 | s.Closed = true 57 | return 58 | } 59 | offset += 1024 60 | } 61 | _, err = s.Conn.Write(p.Data[offset:]) 62 | if err != nil { 63 | s.Closed = true 64 | return 65 | } 66 | } 67 | 68 | func (s *TCPSession) RecvPack() *Pack { 69 | 70 | var buff = make([]byte, 12) 71 | readed, err := s.Conn.Read(buff) 72 | 73 | if err != nil { 74 | s.Closed = true 75 | return nil 76 | } 77 | if readed != 12 { 78 | return nil 79 | } 80 | leng := bytes2uint32(buff[4:8]) 81 | ret := &Pack{ 82 | Head: bytes2uint32(buff[0:4]), 83 | Len: leng, 84 | Type: bytes2uint32(buff[8:12]), 85 | } 86 | leng -= 12 87 | buff = make([]byte, 1024) 88 | for leng > 1024 { 89 | _, err = s.Conn.Read(buff) 90 | if err != nil { 91 | s.Closed = true 92 | return nil 93 | } 94 | ret.Data = append(ret.Data, buff...) 95 | } 96 | readed, err = s.Conn.Read(buff) 97 | if err != nil { 98 | s.Closed = true 99 | return nil 100 | } 101 | ret.Data = append(ret.Data, buff[0:readed]...) 102 | return ret 103 | } 104 | 105 | func NewTCPSession(tcpConn *net.TCPConn) *TCPSession { 106 | return &TCPSession{ 107 | Conn: tcpConn, 108 | } 109 | } 110 | 111 | func Listen(port string) { 112 | tcpAddr, err := net.ResolveTCPAddr("tcp4", ":"+port) 113 | if err != nil { 114 | panic(err) 115 | } 116 | l, err := net.ListenTCP("tcp", tcpAddr) 117 | if err != nil { 118 | panic(err) 119 | } 120 | fmt.Println("Server started.") 121 | for { 122 | conn, err := l.AcceptTCP() 123 | if err != nil { 124 | continue 125 | } 126 | reader := bufio.NewReader(bytes.NewReader([]byte(conn.RemoteAddr().String()))) 127 | ip, _ := reader.ReadBytes(':') 128 | ip = ip[:len(ip)-1] 129 | if string(ip) != "127.0.0.1" { 130 | //Refused 131 | conn.Close() 132 | continue 133 | } 134 | tcpSession := NewTCPSession(conn) 135 | go Handler(tcpSession) 136 | } 137 | } 138 | 139 | func Handler(tcpSession *TCPSession) { 140 | for { 141 | p := tcpSession.RecvPack() 142 | if p == nil { 143 | return 144 | } 145 | if p.Head != 2016 { 146 | continue 147 | } 148 | 149 | switch p.Type { 150 | case DIRECT_QUERY: 151 | command := p.Data 152 | ts, _ := lex.Parse(*lex.NewByteReader([]byte(command))) 153 | stn, err := syntax.Parser(syntax.NewTokenReader(ts)) 154 | if err != nil { 155 | pack := Encode(nil, nil, err) 156 | tcpSession.SendPack(pack) 157 | continue 158 | } 159 | r, re, err := plan.DirectPlan(stn) 160 | pack := Encode(r, re, err) 161 | tcpSession.SendPack(pack) 162 | } 163 | } 164 | } 165 | 166 | func Dial(addr string) *TCPSession { 167 | tcpAddr, err := net.ResolveTCPAddr("tcp4", addr) 168 | if err != nil { 169 | panic(err) 170 | } 171 | conn, err := net.DialTCP("tcp", nil, tcpAddr) 172 | if err != nil { 173 | panic(err) 174 | } 175 | tcpSession := NewTCPSession(conn) 176 | return tcpSession 177 | } 178 | -------------------------------------------------------------------------------- /nodejs/example/monkey.js: -------------------------------------------------------------------------------- 1 | var net = require('net') 2 | 3 | var HOST = '127.0.0.1' 4 | var PORT = '2016' 5 | 6 | const CREATE_CONNECTION = 0 7 | const CLOSE_CONNECTION = 1 8 | const DIRECT_QUERY = 2 9 | const RESPONSE = 3 10 | 11 | function MackPack(type, data) { 12 | return { 13 | Head: 2016, 14 | Len: data.length + 12, 15 | Type: type, 16 | Data: data, 17 | } 18 | } 19 | 20 | function uint322bytes(u) { 21 | var b = new Buffer([0,0,0,0]) 22 | for (var i = 0;i<4;i++) { 23 | b[i] = u & 0x000000ff 24 | u >>= 8 25 | } 26 | return b 27 | } 28 | 29 | function bytes2uint32(b) { 30 | var p = 0 31 | for (var i = 3;i >= 0;i--) { 32 | p <<= 8 33 | p |= b[i] 34 | } 35 | return p 36 | } 37 | 38 | var monkey = { 39 | seq: 0, 40 | temp: "", 41 | tempcallback: null, 42 | templen: 0, 43 | client: new net.Socket(), 44 | connect: function(callback) { 45 | this.client.connect({port:'2016', host:'127.0.0.1'}, function() { 46 | this.on('data', monkey.ondata) 47 | if (callback != null) { 48 | callback() 49 | } 50 | }) 51 | }, 52 | query: function(queryStr, callback) { 53 | var buff = Buffer.concat([uint322bytes(2016), 54 | uint322bytes(queryStr.length + 12), 55 | uint322bytes(DIRECT_QUERY)]) 56 | monkey.client.write(buff, function(){ 57 | monkey.client.write(new Buffer(queryStr), function() { 58 | monkey.seq = 0 59 | monkey.temp = "" 60 | monkey.templen = 0 61 | monkey.tempcallback = callback 62 | }) 63 | }) 64 | }, 65 | ondata: function(data) { 66 | if (monkey.seq == 0) { 67 | var head = bytes2uint32(new Buffer([data[0],data[1],data[2],data[3]])) 68 | var len = bytes2uint32(new Buffer([data[4],data[5],data[6],data[7]])) 69 | var type = bytes2uint32(new Buffer([data[8],data[9],data[10],data[11]])) 70 | data = data.toString('ASCII',12) 71 | if (head != 2016) { 72 | monkey.seq = 0 73 | monkey.temp = "" 74 | monkey.templen = 0 75 | return 76 | } 77 | var leng = len - 12 78 | if (leng > 0) { 79 | monkey.templen = len - data.length - 12 80 | monkey.temp += data.slice(12) 81 | if (monkey.templen == 0) { 82 | monkey.temp += data.slice(0, monkey.templen) 83 | monkey.seq = 0 84 | if (monkey.tempcallback != null) 85 | monkey.tempcallback(monkey.temp) 86 | monkey.temp = "" 87 | monkey.templen = 0 88 | return 89 | } 90 | } else { 91 | monkey.seq = 0 92 | if (monkey.tempcallback != null) 93 | monkey.tempcallback(monkey.temp) 94 | monkey.temp = "" 95 | monkey.templen = 0 96 | return 97 | } 98 | monkey.seq++ 99 | } else { 100 | data = data.toString('ASCII') 101 | if (monkey.templen > 0) { 102 | if (data.length > monkey.templen) { 103 | monkey.temp += data.slice(0, monkey.templen) 104 | monkey.seq = 0 105 | if (monkey.tempcallback != null) 106 | monkey.tempcallback(monkey.temp) 107 | monkey.temp = "" 108 | monkey.templen = 0 109 | return 110 | //TODO: data remain 111 | } 112 | monkey.templen -= data.length 113 | monkey.temp += data 114 | if (monkey.templen == 0) { 115 | monkey.temp += data.slice(0, monkey.templen) 116 | monkey.seq = 0 117 | if (monkey.tempcallback != null) 118 | monkey.tempcallback(monkey.temp) 119 | monkey.temp = "" 120 | monkey.templen = 0 121 | return 122 | } 123 | monkey.seq++ 124 | } 125 | } 126 | }, 127 | close: function() { 128 | monkey.client.destroy() 129 | } 130 | } 131 | 132 | /* 133 | monkey.connect(function() { 134 | monkey.query("select * from t1 where id=2", function(data) { 135 | console.log(data) 136 | monkey.query("select * from t1 where id=2", function(data) { 137 | console.log(data) 138 | monkey.query("select * from t1 where id=2", function(data) { 139 | console.log(data) 140 | }) 141 | }) 142 | }) 143 | 144 | })*/ 145 | 146 | module.exports = monkey -------------------------------------------------------------------------------- /nodejs/example/server.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/nodejs/example/server.js -------------------------------------------------------------------------------- /nodejs/monkey.js: -------------------------------------------------------------------------------- 1 | var net = require('net') 2 | 3 | var HOST = '127.0.0.1' 4 | var PORT = '2016' 5 | 6 | const CREATE_CONNECTION = 0 7 | const CLOSE_CONNECTION = 1 8 | const DIRECT_QUERY = 2 9 | const RESPONSE = 3 10 | 11 | function MackPack(type, data) { 12 | return { 13 | Head: 2016, 14 | Len: data.length + 12, 15 | Type: type, 16 | Data: data, 17 | } 18 | } 19 | 20 | function uint322bytes(u) { 21 | var b = new Buffer([0,0,0,0]) 22 | for (var i = 0;i<4;i++) { 23 | b[i] = u & 0x000000ff 24 | u >>= 8 25 | } 26 | return b 27 | } 28 | 29 | function bytes2uint32(b) { 30 | var p = 0 31 | for (var i = 3;i >= 0;i--) { 32 | p <<= 8 33 | p |= b[i] 34 | } 35 | return p 36 | } 37 | 38 | var monkey = { 39 | seq: 0, 40 | temp: "", 41 | tempcallback: null, 42 | templen: 0, 43 | client: new net.Socket(), 44 | connect: function(callback) { 45 | this.client.connect({port:'2016', host:'127.0.0.1'}, function() { 46 | this.on('data', monkey.ondata) 47 | if (callback != null) { 48 | callback() 49 | } 50 | }) 51 | }, 52 | query: function(queryStr, callback) { 53 | var buff = Buffer.concat([uint322bytes(2016), 54 | uint322bytes(queryStr.length + 12), 55 | uint322bytes(DIRECT_QUERY)]) 56 | monkey.client.write(buff, function(){ 57 | monkey.client.write(new Buffer(queryStr), function() { 58 | monkey.seq = 0 59 | monkey.temp = "" 60 | monkey.templen = 0 61 | monkey.tempcallback = callback 62 | }) 63 | }) 64 | }, 65 | ondata: function(data) { 66 | if (monkey.seq == 0) { 67 | var head = bytes2uint32(new Buffer([data[0],data[1],data[2],data[3]])) 68 | var len = bytes2uint32(new Buffer([data[4],data[5],data[6],data[7]])) 69 | var type = bytes2uint32(new Buffer([data[8],data[9],data[10],data[11]])) 70 | data = data.toString('ASCII',12) 71 | if (head != 2016) { 72 | monkey.seq = 0 73 | monkey.temp = "" 74 | monkey.templen = 0 75 | return 76 | } 77 | var leng = len - 12 78 | if (leng > 0) { 79 | monkey.templen = len - data.length - 12 80 | monkey.temp += data.slice(12) 81 | if (monkey.templen == 0) { 82 | monkey.temp += data.slice(0, monkey.templen) 83 | monkey.seq = 0 84 | if (monkey.tempcallback != null) 85 | monkey.tempcallback(monkey.temp) 86 | monkey.temp = "" 87 | monkey.templen = 0 88 | return 89 | } 90 | } else { 91 | monkey.seq = 0 92 | if (monkey.tempcallback != null) 93 | monkey.tempcallback(monkey.temp) 94 | monkey.temp = "" 95 | monkey.templen = 0 96 | return 97 | } 98 | monkey.seq++ 99 | } else { 100 | data = data.toString('ASCII') 101 | if (monkey.templen > 0) { 102 | if (data.length > monkey.templen) { 103 | monkey.temp += data.slice(0, monkey.templen) 104 | monkey.seq = 0 105 | if (monkey.tempcallback != null) 106 | monkey.tempcallback(monkey.temp) 107 | monkey.temp = "" 108 | monkey.templen = 0 109 | return 110 | //TODO: data remain 111 | } 112 | monkey.templen -= data.length 113 | monkey.temp += data 114 | if (monkey.templen == 0) { 115 | monkey.temp += data.slice(0, monkey.templen) 116 | monkey.seq = 0 117 | if (monkey.tempcallback != null) 118 | monkey.tempcallback(monkey.temp) 119 | monkey.temp = "" 120 | monkey.templen = 0 121 | return 122 | } 123 | monkey.seq++ 124 | } 125 | } 126 | }, 127 | close: function() { 128 | monkey.client.destroy() 129 | } 130 | } 131 | 132 | /* 133 | monkey.connect(function() { 134 | monkey.query("select * from t1 where id=2", function(data) { 135 | console.log(data) 136 | monkey.query("select * from t1 where id=2", function(data) { 137 | console.log(data) 138 | monkey.query("select * from t1 where id=2", function(data) { 139 | console.log(data) 140 | }) 141 | }) 142 | }) 143 | 144 | })*/ 145 | 146 | module.exports = monkey -------------------------------------------------------------------------------- /nodejs/readme.md: -------------------------------------------------------------------------------- 1 | # Monkey-Node-Driver 2 | 3 | ## Usage 4 | 5 | Like those shown in `test.js`: 6 | ``` 7 | var monkey = require("./monkey") 8 | monkey.connect(function() { 9 | monkey.query("select * from t1", function(data) { 10 | console.log(data) 11 | monkey.close() 12 | }) 13 | }) 14 | ``` 15 | You can run slowly in this version, and we will perfect it in future versions. 16 | 17 | ## Response 18 | 19 | Response is a json string like: 20 | ``` 21 | {"relation":[{"id":1,"name":"InsZVA","gpa":2},{"id":2,"name":"naloy","gpa":5}],"result":{"affectedRows":2,"usedTime":0}, 22 | "error":null} 23 | ``` 24 | realtion is the query relation, result is something around this query. 25 | 26 | ## Note 27 | 28 | You should close `monkey` after your using, otherwise your node will never stop. -------------------------------------------------------------------------------- /nodejs/test.js: -------------------------------------------------------------------------------- 1 | var monkey = require("./monkey") 2 | monkey.connect(function() { 3 | monkey.query("select * from t1", function(data) { 4 | data = JSON.parse(data) 5 | console.log(data) 6 | monkey.close() 7 | }) 8 | }) -------------------------------------------------------------------------------- /plan/create.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | "strconv" 6 | 7 | "../exe" 8 | 9 | "../index" 10 | "../table" 11 | 12 | "../sql/syntax" 13 | ) 14 | 15 | func CreatePlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 16 | result := NewResult() 17 | if stn.Name != "createtable" { 18 | return nil, nil, errors.New("Expected createtable but get " + stn.Name) 19 | } 20 | r, _, err := IdenticalPlan(stn.Child[0]) 21 | if err != nil { 22 | return nil, nil, err 23 | } 24 | tableName := string(r.Rows[0][0].Raw) 25 | if table.GetTableByName(tableName) != nil { 26 | return nil, nil, errors.New("Table exists.") 27 | } 28 | t := table.CreateTable(tableName) 29 | r, _, err = ColumnDefinesPlan(stn.Child[1]) 30 | if err != nil { 31 | return nil, nil, err 32 | } 33 | for _, v := range r.Rows { 34 | tp, _ := strconv.Atoi(string(v[1].Raw)) 35 | size := 0 36 | fixed := true 37 | switch tp { 38 | case exe.INT: 39 | size = 8 40 | case exe.FLOAT: 41 | size = 8 42 | case exe.STRING: 43 | fixed = false 44 | case exe.ARRAY: 45 | fixed = false 46 | case exe.OBJECT: 47 | size = 8 48 | } 49 | var err error 50 | if len(v) > 2 { 51 | keyS := string(v[2].Raw) 52 | switch keyS { 53 | case "primary key": 54 | err = t.AddFiled(string(v[0].Raw), fixed, size, tp, index.PRIMARY) 55 | case "unique": 56 | err = t.AddFiled(string(v[0].Raw), fixed, size, tp, index.UNIQUE) 57 | default: 58 | err = t.AddFiled(string(v[0].Raw), fixed, size, tp, -1) 59 | } 60 | } else { 61 | err = t.AddFiled(string(v[0].Raw), fixed, size, tp, -1) 62 | } 63 | if err != nil { 64 | t.Drop() 65 | return nil, nil, err 66 | } 67 | } 68 | 69 | result.SetResult(0) 70 | return nil, result, nil 71 | } 72 | 73 | func ColumnDefinesPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 74 | result := NewResult() 75 | relation := exe.NewRelation() 76 | switch stn.Name { 77 | case "ColumnDefine": 78 | if stn.Child[0].Name != "identical" { 79 | return nil, nil, errors.New("Expected indentical but get " + stn.Child[0].Name) 80 | } 81 | varName := stn.Child[0].Value.([]byte) 82 | if stn.Child[1].Name != "type" { 83 | return nil, nil, errors.New("Expected type but get " + stn.Child[1].Name) 84 | } 85 | varType := exe.StringToType(string(stn.Child[1].Value.([]byte))) 86 | row := exe.NewRow([]exe.Value{exe.NewValue(exe.STRING, varName), exe.NewValue(exe.INT, []byte(strconv.Itoa(varType)))}) 87 | relation.AddRow(row) 88 | result.SetResult(1) 89 | return relation, result, nil 90 | case "attributes": 91 | relation, r, err := ColumnDefinesPlan(stn.Child[0]) 92 | newR := exe.NewRelation() 93 | if err != nil { 94 | return nil, nil, err 95 | } 96 | for _, v := range relation.Rows { 97 | newR.AddRow(append(v, exe.NewValue(exe.STRING, stn.Value.([]byte)))) 98 | } 99 | result.SetResult(r.AffectedRows) 100 | return newR, result, nil 101 | case "dot": 102 | r, re, err := ColumnDefinesPlan((stn.Child[0])) 103 | if err != nil { 104 | return nil, nil, err 105 | } 106 | Num := re.AffectedRows 107 | Rows := r.Rows 108 | r, re, err = ColumnDefinesPlan((stn.Child[1])) 109 | if err != nil { 110 | return nil, nil, err 111 | } 112 | Num += re.AffectedRows 113 | Rows = append(Rows, r.Rows...) 114 | for _, v := range Rows { 115 | relation.AddRow(v) 116 | } 117 | result.SetResult(Num) 118 | return relation, result, nil 119 | } 120 | return nil, nil, errors.New("Cannot plan " + stn.Name) 121 | } 122 | -------------------------------------------------------------------------------- /plan/createindex.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../index" 8 | "../table" 9 | 10 | "../sql/syntax" 11 | ) 12 | 13 | func CreateIndexPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 14 | res := NewResult() 15 | if stn.Name != "createindex" { 16 | return nil, nil, errors.New("Expected createtable but get " + stn.Name) 17 | } 18 | values := stn.Value.([][]byte) 19 | tab := table.GetTableByName(string(values[1])) 20 | if tab == nil { 21 | return nil, nil, errors.New("Table not exists") 22 | } 23 | var f *table.Field 24 | var kField int 25 | for k, v := range tab.Fields { 26 | if v.Name == string(values[2]) { 27 | f = &tab.Fields[k] 28 | kField = k 29 | } 30 | } 31 | if f == nil { 32 | return nil, nil, errors.New("field not exists") 33 | } 34 | indexName := string(values[0]) 35 | f.Index = index.CreateIndex(index.UNIQUE, "db", string(values[1]), string(values[2])) 36 | reader := tab.FirstPage.NewReader() 37 | if reader.LoadIndex(f.Index, kField) != nil { 38 | f.Index.Delete() 39 | f.Index = nil 40 | return nil, nil, errors.New("Cannot create index on this column") 41 | } 42 | f.Index.Name = indexName 43 | //TODO: Load Index 44 | res.SetResult(0) 45 | return nil, res, nil 46 | } 47 | -------------------------------------------------------------------------------- /plan/createkv.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../sql/syntax" 8 | "../table" 9 | ) 10 | 11 | func createKVPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 12 | result := NewResult() 13 | if stn.Name != "createkv" { 14 | return nil, nil, errors.New("expected createkv but get:" + stn.Name) 15 | } 16 | tableName := string(stn.Value.([]byte)) 17 | t := table.GetTableByName(string(tableName)) 18 | if t != nil { 19 | return nil, nil, errors.New("table already exists") 20 | } 21 | ktypeR := stn.Child[0].Value.([]byte) 22 | ktype := exe.StringToType(string(ktypeR)) 23 | vtypeR := stn.Child[1].Value.([]byte) 24 | vtype := exe.StringToType(string(vtypeR)) 25 | ret := table.CreateKVTable(tableName, ktype, vtype) 26 | if ret == nil { 27 | return nil, nil, errors.New("create table failed") 28 | } 29 | result.SetResult(0) 30 | return nil, result, nil 31 | } 32 | -------------------------------------------------------------------------------- /plan/delete.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../sql/syntax" 8 | "../table" 9 | ) 10 | 11 | func deletePlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 12 | res := NewResult() 13 | if stn.Name != "delete" { 14 | return nil, nil, errors.New("expected delete but get:" + stn.Name) 15 | } 16 | if stn.Child[0].Name != "identical" { 17 | return nil, nil, errors.New("expected delete but get:" + stn.Name) 18 | } 19 | tName := string(stn.Child[0].Value.([]byte)) 20 | tab := table.GetTableByName(tName) 21 | if tab == nil { 22 | return nil, nil, errors.New("Table not exists") 23 | } 24 | reader := tab.FirstPage.NewReader() 25 | rel := reader.DumpTable() 26 | if stn.Child[1] == nil { 27 | res.SetResult(len(rel.Rows)) 28 | ids := &exe.BitSet{} 29 | for i := 0; i < len(rel.Rows); i++ { 30 | ids.Set(i) 31 | } 32 | tab.Delete(ids) 33 | return nil, res, nil 34 | } else { 35 | where, err := wherePlan(stn.Child[1]) 36 | if err != nil { 37 | return nil, nil, err 38 | } 39 | ids := where(rel) 40 | tab.Delete(ids) 41 | n := 0 42 | for i := 0; i < ids.Len(); i++ { 43 | if ids.Get(i) { 44 | n++ 45 | } 46 | } 47 | res.SetResult(n) 48 | return nil, res, nil 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /plan/drop.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../sql/syntax" 8 | "../table" 9 | ) 10 | 11 | func dropPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 12 | re := NewResult() 13 | if stn.Name != "drop" { 14 | return nil, nil, errors.New("Expected drop but get " + stn.Name) 15 | } 16 | tableName := string(stn.Value.([]byte)) 17 | t := table.GetTableByName(tableName) 18 | if t == nil { 19 | return nil, nil, errors.New("Table not found.") 20 | } 21 | t.Drop() 22 | re.SetResult(0) 23 | return nil, re, nil 24 | } 25 | -------------------------------------------------------------------------------- /plan/dropindex.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../index" 8 | "../sql/syntax" 9 | "../table" 10 | ) 11 | 12 | func dropIndexPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 13 | re := NewResult() 14 | if stn.Name != "dropindex" { 15 | return nil, nil, errors.New("Expected drop but get " + stn.Name) 16 | } 17 | indexName := string(stn.Value.([]byte)) 18 | for _, v := range index.IndexList { 19 | if v.Name == indexName { 20 | tab := table.GetTableByName(v.Table) 21 | if tab != nil { 22 | for k, vv := range tab.Fields { 23 | if vv.Name == v.Key { 24 | tab.Fields[k].Index = nil 25 | } 26 | } 27 | } 28 | v.Delete() 29 | re.SetResult(0) 30 | return nil, re, nil 31 | } 32 | } 33 | return nil, re, errors.New("Cannot find index") 34 | } 35 | -------------------------------------------------------------------------------- /plan/dump.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../sql/syntax" 8 | "../table" 9 | ) 10 | 11 | func dumpPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 12 | re := NewResult() 13 | if stn.Name != "dump" { 14 | return nil, nil, errors.New("Expected dump but get " + stn.Name) 15 | } 16 | tableName := string(stn.Value.([]byte)) 17 | t := table.GetTableByName(tableName) 18 | if t == nil { 19 | return nil, nil, errors.New("Table not found.") 20 | } 21 | reader := t.FirstPage.NewReader() 22 | r := reader.DumpPage() 23 | re.SetResult(len(r.Rows)) 24 | return r, re, nil 25 | } 26 | -------------------------------------------------------------------------------- /plan/getkv.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | "unsafe" 6 | 7 | "../exe" 8 | "../sql/syntax" 9 | "../table" 10 | ) 11 | 12 | func getKVPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 13 | res := NewResult() 14 | if stn.Name != "getkv" { 15 | return nil, nil, errors.New("expected getkv but get:" + stn.Name) 16 | } 17 | tableName := string(stn.Value.([]byte)) 18 | t := table.GetTableByName(tableName) 19 | if t == nil { 20 | return nil, nil, errors.New("table not exist") 21 | } 22 | var k []byte 23 | switch stn.Child[0].ValueType { 24 | case syntax.INT: 25 | k = make([]byte, 8) 26 | i := stn.Child[0].Value.(int) 27 | p_bytes := *(*[8]byte)(unsafe.Pointer(&i)) 28 | for t := 0; t < 8; t++ { 29 | k[t] = p_bytes[t] 30 | } 31 | case syntax.FLOAT: 32 | k = make([]byte, 8) 33 | i := stn.Child[0].Value.(float64) 34 | p_bytes := *(*[8]byte)(unsafe.Pointer(&i)) 35 | for t := 0; t < 8; t++ { 36 | k[t] = p_bytes[t] 37 | } 38 | default: 39 | k = stn.Child[0].Value.([]byte) 40 | } 41 | v, err := t.KVGetValue(k) 42 | if err != nil { 43 | return nil, nil, err 44 | } 45 | rel := exe.NewRelation() 46 | rel.SetColumnNames([]string{"value"}) 47 | rel.AddRow(exe.Row{exe.NewValue(t.Fields[1].Type, v)}) 48 | res.SetResult(1) 49 | return rel, res, nil 50 | } 51 | -------------------------------------------------------------------------------- /plan/identical.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../sql/syntax" 8 | ) 9 | 10 | func IdenticalPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 11 | result := NewResult() 12 | if stn.Name != "identical" { 13 | return nil, nil, errors.New("Expect indentical, but get " + stn.Name) 14 | } 15 | relation := exe.NewRelation() 16 | value := exe.NewValue(exe.STRING, stn.Value.([]byte)) 17 | row := exe.NewRow([]exe.Value{value}) 18 | relation.AddRow(row) 19 | result.SetResult(1) 20 | return relation, result, nil 21 | } 22 | -------------------------------------------------------------------------------- /plan/insert.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | "unsafe" 6 | 7 | "../exe" 8 | "../sql/syntax" 9 | "../table" 10 | ) 11 | 12 | //Unensuarble 13 | func insertPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 14 | re := NewResult() 15 | if stn.Name != "insert" { 16 | return nil, nil, errors.New("Expected insert but get " + stn.Name) 17 | } 18 | r, _, err := IdenticalPlan(stn.Child[0]) 19 | if err != nil { 20 | return nil, nil, err 21 | } 22 | tableName := string(r.Rows[0][0].Raw) 23 | table := table.GetTableByName(tableName) 24 | if table == nil { 25 | return nil, nil, errors.New("Not found this table: " + tableName) 26 | } 27 | r, _, err = fieldsPlan(stn.Child[1]) 28 | if err != nil { 29 | return nil, nil, err 30 | } 31 | columnNames := make([]string, 0) 32 | for i := 0; len(r.Rows) > 0 && i < len(r.Rows[0]); i++ { 33 | columnNames = append(columnNames, string(r.Rows[0][i].Raw)) 34 | } 35 | 36 | datas := make([][][]byte, 0) 37 | r, _, err = rowsPlan(stn.Child[2]) 38 | for _, row := range r.Rows { 39 | rowD := make([][]byte, 0) 40 | for i := 0; i < len(row); i++ { 41 | rowD = append(rowD, row[i].Raw) 42 | } 43 | datas = append(datas, rowD) 44 | } 45 | if len(columnNames) == 0 { 46 | for i := 0; i < len(datas[0]); i++ { 47 | columnNames = append(columnNames, table.Fields[i].Name) 48 | } 49 | } 50 | for i := 0; i < len(datas); i++ { 51 | if len(columnNames) != len(datas[i]) { 52 | return nil, nil, errors.New("Insert fields does not match data row") 53 | } 54 | } 55 | fieldMap := make(map[int]int) 56 | n := 0 57 | for fk, f := range table.Fields { 58 | for dk, v := range columnNames { 59 | if v == f.Name { 60 | fieldMap[fk] = dk 61 | n++ 62 | continue 63 | } 64 | } 65 | } 66 | for k, f := range table.Fields { 67 | if _, ok := fieldMap[k]; f.Index != nil && !ok { 68 | return nil, nil, errors.New(f.Name + " field is a index, but you give no value.") 69 | } 70 | } 71 | if n != len(columnNames) { 72 | return nil, nil, errors.New("Insert fields error, maybe repeat or not exist in table") 73 | } 74 | err = table.Insert(fieldMap, datas) 75 | if err != nil { 76 | return nil, nil, err 77 | } 78 | rel := exe.NewRelation() 79 | re.SetResult(len(stn.Child[2].Child)) 80 | return rel, re, nil 81 | } 82 | 83 | //Unensurable 84 | func fieldsPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 85 | re := NewResult() 86 | r := exe.NewRelation() 87 | if stn == nil { 88 | re.SetResult(0) 89 | return r, re, nil 90 | } 91 | if stn.Name != "fields" { 92 | return nil, nil, errors.New("Expected fields but get " + stn.Name) 93 | } 94 | row := make([]exe.Value, 0) 95 | for i := 0; i < len(stn.Child); i++ { 96 | // ignored spot case 97 | if stn.Child[i].Name != "identical" { 98 | return nil, nil, errors.New("Expected identical but get " + stn.Child[i].Name) 99 | } 100 | row = append(row, exe.NewValue(exe.STRING, stn.Child[i].Value.([]byte))) 101 | } 102 | r.AddRow(row) 103 | re.SetResult(0) 104 | return r, re, nil 105 | } 106 | 107 | //Unensurable 108 | func rowsPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 109 | re := NewResult() 110 | if stn.Name != "rows" { 111 | return nil, nil, errors.New("Expected rows but get " + stn.Name) 112 | } 113 | r := exe.NewRelation() 114 | for rowIndex := 0; rowIndex < len(stn.Child); rowIndex++ { 115 | rowNode := stn.Child[rowIndex] 116 | if rowNode.Name != "row" { 117 | return nil, nil, errors.New("Expected row but get " + stn.Name) 118 | } 119 | var row exe.Row 120 | for i := 0; i < len(rowNode.Child); i++ { 121 | v := rowNode.Child[i] 122 | switch v.Name { 123 | case "value": 124 | var b *[8]byte 125 | var kind int 126 | if v.ValueType == syntax.INT { 127 | i := v.Value.(int) 128 | b = (*[8]byte)(unsafe.Pointer(&i)) 129 | kind = exe.FLOAT 130 | } else { 131 | f := v.Value.(float64) 132 | b = (*[8]byte)(unsafe.Pointer(&f)) 133 | kind = exe.INT 134 | } 135 | var bs []byte 136 | for i := 0; i < 8; i++ { 137 | bs = append(bs, (*b)[i]) 138 | } 139 | row = append(row, exe.NewValue(kind, bs)) 140 | case "string": 141 | row = append(row, exe.NewValue(exe.STRING, v.Value.([]byte))) 142 | } 143 | } 144 | r.AddRow(row) 145 | } 146 | 147 | re.SetResult(1) 148 | return r, re, nil 149 | } 150 | 151 | func uint322bytes(u uint32) []byte { 152 | b := make([]byte, 4) 153 | for i := 0; i < 4; i++ { 154 | b[i] = (byte)(u) 155 | u >>= 8 156 | } 157 | return b 158 | } 159 | -------------------------------------------------------------------------------- /plan/plan.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../recovery" 7 | 8 | "../exe" 9 | "../sql/syntax" 10 | ) 11 | 12 | func DirectPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 13 | defer recovery.RestoreFrame() 14 | switch stn.Name { 15 | case "createtable": 16 | return CreatePlan(stn) 17 | case "createkv": 18 | return createKVPlan(stn) 19 | case "createindex": 20 | return CreateIndexPlan(stn) 21 | case "insert": 22 | return insertPlan(stn) 23 | case "dump": 24 | return dumpPlan(stn) 25 | case "select": 26 | return selectPlan(stn) 27 | case "delete": 28 | return deletePlan(stn) 29 | case "drop": 30 | return dropPlan(stn) 31 | case "dropindex": 32 | return dropIndexPlan(stn) 33 | case "update": 34 | return updatePlan(stn) 35 | case "setkv": 36 | return setKVPlan(stn) 37 | case "getkv": 38 | return getKVPlan(stn) 39 | case "removekv": 40 | return removeKVPlan(stn) 41 | case "showtable": 42 | return showTablePlan(stn) 43 | case "showtables": 44 | return showTablesPlan(stn) 45 | } 46 | return nil, nil, errors.New("Unsopprted plan.") 47 | } 48 | -------------------------------------------------------------------------------- /plan/removekv.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | "unsafe" 6 | 7 | "../exe" 8 | "../sql/syntax" 9 | "../table" 10 | ) 11 | 12 | func removeKVPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 13 | res := NewResult() 14 | if stn.Name != "removekv" { 15 | return nil, nil, errors.New("expected removekv but get:" + stn.Name) 16 | } 17 | tableName := string(stn.Value.([]byte)) 18 | t := table.GetTableByName(tableName) 19 | if t == nil { 20 | return nil, nil, errors.New("table not exist") 21 | } 22 | var k []byte 23 | switch stn.Child[0].ValueType { 24 | case syntax.INT: 25 | k = make([]byte, 8) 26 | i := stn.Child[0].Value.(int) 27 | p_bytes := *(*[8]byte)(unsafe.Pointer(&i)) 28 | for t := 0; t < 8; t++ { 29 | k[t] = p_bytes[t] 30 | } 31 | case syntax.FLOAT: 32 | k = make([]byte, 8) 33 | i := stn.Child[0].Value.(float64) 34 | p_bytes := *(*[8]byte)(unsafe.Pointer(&i)) 35 | for t := 0; t < 8; t++ { 36 | k[t] = p_bytes[t] 37 | } 38 | default: 39 | k = stn.Child[0].Value.([]byte) 40 | } 41 | err := t.KVRemove(k) 42 | if err != nil { 43 | return nil, nil, err 44 | } 45 | res.SetResult(1) 46 | return nil, res, nil 47 | } 48 | -------------------------------------------------------------------------------- /plan/result.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type Result struct { 8 | startTime int64 9 | UsedTime int64 10 | AffectedRows int 11 | } 12 | 13 | func NewResult() *Result { 14 | return &Result{ 15 | startTime: time.Now().UnixNano(), 16 | } 17 | } 18 | 19 | func (r *Result) SetResult(affectedRows int) { 20 | r.AffectedRows = affectedRows 21 | r.UsedTime = time.Now().UnixNano() - r.startTime 22 | } 23 | -------------------------------------------------------------------------------- /plan/select.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../sql/syntax" 8 | "../table" 9 | ) 10 | 11 | func selectPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 12 | res := NewResult() 13 | if stn.Name != "select" { 14 | return nil, nil, errors.New("expected select but get:" + stn.Name) 15 | } 16 | projects, err := selectFieldsPlan(stn.Child[0]) 17 | if err != nil { 18 | return nil, nil, err 19 | } 20 | froms, err := selectFieldsPlan(stn.Child[1]) 21 | if err != nil { 22 | return nil, nil, err 23 | } 24 | var tab *table.Table 25 | if len(froms) == 1 { 26 | tab = table.GetTableByName(froms[0]) 27 | } else { 28 | //TODO: Join 29 | } 30 | if tab == nil { 31 | return nil, nil, errors.New("Table not found.") 32 | } 33 | if len(projects) == 1 && projects[0] == "*" { 34 | projects = []string{} 35 | for i := 0; i < len(tab.Fields); i++ { 36 | projects = append(projects, tab.Fields[i].Name) 37 | } 38 | } 39 | reader := tab.FirstPage.NewReader() 40 | rel := reader.DumpTable() 41 | if stn.Child[2] == nil { 42 | res.SetResult(len(rel.Rows)) 43 | return rel.Project(projects), res, nil 44 | } else { 45 | where, err := wherePlan(stn.Child[2]) 46 | if err != nil { 47 | return nil, nil, err 48 | } 49 | ids := where(rel) 50 | relN := exe.NewRelation() 51 | relN.SetColumnNames(rel.ColumnNames) 52 | for i := 0; i < ids.Len(); i++ { 53 | if ids.Get(i) { 54 | relN.AddRow(rel.Rows[i]) 55 | } 56 | } 57 | res.SetResult(len(relN.Rows)) 58 | return relN.Project(projects), res, nil 59 | } 60 | } 61 | 62 | func selectFieldsPlan(stn *syntax.SyntaxTreeNode) ([]string, error) { 63 | if stn.Name != "fields" { 64 | return nil, errors.New("expected fields but get:" + stn.Name) 65 | } 66 | ret := make([]string, 0) 67 | for i := 0; i < len(stn.Child); i++ { 68 | ret = append(ret, string(stn.Child[i].Value.([]byte))) 69 | } 70 | return ret, nil 71 | } 72 | -------------------------------------------------------------------------------- /plan/setkv.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | "unsafe" 6 | 7 | "../exe" 8 | "../sql/syntax" 9 | "../table" 10 | ) 11 | 12 | func setKVPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 13 | res := NewResult() 14 | if stn.Name != "setkv" { 15 | return nil, nil, errors.New("expected setkv but get:" + stn.Name) 16 | } 17 | tableName := string(stn.Value.([]byte)) 18 | t := table.GetTableByName(tableName) 19 | if t == nil { 20 | return nil, nil, errors.New("table not exist") 21 | } 22 | var k, v []byte 23 | switch stn.Child[0].ValueType { 24 | case syntax.INT: 25 | k = make([]byte, 8) 26 | i := stn.Child[0].Value.(int) 27 | p_bytes := *(*[8]byte)(unsafe.Pointer(&i)) 28 | for t := 0; t < 8; t++ { 29 | k[t] = p_bytes[t] 30 | } 31 | case syntax.FLOAT: 32 | k = make([]byte, 8) 33 | i := stn.Child[0].Value.(float64) 34 | p_bytes := *(*[8]byte)(unsafe.Pointer(&i)) 35 | for t := 0; t < 8; t++ { 36 | k[t] = p_bytes[t] 37 | } 38 | default: 39 | k = stn.Child[0].Value.([]byte) 40 | } 41 | switch stn.Child[1].ValueType { 42 | case syntax.INT: 43 | v = make([]byte, 8) 44 | i := stn.Child[1].Value.(int) 45 | p_bytes := *(*[8]byte)(unsafe.Pointer(&i)) 46 | for t := 0; t < 8; t++ { 47 | v[t] = p_bytes[t] 48 | } 49 | case syntax.FLOAT: 50 | v = make([]byte, 8) 51 | i := stn.Child[1].Value.(float64) 52 | p_bytes := *(*[8]byte)(unsafe.Pointer(&i)) 53 | for t := 0; t < 8; t++ { 54 | v[t] = p_bytes[t] 55 | } 56 | default: 57 | v = stn.Child[1].Value.([]byte) 58 | } 59 | 60 | err := t.KVSetValue(k, v) 61 | if err != nil { 62 | return nil, nil, err 63 | } 64 | res.SetResult(1) 65 | return nil, res, nil 66 | } 67 | -------------------------------------------------------------------------------- /plan/show.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../sql/syntax" 8 | "../table" 9 | ) 10 | 11 | func showTablePlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 12 | res := NewResult() 13 | if stn.Name != "showtable" { 14 | return nil, nil, errors.New("expected showtable but get:" + stn.Name) 15 | } 16 | tableName := string(stn.Value.([]byte)) 17 | t := table.GetTableByName(tableName) 18 | if t == nil { 19 | return nil, nil, errors.New("table not exist") 20 | } 21 | 22 | rel := exe.NewRelation() 23 | rel.SetColumnNames([]string{"filed", "type", "key"}) 24 | for _, v := range t.Fields { 25 | var key string 26 | if v.Index != nil { 27 | key = "Y" 28 | } else { 29 | key = "N" 30 | } 31 | rel.AddRow(exe.Row{exe.NewValue(exe.STRING, []byte(v.Name)), 32 | exe.NewValue(exe.STRING, []byte(exe.TypeToString(v.Type))), 33 | exe.NewValue(exe.STRING, []byte(key))}) 34 | } 35 | 36 | res.SetResult(1) 37 | return rel, res, nil 38 | } 39 | 40 | func showTablesPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 41 | res := NewResult() 42 | if stn.Name != "showtables" { 43 | return nil, nil, errors.New("expected showtables but get:" + stn.Name) 44 | } 45 | 46 | rel := exe.NewRelation() 47 | rel.SetColumnNames([]string{"table"}) 48 | for _, v := range table.TableList { 49 | rel.AddRow(exe.Row{exe.NewValue(exe.STRING, []byte(v.Name))}) 50 | } 51 | 52 | res.SetResult(1) 53 | return rel, res, nil 54 | } 55 | -------------------------------------------------------------------------------- /plan/string.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../sql/syntax" 8 | ) 9 | 10 | func StringPlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 11 | result := NewResult() 12 | if stn.Name != "string" { 13 | return nil, nil, errors.New("Expect string, but get " + stn.Name) 14 | } 15 | relation := exe.NewRelation() 16 | value := exe.NewValue(exe.STRING, stn.Value.([]byte)) 17 | row := exe.NewRow([]exe.Value{value}) 18 | relation.AddRow(row) 19 | result.SetResult(1) 20 | return relation, result, nil 21 | } 22 | -------------------------------------------------------------------------------- /plan/update.go: -------------------------------------------------------------------------------- 1 | package plan 2 | 3 | import ( 4 | "errors" 5 | "unsafe" 6 | 7 | "../exe" 8 | "../sql/syntax" 9 | "../table" 10 | ) 11 | 12 | func updatePlan(stn *syntax.SyntaxTreeNode) (*exe.Relation, *Result, error) { 13 | res := NewResult() 14 | if stn.Name != "update" { 15 | return nil, nil, errors.New("Except update but get: " + stn.Name) 16 | } 17 | tabN := string(stn.Value.([]byte)) 18 | tab := table.GetTableByName(tabN) 19 | if tab == nil { 20 | return nil, nil, errors.New("Table not exists") 21 | } 22 | sets, err := setsPlan(stn.Child[0]) 23 | if err != nil { 24 | return nil, nil, err 25 | } 26 | n := 0 27 | for _, v := range tab.Fields { 28 | if _, ok := sets[v.Name]; ok { 29 | n++ 30 | } 31 | } 32 | if n != len(sets) { 33 | return nil, nil, errors.New("Some fields given are not in table.") 34 | } 35 | reader := tab.FirstPage.NewReader() 36 | rel := reader.DumpTable() 37 | if stn.Child[1] == nil { 38 | res.SetResult(len(rel.Rows)) 39 | ids := &exe.BitSet{} 40 | for i := 0; i < len(rel.Rows); i++ { 41 | ids.Set(i) 42 | } 43 | newColumns := make(map[int]int) 44 | for i := 0; i < len(rel.ColumnNames); i++ { 45 | newColumns[i] = i 46 | } 47 | var data [][][]byte 48 | for r := 0; r < len(rel.Rows); r++ { 49 | data = append(data, make([][]byte, 0)) 50 | for i := 0; i < len(rel.ColumnNames); i++ { 51 | if d, ok := sets[rel.ColumnNames[i]]; ok { 52 | data[r] = append(data[r], d) 53 | } else { 54 | data[r] = append(data[r], rel.Rows[r][i].Raw) 55 | } 56 | } 57 | } 58 | 59 | tab.Delete(ids) 60 | tab.Insert(newColumns, data) 61 | return nil, res, nil 62 | } else { 63 | where, err := wherePlan(stn.Child[1]) 64 | if err != nil { 65 | return nil, nil, err 66 | } 67 | ids := where(rel) 68 | newColumns := make(map[int]int) 69 | for i := 0; i < len(rel.ColumnNames); i++ { 70 | newColumns[i] = i 71 | } 72 | var data [][][]byte 73 | for r := 0; r < len(rel.Rows); r++ { 74 | if ids.Get(r) { 75 | data = append(data, make([][]byte, 0)) 76 | for i := 0; i < len(rel.ColumnNames); i++ { 77 | if d, ok := sets[rel.ColumnNames[i]]; ok { 78 | data[len(data)-1] = append(data[len(data)-1], d) 79 | } else { 80 | data[len(data)-1] = append(data[len(data)-1], rel.Rows[r][i].Raw) 81 | } 82 | } 83 | } 84 | 85 | } 86 | tab.Delete(ids) 87 | tab.Insert(newColumns, data) 88 | n := 0 89 | for i := 0; i < ids.Len(); i++ { 90 | if ids.Get(i) { 91 | n++ 92 | } 93 | } 94 | res.SetResult(n) 95 | return nil, res, nil 96 | } 97 | } 98 | 99 | func setsPlan(stn *syntax.SyntaxTreeNode) (map[string][]byte, error) { 100 | if stn.Name != "sets" { 101 | return nil, errors.New("Except sets but get: " + stn.Name) 102 | } 103 | ret := make(map[string][]byte) 104 | for _, v := range stn.Child { 105 | if v.Name != "set" { 106 | return nil, errors.New("Except set but get: " + v.Name) 107 | } 108 | col := string(v.Value.([]byte)) 109 | switch v.Child[0].Name { 110 | case "value": 111 | var b *[8]byte 112 | if v.Child[0].ValueType == syntax.INT { 113 | i := v.Child[0].Value.(int) 114 | b = (*[8]byte)(unsafe.Pointer(&i)) 115 | } else { 116 | f := v.Child[0].Value.(float64) 117 | b = (*[8]byte)(unsafe.Pointer(&f)) 118 | } 119 | var bs []byte 120 | for i := 0; i < 8; i++ { 121 | bs = append(bs, (*b)[i]) 122 | } 123 | ret[col] = bs 124 | case "string": 125 | ret[col] = v.Child[0].Value.([]byte) 126 | } 127 | } 128 | return ret, nil 129 | } 130 | -------------------------------------------------------------------------------- /python/monkey.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import socket 4 | 5 | CREATE_CONNECTION = 0 6 | CLOSE_CONNECTION = 1 7 | DIRECT_QUERY = 2 8 | RESPONSE = 3 9 | 10 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 11 | 12 | def uint322bytes(a): 13 | i = 0 14 | s = '' 15 | while (i < 4): 16 | s = s + chr(a % 256) 17 | a /= 256 18 | i = i + 1 19 | return s 20 | 21 | def bytes2uint32(a): 22 | p = 0 23 | i = 3 24 | while (i >= 0): 25 | p = p * 256 26 | p = p | ord(a[i]) 27 | i = i - 1 28 | return p 29 | 30 | def MakePack(tp, data): 31 | pack = {'Head': 2016, 'Len': len(data), 'Type': tp, 'Data': data} 32 | return pack 33 | 34 | def Connect(): 35 | s.connect(('127.0.0.1', 2016)) 36 | 37 | def SendPack(p): 38 | head = uint322bytes(p['Head']) 39 | leng = uint322bytes(p['Len']) 40 | typp = uint322bytes(p['Type']) 41 | buff = head + leng + typp 42 | s.send(buff) 43 | if len(p['Data']) == 0: 44 | return 45 | else: 46 | s.send(p['Data']) #If you send much data, please use buffer blocks # Maybe... Python implement it internal 47 | #oh... I don't know Python 48 | 49 | def RecvPack(): 50 | buff = s.recv(12) 51 | leng = bytes2uint32(buff[4:8]) 52 | ret = {'Head': bytes2uint32(buff[0:4]), 'Len': leng, 'Type': bytes2uint32(buff[8:12])} 53 | leng = leng - 12 54 | data = s.recv(leng) 55 | ret['Data'] = data 56 | return ret 57 | 58 | def Close(): 59 | s.close() 60 | 61 | def SendCmd(cmd): 62 | SendPack(MakePack(DIRECT_QUERY, cmd)) 63 | p = RecvPack() 64 | return p['Data'] 65 | 66 | 67 | # Usage 68 | 69 | # import monkey 70 | 71 | # monkey.Connect() 72 | # res = monkey.SendCmd('createkv kv1 string string') 73 | # res = monkey.SendCmd('set kv1 \'a\' \'123456\'') 74 | # res = monkey.SendCmd('get kv1 \'a\'') 75 | # print res 76 | # monkey.Close() -------------------------------------------------------------------------------- /python/monkey.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/python/monkey.pyc -------------------------------------------------------------------------------- /python/test.py: -------------------------------------------------------------------------------- 1 | import monkey 2 | 3 | monkey.Connect() 4 | cmd = raw_input("Monkey>>") 5 | while (cmd != "quit" and cmd != "quit;"): 6 | res = monkey.SendCmd(cmd) 7 | print res 8 | cmd = raw_input("Monkey>>") 9 | monkey.Close() -------------------------------------------------------------------------------- /recovery/exit.go: -------------------------------------------------------------------------------- 1 | package recovery 2 | 3 | import ( 4 | "os" 5 | "os/signal" 6 | 7 | "../index" 8 | "../log" 9 | "../memory" 10 | "../table" 11 | ) 12 | 13 | var Restoring = 0 14 | 15 | func SafeExit() { 16 | Restore() 17 | os.Exit(0) 18 | } 19 | 20 | func init() { 21 | // Capture Ctrl+C signal 22 | go func() { 23 | c := make(chan os.Signal, 1) 24 | signal.Notify(c, os.Interrupt, os.Kill) 25 | s := <-c 26 | log.WriteLog("sys", "Get Signal:"+s.String()+", Safe Exiting...") 27 | SafeExit() 28 | }() 29 | LoadData() 30 | } 31 | 32 | func Restore() { 33 | Restoring = 1 34 | log.WriteLog("sys", "Begin Restore.") 35 | defer log.WriteLog("sys", "Restore Finished.") 36 | memory.Restore() 37 | table.Restore() 38 | index.Restore() 39 | Restoring = 0 40 | } 41 | -------------------------------------------------------------------------------- /recovery/frame.go: -------------------------------------------------------------------------------- 1 | package recovery 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | const ( 8 | FRAME_TIME = 100 * 1000000 9 | ) 10 | 11 | var LastFrame = time.Now().UnixNano() 12 | 13 | func RestoreFrame() { 14 | defer func() { 15 | LastFrame = time.Now().UnixNano() 16 | }() 17 | if Restoring == 1 { 18 | return 19 | } 20 | if time.Now().UnixNano()-LastFrame > FRAME_TIME { 21 | Restore() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /recovery/load.go: -------------------------------------------------------------------------------- 1 | package recovery 2 | 3 | import ( 4 | "../index" 5 | "../memory" 6 | "../table" 7 | ) 8 | 9 | func LoadData() { 10 | memory.Recovery() 11 | index.Recovery() 12 | table.Recovery() 13 | } 14 | -------------------------------------------------------------------------------- /shell: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/shell -------------------------------------------------------------------------------- /shell.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "flag" 6 | "fmt" 7 | "os" 8 | "strings" 9 | 10 | "./common" 11 | "./plan" 12 | "./recovery" 13 | "./sql/lex" 14 | "./sql/syntax" 15 | ) 16 | 17 | var lexSwitch = flag.Bool("L", false, "Show the lex parser result.") 18 | var syntaxSwitch = flag.Bool("S", false, "Show the syntax parser result.") 19 | var performanceSwitch = flag.Bool("P", false, "Show the performance informations.") 20 | var inReader = bufio.NewReader(os.Stdin) 21 | 22 | func welcome() { 23 | fmt.Println("MonkeyDB2 @ 2016") 24 | fmt.Println("Welcome to SQL play ground~") 25 | } 26 | 27 | func loop() bool { 28 | fmt.Print("Monkey>>") 29 | command := "" 30 | 31 | i := 0 32 | for !strings.Contains(command, ";") { 33 | if i > 0 { 34 | fmt.Print(" ->") 35 | } 36 | cmd, _ := inReader.ReadString('\n') 37 | command += cmd 38 | i++ 39 | } 40 | if strings.Contains(command, "quit;") { 41 | return false 42 | } 43 | 44 | ts, _ := lex.Parse(*lex.NewByteReader([]byte(command))) 45 | if *lexSwitch { 46 | fmt.Println(command) 47 | fmt.Println(ts) 48 | } 49 | stn, err := syntax.Parser(syntax.NewTokenReader(ts)) 50 | if err != nil { 51 | fmt.Fprintln(os.Stderr, err.Error()) 52 | return true 53 | } 54 | if *syntaxSwitch { 55 | stn.Print(1) 56 | } 57 | r, re, err := plan.DirectPlan(stn) 58 | if err != nil { 59 | fmt.Fprintln(os.Stderr, err.Error()) 60 | return true 61 | } 62 | r.Print() 63 | fmt.Println(re.AffectedRows, " row(s) affected in ", (float64)(re.UsedTime)/1000000000, "s.") 64 | return true 65 | } 66 | 67 | func bye() { 68 | recovery.SafeExit() 69 | fmt.Println("Bye!") 70 | } 71 | 72 | func main() { 73 | flag.Parse() 74 | if *performanceSwitch { 75 | common.PRINT2 = true 76 | } 77 | welcome() 78 | for loop() { 79 | } 80 | bye() 81 | } 82 | -------------------------------------------------------------------------------- /sql/lex/buffer.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import "errors" 4 | 5 | type ByteReader struct { 6 | data []byte 7 | pos int 8 | } 9 | 10 | func (br *ByteReader) Fork() *ByteReader { 11 | return &ByteReader { 12 | data: br.data, 13 | pos: br.pos, 14 | } 15 | } 16 | 17 | func (br *ByteReader) Read() (byte, error) { 18 | if br.pos >= len(br.data) { 19 | return 0, errors.New("Empty") 20 | } 21 | br.pos++ 22 | return br.data[br.pos - 1], nil 23 | } 24 | 25 | func (br *ByteReader) Empty() bool { 26 | return br.pos >= len(br.data) 27 | } 28 | 29 | func NewByteReader(bytes []byte) *ByteReader { 30 | return &ByteReader { 31 | data: bytes, 32 | } 33 | } -------------------------------------------------------------------------------- /sql/lex/common.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | func digitNfa() *nfa { 4 | nfas := make([]*nfa, 0) 5 | for i := 0; i <= 9; i++ { 6 | nfas = append(nfas, single(byte(int('0')+i))) 7 | } 8 | return or(nfas...) 9 | } 10 | 11 | func integerNfa() *nfa { 12 | return or(repeat(digitNfa()), 13 | links(single('-'), repeat(digitNfa()))) 14 | } 15 | 16 | func floatNfa() *nfa { 17 | return links(integerNfa(), single('.'), repeat(digitNfa())) 18 | } 19 | 20 | func letterNfa() *nfa { 21 | nfas := make([]*nfa, 0) 22 | for i := 0; i < 26; i++ { 23 | nfas = append(nfas, single(byte(int('a')+i))) 24 | } 25 | for i := 0; i < 26; i++ { 26 | nfas = append(nfas, single(byte(int('A')+i))) 27 | } 28 | return or(nfas...) 29 | } 30 | 31 | func identicalNfa() *nfa { 32 | return links(or(single('_'), letterNfa()), chosable(repeat(or(letterNfa(), digitNfa(), single('_'))))) 33 | } 34 | -------------------------------------------------------------------------------- /sql/lex/lex.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | var NFA *statedNfa 4 | var DFA *statedDfa 5 | 6 | type Token struct { 7 | Kind string 8 | Raw []byte 9 | } 10 | 11 | func init() { 12 | NFA = NewBasic() 13 | // defineTokens() 14 | DFA = NFA.ToDFA() 15 | } 16 | 17 | func Parse(input ByteReader) ([]Token, error) { 18 | return DFA.Parse(input) 19 | } 20 | -------------------------------------------------------------------------------- /sql/lex/stateddfa.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import "errors" 4 | 5 | type statedDfa struct { 6 | class []int 7 | array [][]int 8 | accept []bool 9 | state map[int]string 10 | } 11 | 12 | func (n *statedNfa) ToDFA() *statedDfa { 13 | n.Simplify() 14 | pre, dfa2nfa := n.g.toDfa() 15 | ret := &statedDfa{ 16 | state: make(map[int]string), 17 | } 18 | for k, v := range dfa2nfa { 19 | if !pre.v[k] { 20 | continue 21 | } 22 | for _, i := range v { 23 | if !n.g.v[i] { 24 | continue 25 | } 26 | if kind, ok := ret.state[k]; !ok { 27 | ret.state[k] = n.state[i] 28 | } else if n.level[kind] < n.level[n.state[i]] { 29 | ret.state[k] = n.state[i] 30 | } 31 | } 32 | } 33 | ret.class, ret.array, ret.accept = pre.toArray() 34 | // fmt.Println(ret.state) 35 | return ret 36 | } 37 | 38 | func (d *statedDfa) Parse(input ByteReader) ([]Token, error) { 39 | t := make([]Token, 0) 40 | in := ByteReader{ 41 | data: input.data, 42 | } 43 | var err error 44 | for { 45 | fork := ByteReader{ 46 | data: input.data, 47 | pos: in.pos, 48 | } 49 | fork2 := ByteReader{ 50 | data: input.data, 51 | pos: in.pos, 52 | } 53 | tc, _ := fork2.Read() 54 | if tc == '\'' { 55 | b := make([]byte, 0) 56 | tc, _ = fork2.Read() 57 | for tc != '\'' || (len(b) > 0 && b[len(b)-1] == '\\') { 58 | if tc == '\'' { 59 | b[len(b)-1] = '\'' 60 | } else { 61 | b = append(b, tc) 62 | } 63 | tc, _ = fork2.Read() 64 | } 65 | if tc == 0 { 66 | return nil, errors.New("No string end.") 67 | } 68 | token := Token{ 69 | Kind: "string", 70 | Raw: b, 71 | } 72 | t = append(t, token) 73 | in.pos = fork2.pos 74 | continue 75 | } 76 | s, b, err := RunDFA(d.class, d.array, d.accept, fork) 77 | if b == nil { 78 | break 79 | } 80 | token := Token{} 81 | if k, ok := d.state[s]; ok { 82 | token.Kind = k 83 | } 84 | token.Raw = b 85 | t = append(t, token) 86 | if err == nil { 87 | break 88 | } 89 | in.pos += len(b) 90 | if in.pos >= len(in.data) { 91 | break 92 | } 93 | } 94 | return t, err 95 | } 96 | -------------------------------------------------------------------------------- /sql/lex/statednfa.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import ( 4 | "container/list" 5 | "fmt" 6 | ) 7 | 8 | type statedNfa struct { 9 | g *nfa 10 | state map[int]string 11 | level map[string]int 12 | } 13 | 14 | func NewBasic() *statedNfa { 15 | ret := &statedNfa{ 16 | g: identicalNfa(), 17 | state: make(map[int]string), 18 | level: make(map[string]int), 19 | } 20 | acID := len(ret.g.v) - 1 21 | ret.state[acID] = "identical" 22 | ret.level["identical"] = 0 23 | ret.appendToken("intval", 1, integerNfa()) 24 | ret.appendToken("floatval", 0, floatNfa()) 25 | keyword := stringsToken("show", "select", "tables", "from", "where", "update", "delete", "create", "insert", "into", "table", "order", "by", "values", "dump", "set", "drop", "index", "on", "createkv", "remove", "get") 26 | logical := stringsToken("and", "or", "not") 27 | structs := stringsToken("(", ")", ";", ",", ".") 28 | split := stringsToken(" ", "\t", "\n", "\r\n", "\r") 29 | relations := stringsToken(">", "<", ">=", "<=", "=", "<>") 30 | types := stringsToken("int", "float", "string", "object", "array") 31 | attributes := stringsToken("primary key", "unique") 32 | wildcard := stringsToken("*", "%") 33 | ret.appendToken("keyword", 2, keyword) 34 | ret.appendToken("types", 4, types) 35 | ret.appendToken("logical", 4, logical) 36 | ret.appendToken("structs", 4, structs) 37 | ret.appendToken("split", 4, split) 38 | ret.appendToken("relations", 4, relations) 39 | ret.appendToken("unReference", 4, single('`')) 40 | ret.appendToken("reference", 4, single('\'')) 41 | ret.appendToken("attributes", 4, attributes) 42 | ret.appendToken("wildcard", 4, wildcard) 43 | return ret 44 | } 45 | 46 | func NewTest() *statedNfa { 47 | ret := &statedNfa{ 48 | g: strings([]byte("abc")), 49 | state: make(map[int]string), 50 | level: make(map[string]int), 51 | } 52 | acID := len(ret.g.v) - 1 53 | ret.state[acID] = "abc" 54 | ret.level["abc"] = 0 55 | ret.appendToken("abd", 1, strings([]byte("abd"))) 56 | return ret 57 | } 58 | 59 | func (n *statedNfa) Print() { 60 | n.g.Print() 61 | fmt.Println(n.state) 62 | } 63 | 64 | func (n *statedNfa) appendToken(kind string, level int, g *nfa) { 65 | n.level[kind] = level 66 | v := make([]bool, 1) 67 | v[0] = false 68 | v = append(v, n.g.v...) 69 | state := make(map[int]string) 70 | for k, v := range n.state { 71 | state[k+1] = v 72 | } 73 | for l := n.g.e.Front(); l != nil; l = l.Next() { 74 | p := l.Value.(path) 75 | newP := path{ 76 | x: p.x + 1, 77 | y: p.y + 1, 78 | c: p.c, 79 | } 80 | l.Value = newP 81 | } 82 | n.g.e.PushBack(path{ 83 | x: 0, 84 | y: 1, 85 | c: 0, 86 | }) 87 | base := len(v) 88 | v = append(v, g.v...) 89 | for l := g.e.Front(); l != nil; l = l.Next() { 90 | p := l.Value.(path) 91 | n.g.e.PushBack(path{ 92 | x: p.x + base, 93 | y: p.y + base, 94 | c: p.c, 95 | }) 96 | } 97 | for i := base; i < len(v); i++ { 98 | if v[i] { 99 | state[i] = kind 100 | } 101 | } 102 | n.g.addEdge(0, base, 0) 103 | n.g.v = v 104 | n.state = state 105 | } 106 | 107 | func copyEdgeEx(g *statedNfa, v int) { 108 | bag := []int{} 109 | makeBag(g.g, v, &bag) 110 | //If there is a accept in one's bag, one should be accept 111 | for _, i := range bag { 112 | if g.g.v[i] { 113 | g.g.v[v] = true 114 | g.state[v] = g.state[i] 115 | } 116 | } 117 | for l := g.g.e.Front(); l != nil; l = l.Next() { 118 | p := l.Value.(path) 119 | if inBag(p.x, bag) && !inBag(p.y, bag) { 120 | g.g.addEdge(v, p.y, p.c) 121 | } 122 | } 123 | } 124 | 125 | //Clear the null edge. After this step nfa would have more than one accept state 126 | func (g *statedNfa) Simplify() { 127 | //Find all valid state 128 | valid := make([]bool, len(g.g.v)) 129 | valid[0] = true 130 | for l := g.g.e.Front(); l != nil; l = l.Next() { 131 | p := l.Value.(path) 132 | if p.c != 0 { 133 | valid[p.y] = true 134 | markAccept(g.g, p.y, &valid) 135 | } 136 | } 137 | //Add neccessary edges 138 | for i, v := range valid { 139 | if v { 140 | copyEdgeEx(g, i) 141 | } 142 | } 143 | //Delete useless edges 144 | for i := 0; i < len(g.g.v); i++ { 145 | if !valid[i] { 146 | g.g.v[i] = false //Only make it not acceptable rather than delete it 147 | if _, ok := g.state[i]; ok { 148 | delete(g.state, i) 149 | } 150 | } 151 | } 152 | eNew := list.List{} 153 | for l := g.g.e.Front(); l != nil; l = l.Next() { 154 | p := l.Value.(path) 155 | if !(p.c == 0 || !valid[p.x] || !valid[p.y]) { 156 | eNew.PushBack(path{ 157 | x: p.x, 158 | y: p.y, 159 | c: p.c, 160 | }) 161 | } 162 | } 163 | //g.e = eNew 164 | //Delete alone edge 165 | eNew2 := list.List{} 166 | for l := eNew.Front(); l != nil; l = l.Next() { 167 | p := l.Value.(path) 168 | v := p.x 169 | if p.x == 0 { 170 | eNew2.PushBack(path{ 171 | x: p.x, 172 | y: p.y, 173 | c: p.c, 174 | }) 175 | continue 176 | } 177 | flag := 0 178 | for ll := eNew.Front(); ll != nil; ll = ll.Next() { 179 | pp := ll.Value.(path) 180 | if pp.y == v { 181 | flag = 1 182 | break 183 | } 184 | } 185 | if flag != 0 { 186 | eNew2.PushBack(path{ 187 | x: p.x, 188 | y: p.y, 189 | c: p.c, 190 | }) 191 | } 192 | } 193 | g.g.e = eNew2 194 | } 195 | -------------------------------------------------------------------------------- /sql/lex/test/token.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/sql/lex/test/token.exe -------------------------------------------------------------------------------- /sql/lex/test/token.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "../../lex" 5 | "fmt" 6 | "strings" 7 | "os" 8 | ) 9 | 10 | func loop() bool { 11 | fmt.Print("Monkey>>") 12 | str := "" 13 | for !strings.Contains(str, ";") { 14 | buff := "" 15 | fmt.Scanf("%s", &buff) 16 | str += " " + buff 17 | } 18 | if strings.Contains(str, "quit") { 19 | return false 20 | } 21 | ts, err := lex.Parse(*lex.NewByteReader([]byte(str))) 22 | if err != nil { 23 | fmt.Fprintf(os.Stderr, err.Error()) 24 | } 25 | fmt.Println(ts) 26 | return true 27 | } 28 | 29 | func main() { 30 | for loop() {} 31 | } -------------------------------------------------------------------------------- /sql/lex/tokens.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | func stringsToken(tokens ...string) *nfa { 4 | ret := make([]*nfa, 0) 5 | for _, v := range tokens { 6 | ret = append(ret, strings([]byte(v))) 7 | } 8 | return or(ret...) 9 | } 10 | 11 | func defineTokens() { 12 | // log.WriteLogSync("sys", "Start making DFA") 13 | // keyword := stringsToken("select", "from", "where", "update", "delete", "create", "insert", "into", "table", "order", "by", "values", "dump") 14 | // logical := stringsToken("and", "or", "not") 15 | // structs := stringsToken("(", ")", ";", ",", ".") 16 | // split := stringsToken(" ", "\t", "\n", "\r\n", "\r") 17 | // relations := stringsToken(">", "<", ">=", "<=", "=", "<>") 18 | // types := stringsToken("int", "float", "string", "object", "array") 19 | // attributes := stringsToken("primary key", "unique") 20 | // NFA.appendToken("keyword", 2, keyword) 21 | // NFA.appendToken("types", 4, types) 22 | // NFA.appendToken("logical", 4, logical) 23 | // NFA.appendToken("structs", 4, structs) 24 | // NFA.appendToken("split", 4, split) 25 | // NFA.appendToken("relations", 4, relations) 26 | // NFA.appendToken("unReference", 4, single('`')) 27 | // NFA.appendToken("reference", 4, single('\'')) 28 | // NFA.appendToken("attributes", 4, attributes) 29 | // log.WriteLogSync("sys", "DFA prepared") 30 | } 31 | -------------------------------------------------------------------------------- /sql/lex_old/buffer.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import "errors" 4 | 5 | type ByteReader struct { 6 | data []byte 7 | pos int 8 | } 9 | 10 | func (br *ByteReader) Fork() *ByteReader { 11 | return &ByteReader { 12 | data: br.data, 13 | pos: br.pos, 14 | } 15 | } 16 | 17 | func (br *ByteReader) Read() (byte, error) { 18 | if br.pos >= len(br.data) { 19 | return 0, errors.New("Empty") 20 | } 21 | br.pos++ 22 | return br.data[br.pos - 1], nil 23 | } 24 | 25 | func (br *ByteReader) Empty() bool { 26 | return br.pos >= len(br.data) 27 | } 28 | 29 | func NewByteReader(bytes []byte) *ByteReader { 30 | return &ByteReader { 31 | data: bytes, 32 | } 33 | } -------------------------------------------------------------------------------- /sql/lex_old/dfa_test.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import "testing" 4 | import _"fmt" 5 | 6 | func Test_toDfa(t *testing.T) {/* 7 | g := links(single('a'), single('b'), single('c'), chosable(repeat(or(single('a'), single('b'), single('c')))), 8 | strings([]byte("cba"))) 9 | g.Simplify() 10 | g.Print() 11 | g.toDfa()*/ 12 | } 13 | 14 | func TestRunDFA(t *testing.T) { 15 | g := links(single('a'), single('b'), single('c'), chosable(repeat(or(single('a'), single('b'), single('c')))), 16 | strings([]byte("cba"))) 17 | g.Simplify() 18 | dfa := g.toDfa() 19 | //dfa.Print() 20 | c, a, ac := dfa.toArray() 21 | _, _, err := RunDFA(c, a, ac, ByteReader { 22 | data: []byte("abcbsa"), 23 | }) 24 | if err == nil { 25 | t.Error("abcbsa, s not checked") 26 | } 27 | _, _, err = RunDFA(c, a, ac, ByteReader { 28 | data: []byte("abcbbbcba"), 29 | }) 30 | if err != nil { 31 | t.Error("abcbbbcba with an error:" + err.Error()) 32 | } 33 | _, _, err = RunDFA(c, a, ac, ByteReader { 34 | data: []byte("abcbbbba"), 35 | }) 36 | if err == nil { 37 | t.Error("abcbbbba success") 38 | } 39 | _, get, err := RunDFA(c, a, ac, ByteReader { 40 | data: []byte("abcbbbcbaaa"), 41 | }) 42 | if err == nil { 43 | t.Error("abcbbbcbaaa success") 44 | } 45 | if string(get) != "abcbbbcba" { 46 | t.Error("abcbbbcbaaa, abcbbbcba not get") 47 | } 48 | _, _, err = RunDFA(c, a, ac, ByteReader { 49 | data: []byte("abcbbbcba"), 50 | }) 51 | if err != nil { 52 | t.Error("abcbbbcba fail") 53 | } 54 | } 55 | 56 | func Test_findBag(t *testing.T) { 57 | g := links(strings([]byte("sel")), or(single('e'), single('p')), strings([]byte("ekk"))) 58 | g.Simplify() 59 | dfa1 := g.toDfa() 60 | g2 := strings([]byte("seleee")) 61 | g2.Simplify() 62 | dfa2 := g2.toDfa() 63 | b1, b2 := findBag(dfa1, dfa2) 64 | if b1[3] != 3 || b1[5] != 6 || b2[5] != 5 { 65 | t.Error("fing bag error") 66 | } 67 | } 68 | 69 | func Test_addDfa(t *testing.T) { 70 | g := links(strings([]byte("sel")), or(single('e'), single('p')), strings([]byte("ekk"))) 71 | g.Simplify() 72 | dfa1 := g.toDfa() 73 | g2 := strings([]byte("seleee")) 74 | g2.Simplify() 75 | dfa2 := g2.toDfa() 76 | if dfa1.addDfa(dfa2)[0] != 14 { 77 | t.Error("accept error") 78 | }/* 79 | f := links(repeat(numberNfa()), single('.'), chosable(repeat(numberNfa()))) 80 | i := repeat(or(numberNfa())) 81 | f.Simplify() 82 | i.Simplify() 83 | dfa1 = f.toDfa() 84 | dfa2 = i.toDfa() 85 | dfa1.addDfa(dfa2) 86 | a, b, c := dfa1.toArray() 87 | fmt.Println(RunDFA(a, b, c, ByteReader{data:[]byte("1234566")})) 88 | fmt.Println(" --- ")*/ 89 | } -------------------------------------------------------------------------------- /sql/lex_old/identical.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import "fmt" 4 | 5 | func allCharsExcept(exc byte) []byte { 6 | ac := make([]byte, 0) 7 | for l := byte('a');l < 'z';l++ { 8 | if l == exc { 9 | continue 10 | } 11 | ac = append(ac, l) 12 | } 13 | for l := byte('A');l < 'Z';l++ { 14 | if l == exc { 15 | continue 16 | } 17 | ac = append(ac, l) 18 | } 19 | for l := byte('0');l < '9';l++ { 20 | if l == exc { 21 | continue 22 | } 23 | ac = append(ac, l) 24 | } 25 | if exc != byte('_') { 26 | ac = append(ac, '_') 27 | } 28 | return ac 29 | } 30 | 31 | func identicalNfa() *nfa { 32 | return links(repeat(or(letterNfa(), single('_'))), chosable(repeat(or(numberNfa(), letterNfa(), single('_'))))) 33 | } 34 | 35 | func generateIdenticalExceptString(exc []byte) *nfa { 36 | fmt.Println(len(exc)) 37 | defer fmt.Println("return") 38 | if len(exc) == 1 { 39 | chars := allCharsExcept(exc[0]) 40 | g := single(chars[0]) 41 | for i := 1;i < len(chars);i++ { 42 | g = or(g, single(chars[i])) 43 | } 44 | return links(g, identicalNfa()) 45 | } 46 | return or(generateIdenticalExceptString([]byte{exc[0]}), 47 | links(single(exc[0]), generateIdenticalExceptString(exc[1:]))) 48 | } 49 | 50 | func generateIdenticalExceptStrings(exc [][]byte) *nfa { 51 | g := generateIdenticalExceptString(exc[0]) 52 | for i := 1;i < len(exc);i++ { 53 | g = or(g, generateIdenticalExceptString(exc[i])) 54 | } 55 | fmt.Println("ok") 56 | return g 57 | } -------------------------------------------------------------------------------- /sql/lex_old/lex.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import ( 4 | "../../log" 5 | ) 6 | 7 | type DFA struct { 8 | accept []bool 9 | array [][]int 10 | class []int 11 | } 12 | 13 | var ( 14 | reservesDfa DFA 15 | normalDfa DFA 16 | ac map[int]string 17 | dfaKeyword *preDfa 18 | dfaOther *preDfa 19 | ) 20 | 21 | type Token struct { 22 | Kind string 23 | Raw []byte 24 | } 25 | 26 | func DefineToken(token string, g *nfa) { 27 | if dfaKeyword == nil { 28 | fork := g.fork() 29 | fork.Simplify() 30 | dfaKeyword = fork.toDfa() 31 | for i, v := range dfaKeyword.v { 32 | if v { 33 | ac[i] = token 34 | } 35 | } 36 | } else { 37 | fork := g.fork() 38 | fork.Simplify() 39 | for _, v := range dfaKeyword.addDfa(fork.toDfa()) { 40 | ac[v] = token 41 | } 42 | } 43 | } 44 | 45 | func DefineCommon(token string, g *nfa) { 46 | if dfaOther == nil { 47 | fork := g.fork() 48 | fork.Simplify() 49 | dfaOther = fork.toDfa() 50 | for i, v := range dfaOther.v { 51 | if v { 52 | ac[i] = token 53 | } 54 | } 55 | } else { 56 | fork := g.fork() 57 | fork.Simplify() 58 | for _, v := range dfaOther.addDfa(fork.toDfa()) { 59 | ac[v] = token 60 | } 61 | } 62 | } 63 | 64 | func init() { 65 | ac = make(map[int]string) 66 | defineTokens() 67 | reservesDfa.class, reservesDfa.array, reservesDfa.accept = dfaKeyword.toArray() 68 | normalDfa.class, normalDfa.array, normalDfa.accept = dfaOther.toArray() 69 | log.WriteLogSync("sys", "lex module ready") 70 | } 71 | 72 | func numberNfa() *nfa { 73 | nfas := make([]*nfa, 0) 74 | for i := 0; i < 9; i++ { 75 | nfas = append(nfas, single(byte(int('0')+i))) 76 | } 77 | return or(nfas...) 78 | } 79 | 80 | func letterNfa() *nfa { 81 | nfas := make([]*nfa, 0) 82 | for i := 0; i < 26; i++ { 83 | nfas = append(nfas, single(byte(int('a')+i))) 84 | } 85 | for i := 0; i < 26; i++ { 86 | nfas = append(nfas, single(byte(int('A')+i))) 87 | } 88 | return or(nfas...) 89 | } 90 | 91 | func stringsToken(tokens ...string) *nfa { 92 | ret := make([]*nfa, 0) 93 | for _, v := range tokens { 94 | ret = append(ret, strings([]byte(v))) 95 | } 96 | return or(ret...) 97 | } 98 | 99 | func Parse(input ByteReader) ([]Token, error) { 100 | log.WriteLogSync("query", "Parser:"+string(input.data)) 101 | defer log.WriteLogSync("query", "Parser finished") 102 | t := make([]Token, 0) 103 | in := ByteReader{ 104 | data: input.data, 105 | } 106 | var err error 107 | for { 108 | fork := ByteReader{ 109 | data: input.data, 110 | pos: in.pos, 111 | } 112 | s1, b1, err1 := RunDFA(reservesDfa.class, reservesDfa.array, reservesDfa.accept, fork) 113 | s2, b2, err2 := RunDFA(normalDfa.class, normalDfa.array, normalDfa.accept, fork) 114 | var s int 115 | var b []byte 116 | if b1 == nil { 117 | if b2 == nil { 118 | break 119 | } 120 | b = b2 121 | s = s2 122 | err = err2 123 | } else if b2 != nil { 124 | if len(b2) > len(b1) { 125 | b = b2 126 | s = s2 127 | err = err2 128 | } else { 129 | b = b1 130 | s = s1 131 | err = err1 132 | } 133 | } else { 134 | b = b1 135 | s = s1 136 | err = err1 137 | } 138 | token := Token{} 139 | if k, ok := ac[s]; ok { 140 | token.Kind = k 141 | } 142 | token.Raw = b 143 | t = append(t, token) 144 | if err == nil { 145 | break 146 | } 147 | in.pos += len(b) 148 | if in.pos >= len(in.data) { 149 | break 150 | } 151 | } 152 | return t, err 153 | } 154 | -------------------------------------------------------------------------------- /sql/lex_old/lex_test.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import "testing" 4 | import "fmt" 5 | 6 | func Test_DefineTokens(t *testing.T) { 7 | // g := links(single('a'), single('b'), single('c'), chosable(repeat(or(single('a'), single('b'), single('c')))), 8 | // strings([]byte("cba"))) 9 | // DefineToken("Test", g) 10 | // c, a, acs := dfa.toArray() 11 | // s, _, _ := RunDFA(c, a, acs, ByteReader { data: []byte("abcbbcba") }) 12 | // flag := 0 13 | // for _, i := range ac["Test"] { 14 | // if i == s { 15 | // flag = 1 16 | // break 17 | // } 18 | // } 19 | // if flag != 1 { 20 | // t.Error("fail") 21 | // } 22 | } 23 | 24 | func TestParse(t *testing.T) { 25 | raw := []byte("select `name`,kk from `table` where a>= 123 and 1.4>") 26 | fmt.Println(Parse(ByteReader{data: raw})) 27 | } -------------------------------------------------------------------------------- /sql/lex_old/nfa_test.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import "testing" 4 | 5 | func Test_merge(t *testing.T) { 6 | g := single('a') 7 | g2 := single('b') 8 | g3 := merge(g, g2) 9 | if len(g3.v) != 4 { 10 | t.Error("merge len v error") 11 | } 12 | if g3.e.Len() != 2 { 13 | t.Error("merge len e error") 14 | } 15 | } 16 | 17 | func Test_link(t *testing.T) { 18 | g := single('a') 19 | g2 := single('b') 20 | g3 := link(g, g2) 21 | if len(g3.v) != 4 { 22 | t.Error("link len v error") 23 | } 24 | if g3.e.Len() != 3 { 25 | t.Error("link len e error") 26 | } 27 | } 28 | 29 | func Test_or(t *testing.T) { 30 | g := single('a') 31 | g2 := single('b') 32 | g4 := single('c') 33 | g3 := link(g, g2) 34 | g5 := link(g, g4) 35 | g6 := or(g3, g5) 36 | if len(g6.v) != 10 { 37 | t.Error("or len v error") 38 | } 39 | } 40 | 41 | func Test_repeat(t *testing.T) { 42 | g := single('a') 43 | g2 := single('c') 44 | g3 := link(g, g2) 45 | g4 := repeat(g3) 46 | if len(g4.v) != 9 { 47 | t.Error("repeat len v error") 48 | } 49 | } 50 | 51 | func Test_chosable(t *testing.T) { 52 | g := single('a') 53 | g2 := single('c') 54 | g3 := chosable(g2) 55 | g4 := link(g, g3) 56 | if len(g4.v) != 4 { 57 | t.Error("or len v error") 58 | } 59 | } 60 | 61 | func TestTest(t *testing.T) { 62 | g := links(single('a'), single('b'), single('c'), chosable(repeat(or(single('a'), single('b'), single('c')))), 63 | strings([]byte("cba"))) 64 | input := &ByteReader { 65 | data: []byte("abcabcccccba"), 66 | } 67 | if !g.Test(input, 0, false) { 68 | t.Error("abcabcccccba fail") 69 | } 70 | input = &ByteReader { 71 | data: []byte("abccba"), 72 | } 73 | if !g.Test(input, 0, false) { 74 | t.Error("abccba fail") 75 | } 76 | input = &ByteReader { 77 | data: []byte("abcba"), 78 | } 79 | if g.Test(input, 0, false) { 80 | t.Error("abcba success") 81 | } 82 | input = &ByteReader { 83 | data: []byte("acba"), 84 | } 85 | if g.Test(input, 0, false) { 86 | t.Error("acba success") 87 | } 88 | } 89 | 90 | func TestSimplify(t *testing.T) { 91 | g := links(single('a'), or(links(single('c'), chosable(links(single('c'), single('e'), single('p'), single('t')))), 92 | links(single('b'), single('o'), single('r'), single('t')))) 93 | g.Simplify() 94 | input := &ByteReader { 95 | data: []byte{'a', 'c', 'c'}, 96 | } 97 | if g.Test(input, 0, false) { 98 | t.Error("acc success") 99 | } 100 | input = &ByteReader { 101 | data: []byte{'a', 'c'}, 102 | } 103 | if !g.Test(input, 0, false) { 104 | t.Error("ac fail") 105 | } 106 | input = &ByteReader { 107 | data: []byte{'a', 'c', 'c', 'e', 'p', 't'}, 108 | } 109 | if !g.Test(input, 0, false) { 110 | t.Error("accept fail") 111 | } 112 | input = &ByteReader { 113 | data: []byte{'a', 'b', 'c', 'e', 'p', 't'}, 114 | } 115 | if g.Test(input, 0, false) { 116 | t.Error("abcept success") 117 | } 118 | input = &ByteReader { 119 | data: []byte{'a', 'b', 'o', 'r', 't'}, 120 | } 121 | if !g.Test(input, 0, false) { 122 | t.Error("abort fail") 123 | } 124 | 125 | g = links(single('a'), single('b'), single('c'), chosable(repeat(or(single('a'), single('b'), single('c')))), 126 | strings([]byte("cba"))) 127 | g.Simplify() 128 | input = &ByteReader { 129 | data: []byte("abcabcabcabccba"), 130 | } 131 | if !g.Test(input, 0, false) { 132 | t.Error("abcabcabcabccba fail") 133 | } 134 | input = &ByteReader { 135 | data: []byte("abccba"), 136 | } 137 | if !g.Test(input, 0, false) { 138 | t.Error("abccba fail") 139 | } 140 | input = &ByteReader { 141 | data: []byte("abcba"), 142 | } 143 | if g.Test(input, 0, false) { 144 | t.Error("abcba success") 145 | } 146 | input = &ByteReader { 147 | data: []byte("acba"), 148 | } 149 | if g.Test(input, 0, false) { 150 | t.Error("acba success") 151 | } 152 | } -------------------------------------------------------------------------------- /sql/lex_old/reverse.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | var ( 4 | reverseTable = [][]byte { 5 | []byte("abort"), 6 | []byte("abs"), 7 | []byte("absolute"), 8 | []byte("access"), 9 | []byte("action"), 10 | []byte("ada"), 11 | []byte("add"), 12 | []byte("admin"), 13 | []byte("after"), 14 | []byte("aggregate"), 15 | []byte("alias"), 16 | []byte("all"), 17 | []byte("allocate"), 18 | []byte("alter"), 19 | []byte("analyse"), 20 | []byte("analyze"), 21 | []byte("and"), 22 | []byte("any"), 23 | []byte("are"), 24 | []byte("array"), 25 | []byte("as"), 26 | []byte("asc"), 27 | []byte("asensitive"), 28 | []byte("assertion"), 29 | []byte("assignment"), 30 | []byte("asymmetric"), 31 | []byte("at"), 32 | []byte("atomic"), 33 | []byte("authorization"), 34 | []byte("avg"), 35 | []byte("backward"), 36 | []byte("before"), 37 | []byte("begin"), 38 | []byte("between"), 39 | []byte("bigint"), 40 | []byte("binary"), 41 | []byte("bit"), 42 | []byte("bitvar"), 43 | []byte("bit_length"), 44 | []byte("blob"), 45 | []byte("boolean"), 46 | []byte("by"), 47 | []byte("c"), 48 | []byte("cache"), 49 | []byte("call"), 50 | []byte("called"), 51 | []byte("cardinality"), 52 | []byte("cascade"), 53 | []byte("cascaded"), 54 | []byte("case"), 55 | []byte("cast"), 56 | []byte("catalog"), 57 | []byte("catalog_name"), 58 | []byte("chain"), 59 | []byte("char"), 60 | []byte("characer"), 61 | []byte("select"), 62 | []byte("int"), 63 | []byte("varchar"), 64 | []byte("float"), 65 | []byte("object"), 66 | []byte("from"), 67 | []byte("where"), 68 | []byte("table"), 69 | []byte("update"), 70 | []byte("delete"), 71 | []byte("insert"), 72 | []byte("into"), 73 | []byte("by"), 74 | []byte("order"), 75 | []byte("group"), 76 | []byte("limit"), 77 | } 78 | ) -------------------------------------------------------------------------------- /sql/lex_old/test/token.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/InsZVA/MonkeyDB2/63f328ccc5f26711c4f89746fab93ab32724671b/sql/lex_old/test/token.exe -------------------------------------------------------------------------------- /sql/lex_old/test/token.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "../../lex" 5 | "fmt" 6 | "strings" 7 | "os" 8 | ) 9 | 10 | func loop() bool { 11 | fmt.Print("Monkey>>") 12 | str := "" 13 | for !strings.Contains(str, ";") { 14 | buff := "" 15 | fmt.Scanf("%s", &buff) 16 | str += " " + buff 17 | } 18 | if strings.Contains(str, "quit") { 19 | return false 20 | } 21 | ts, err := lex.Parse(*lex.NewByteReader([]byte(str))) 22 | if err != nil { 23 | fmt.Fprintf(os.Stderr, err.Error()) 24 | } 25 | fmt.Println(ts) 26 | return true 27 | } 28 | 29 | func main() { 30 | for loop() {} 31 | } -------------------------------------------------------------------------------- /sql/lex_old/tokens.go: -------------------------------------------------------------------------------- 1 | package lex 2 | 3 | import ( 4 | "../../log" 5 | ) 6 | 7 | func defineTokens() { 8 | log.WriteLogSync("sys", "Start making DFA") 9 | keyword := stringsToken("select", "from", "where", "update", "delete", "create", "insert", "into", "table", "order", "by", "values", "dump") 10 | logical := stringsToken("and", "or", "not") 11 | structs := stringsToken("(", ")", ";", ",", ".") 12 | split := stringsToken(" ", "\t", "\n", "\r\n", "\r") 13 | relations := stringsToken(">", "<", ">=", "<=", "=", "<>") 14 | types := stringsToken("int", "float", "string", "object", "array") 15 | attributes := stringsToken("primary key", "unique") 16 | DefineCommon("floatval", links(repeat(numberNfa()), single('.'), chosable(repeat(numberNfa())))) 17 | DefineCommon("intval", repeat(numberNfa())) 18 | DefineCommon("identical", identicalNfa()) 19 | DefineToken("keyword", keyword) 20 | DefineToken("types", types) 21 | DefineToken("logical", logical) 22 | DefineToken("structs", structs) 23 | DefineToken("split", split) 24 | DefineToken("relations", relations) 25 | DefineToken("unReference", single('`')) 26 | DefineToken("reference", single('\'')) 27 | DefineToken("attributes", attributes) 28 | log.WriteLogSync("sys", "DFA prepared") 29 | } 30 | -------------------------------------------------------------------------------- /sql/syntax/calculate.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "strconv" 5 | ) 6 | 7 | func calculateInt(raw []byte) int { 8 | i, err := strconv.Atoi(string(raw)) 9 | if err != nil { 10 | return 0 11 | } 12 | return i 13 | } 14 | 15 | func calculateFloat(raw []byte) float64 { 16 | //TODO : Other way to detect '.' 17 | f, err := strconv.ParseFloat(string(raw), 64) 18 | if err != nil { 19 | fI, err := (strconv.Atoi(string(raw))) 20 | 21 | if err != nil { 22 | return 0.0 23 | } else { 24 | f = float64(fI) 25 | return f 26 | } 27 | } 28 | return f 29 | } 30 | -------------------------------------------------------------------------------- /sql/syntax/checkend.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | func checkend(tr *TokenReader) bool { 4 | t := tr.Read() 5 | if t.Kind == "split" { 6 | t = tr.Read() 7 | } 8 | if t.Kind == "structs" && string(t.Raw) == ";" { 9 | t = tr.Read() 10 | for t.Kind == "split" { 11 | t = tr.Read() 12 | } 13 | if !tr.Empty() { 14 | return false 15 | } 16 | return true 17 | } 18 | return false 19 | } 20 | -------------------------------------------------------------------------------- /sql/syntax/create.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func typeParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind == "types" { 10 | return &SyntaxTreeNode{ 11 | Name: "type", 12 | Value: t.Raw, 13 | ValueType: NAME, 14 | }, nil 15 | } 16 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 17 | } 18 | 19 | func columndefineParser(tr *TokenReader) (*SyntaxTreeNode, error) { 20 | t := tr.Read() 21 | if t.Kind != "identical" { 22 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 23 | } 24 | tpNode, err := typeParser(tr) 25 | if err != nil { 26 | return nil, err 27 | } 28 | first := &SyntaxTreeNode{ 29 | Name: "ColumnDefine", 30 | Value: nil, 31 | Child: []*SyntaxTreeNode{ 32 | &SyntaxTreeNode{ 33 | Name: "identical", 34 | Value: t.Raw, 35 | ValueType: NAME, 36 | }, 37 | tpNode, 38 | }} 39 | fork := tr.Fork() 40 | t2 := fork.Read() 41 | if t2.Kind == "attributes" { 42 | tr.Next(1) 43 | first = &SyntaxTreeNode{ 44 | Name: "attributes", 45 | Value: t2.Raw, 46 | ValueType: NAME, 47 | Child: []*SyntaxTreeNode{ 48 | first, 49 | }, 50 | } 51 | } 52 | fork = tr.Fork() 53 | t2 = fork.Read() 54 | if t2.Kind == "structs" && string(t2.Raw) == "," { 55 | tr.Next(1) 56 | nexts, err := columndefineParser(tr) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return &SyntaxTreeNode{ 61 | Name: "dot", 62 | Child: []*SyntaxTreeNode{ 63 | first, nexts, 64 | }, 65 | }, nil 66 | } 67 | 68 | return first, nil 69 | } 70 | 71 | func createtableParser(tr *TokenReader) (*SyntaxTreeNode, error) { 72 | t1 := tr.Read() 73 | if t1.Kind != "keyword" || string(t1.Raw) != "create" { 74 | return nil, errors.New("You have a syntax error near:" + string(t1.Raw)) 75 | } 76 | t2 := tr.Read() 77 | if t2.Kind != "keyword" || string(t2.Raw) != "table" { 78 | return nil, errors.New("You have a syntax error near:" + string(t2.Raw)) 79 | } 80 | t3 := tr.Read() 81 | if t3.Kind != "identical" { 82 | return nil, errors.New("You have a syntax error near:" + string(t3.Raw)) 83 | } 84 | t4 := tr.Read() 85 | if t4.Kind != "structs" || string(t4.Raw) != "(" { 86 | return nil, errors.New("You have a syntax error near:" + string(t4.Raw)) 87 | } 88 | columndefine, err := columndefineParser(tr) 89 | if err != nil { 90 | return nil, err 91 | } 92 | t5 := tr.Read() 93 | if t5.Kind != "structs" || string(t5.Raw) != ")" { 94 | return nil, errors.New("You have a syntax error near:" + string(t5.Raw)) 95 | } 96 | return &SyntaxTreeNode{ 97 | Name: "createtable", 98 | Child: []*SyntaxTreeNode{ 99 | &SyntaxTreeNode{ 100 | Name: "identical", 101 | ValueType: NAME, 102 | Value: t3.Raw, 103 | }, 104 | columndefine, 105 | }, 106 | }, nil 107 | } 108 | -------------------------------------------------------------------------------- /sql/syntax/createindex.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func createIndexParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind != "keyword" || string(t.Raw) != "create" { 10 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 11 | } 12 | t = tr.Read() 13 | if t.Kind != "keyword" || string(t.Raw) != "index" { 14 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 15 | } 16 | t = tr.Read() 17 | if t.Kind != "identical" { 18 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 19 | } 20 | indexName := t.Raw 21 | t = tr.Read() 22 | if t.Kind != "keyword" || string(t.Raw) != "on" { 23 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 24 | } 25 | t = tr.Read() 26 | if t.Kind != "identical" { 27 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 28 | } 29 | tableName := t.Raw 30 | t = tr.Read() 31 | if t.Kind != "structs" || string(t.Raw) != "(" { 32 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 33 | } 34 | t = tr.Read() 35 | if t.Kind != "identical" { 36 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 37 | } 38 | fieldName := t.Raw 39 | t = tr.Read() 40 | if t.Kind != "structs" || string(t.Raw) != ")" { 41 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 42 | } 43 | return &SyntaxTreeNode{ 44 | Name: "createindex", 45 | Value: [][]byte{indexName, tableName, fieldName}, 46 | }, nil 47 | } 48 | -------------------------------------------------------------------------------- /sql/syntax/createkv.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func createKVParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind != "keyword" || string(t.Raw) != "createkv" { 10 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 11 | } 12 | t = tr.Read() 13 | if t.Kind != "identical" { 14 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 15 | } 16 | tableName := t.Raw 17 | t = tr.Read() 18 | if t.Kind != "types" { 19 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 20 | } 21 | ktype := t.Raw 22 | t = tr.Read() 23 | if t.Kind != "types" { 24 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 25 | } 26 | vtype := t.Raw 27 | return &SyntaxTreeNode{ 28 | Name: "createkv", 29 | Value: tableName, 30 | ValueType: NAME, 31 | Child: []*SyntaxTreeNode{ 32 | &SyntaxTreeNode{ 33 | Name: "ktype", 34 | Value: ktype, 35 | }, 36 | &SyntaxTreeNode{ 37 | Name: "vtype", 38 | Value: vtype, 39 | }, 40 | }, 41 | }, nil 42 | } 43 | -------------------------------------------------------------------------------- /sql/syntax/delete.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func deleteParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind != "keyword" && string(t.Raw) != "delete" { 10 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 11 | } 12 | t = tr.Read() 13 | if t.Kind != "keyword" || string(t.Raw) != "from" { 14 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 15 | } 16 | tName := tr.Read() 17 | if tName.Kind != "identical" { 18 | return nil, errors.New("You have a syntax error near: " + string(tName.Raw)) 19 | } 20 | where, err := whereParser(tr) 21 | if where == nil && !tr.Empty() { 22 | return nil, err 23 | } 24 | return &SyntaxTreeNode{ 25 | Name: "delete", 26 | Child: []*SyntaxTreeNode{&SyntaxTreeNode{ 27 | Name: "identical", 28 | Value: tName.Raw, 29 | ValueType: NAME, 30 | }, where}, 31 | }, nil 32 | } 33 | -------------------------------------------------------------------------------- /sql/syntax/drop.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func dropParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind != "keyword" || string(t.Raw) != "drop" { 10 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 11 | } 12 | t = tr.Read() 13 | if t.Kind != "keyword" || string(t.Raw) != "table" { 14 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 15 | } 16 | t = tr.Read() 17 | if t.Kind != "identical" { 18 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 19 | } 20 | return &SyntaxTreeNode{ 21 | Name: "drop", 22 | Child: nil, 23 | Value: t.Raw, 24 | ValueType: NAME, 25 | }, nil 26 | } 27 | -------------------------------------------------------------------------------- /sql/syntax/dropindex.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func dropIndexParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind != "keyword" || string(t.Raw) != "drop" { 10 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 11 | } 12 | t = tr.Read() 13 | if t.Kind != "keyword" || string(t.Raw) != "index" { 14 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 15 | } 16 | t = tr.Read() 17 | if t.Kind != "identical" { 18 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 19 | } 20 | return &SyntaxTreeNode{ 21 | Name: "dropindex", 22 | Child: nil, 23 | Value: t.Raw, 24 | ValueType: NAME, 25 | }, nil 26 | } 27 | -------------------------------------------------------------------------------- /sql/syntax/dump.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func dumpParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind != "keyword" || string(t.Raw) != "dump" { 10 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 11 | } 12 | t = tr.Read() 13 | if t.Kind != "identical" { 14 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 15 | } 16 | return &SyntaxTreeNode{ 17 | Name: "dump", 18 | Child: nil, 19 | Value: t.Raw, 20 | ValueType: NAME, 21 | }, nil 22 | } 23 | -------------------------------------------------------------------------------- /sql/syntax/filed.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | //Duplicated 8 | func expressionParser_duplicated(tr *TokenReader) (*SyntaxTreeNode, error) { 9 | fork := tr.Fork() 10 | t := fork.Read() 11 | if t.Kind == "identical" { 12 | tr.Next(1) 13 | return &SyntaxTreeNode{ 14 | Name: "identical", 15 | Value: t.Raw, 16 | ValueType: NAME, 17 | }, nil 18 | } 19 | if t.Kind == "unReference" { 20 | i := fork.Read() 21 | if fork.Read().Kind != "unReference" { 22 | return nil, errors.New("You have a SQL syntax error near:" + string(i.Raw)) 23 | } 24 | tr.Next(3) 25 | return &SyntaxTreeNode{ 26 | Name: "identical", 27 | Value: t.Raw, 28 | ValueType: NAME, 29 | }, nil 30 | } 31 | stn, err := valueParser(tr) 32 | if err != nil { 33 | return nil, err 34 | } 35 | value, valueType := stn.Value, stn.ValueType 36 | return &SyntaxTreeNode{ 37 | Name: "identical", 38 | Value: value, 39 | ValueType: valueType, 40 | }, nil 41 | } 42 | 43 | func filedParser(tr *TokenReader) (*SyntaxTreeNode, error) { 44 | fork := tr.Fork() 45 | t := fork.Read() 46 | if t.Kind == "identical" || (t.Kind == "wildcard" && string(t.Raw) == "*") { 47 | tr.Next(1) 48 | pre := fork.Read() 49 | if pre.Kind == "structs" && string(pre.Raw) == "." { 50 | tr.Next(1) 51 | snt, err := filedParser(tr) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return &SyntaxTreeNode{ 56 | Name: "spot", 57 | Value: nil, 58 | Child: []*SyntaxTreeNode{ 59 | &SyntaxTreeNode{ 60 | Name: "identical", 61 | Value: t.Raw, 62 | ValueType: NAME, 63 | }, 64 | snt, 65 | }, 66 | }, nil 67 | } 68 | return &SyntaxTreeNode{ 69 | Name: "identical", 70 | Value: t.Raw, 71 | ValueType: NAME, 72 | }, nil 73 | } 74 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 75 | } 76 | 77 | func filedsParser(tr *TokenReader) (*SyntaxTreeNode, error) { 78 | t := tr.Read() 79 | if t.Kind != "structs" || string(t.Raw) != "(" { 80 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 81 | } 82 | vs := make([]*SyntaxTreeNode, 0) 83 | for { 84 | v, err := filedParser(tr) 85 | if err == nil { 86 | vs = append(vs, v) 87 | } else { 88 | return nil, err 89 | } 90 | t := tr.Read() 91 | if t.Kind == "structs" && string(t.Raw) == "," { 92 | continue 93 | } else if t.Kind == "structs" && string(t.Raw) == ")" { 94 | break 95 | } else { 96 | return nil, errors.New("You have a syntax error near " + string(t.Raw)) 97 | } 98 | } 99 | return &SyntaxTreeNode{ 100 | Name: "fields", 101 | Child: vs, 102 | }, nil 103 | } 104 | -------------------------------------------------------------------------------- /sql/syntax/get.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | //For KV 8 | func getParser(tr *TokenReader) (*SyntaxTreeNode, error) { 9 | t := tr.Read() 10 | if t.Kind != "keyword" || string(t.Raw) != "get" { 11 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 12 | } 13 | t = tr.Read() 14 | if t.Kind != "identical" { 15 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 16 | } 17 | tableName := t.Raw 18 | k, err := valueParser(tr) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return &SyntaxTreeNode{ 23 | Name: "getkv", 24 | Value: tableName, 25 | ValueType: NAME, 26 | Child: []*SyntaxTreeNode{ 27 | k, 28 | }, 29 | }, nil 30 | } 31 | -------------------------------------------------------------------------------- /sql/syntax/insert.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func insertParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind != "keyword" || string(t.Raw) != "insert" { 10 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 11 | } 12 | t = tr.Read() 13 | if t.Kind != "keyword" || string(t.Raw) != "into" { 14 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 15 | } 16 | tName := tr.Read() 17 | if tName.Kind != "identical" { 18 | return nil, errors.New("You have a syntax error near: " + string(tName.Raw)) 19 | } 20 | fork := tr.Fork() 21 | t = fork.Read() 22 | var names *SyntaxTreeNode 23 | if t.Kind == "structs" && string(t.Raw) == "(" { 24 | var err error 25 | names, err = filedsParser(tr) 26 | if err != nil { 27 | return nil, err 28 | } 29 | } 30 | rows, err := valuesParser(tr) 31 | if err != nil { 32 | return nil, err 33 | } 34 | return &SyntaxTreeNode{ 35 | Name: "insert", 36 | Child: []*SyntaxTreeNode{ 37 | &SyntaxTreeNode{ 38 | Name: "identical", 39 | Value: tName.Raw, 40 | ValueType: NAME, 41 | }, 42 | names, 43 | rows, 44 | }, 45 | }, nil 46 | } 47 | 48 | func valuesParser(tr *TokenReader) (*SyntaxTreeNode, error) { 49 | t := tr.Read() 50 | if t.Kind != "keyword" || string(t.Raw) != "values" { 51 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 52 | } 53 | vs, err := rowsParser(tr) 54 | if err != nil { 55 | return nil, err 56 | } 57 | return vs, nil 58 | } 59 | 60 | func rowParser(tr *TokenReader) (*SyntaxTreeNode, error) { 61 | t := tr.Read() 62 | if t.Kind != "structs" || string(t.Raw) != "(" { 63 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 64 | } 65 | vs := make([]*SyntaxTreeNode, 0) 66 | for { 67 | v, err := valueParser(tr) 68 | if err == nil { 69 | vs = append(vs, v) 70 | } else { 71 | return nil, err 72 | } 73 | t := tr.Read() 74 | if t.Kind == "structs" && string(t.Raw) == "," { 75 | continue 76 | } else if t.Kind == "structs" && string(t.Raw) == ")" { 77 | break 78 | } else { 79 | return nil, errors.New("You have a syntax error near " + string(t.Raw)) 80 | } 81 | } 82 | return &SyntaxTreeNode{ 83 | Name: "row", 84 | Child: vs, 85 | }, nil 86 | } 87 | 88 | func rowsParser(tr *TokenReader) (*SyntaxTreeNode, error) { 89 | vs := make([]*SyntaxTreeNode, 0) 90 | v, err := rowParser(tr) 91 | if err != nil { 92 | return nil, err 93 | } 94 | vs = append(vs, v) 95 | for { 96 | fork := tr.Fork() 97 | t := fork.Read() 98 | if t.Kind != "structs" || string(t.Raw) != "," { 99 | break 100 | } 101 | tr.Next(1) 102 | v, err = rowParser(tr) 103 | if err != nil { 104 | return nil, err 105 | } 106 | vs = append(vs, v) 107 | } 108 | return &SyntaxTreeNode{ 109 | Name: "rows", 110 | Child: vs, 111 | }, nil 112 | } 113 | -------------------------------------------------------------------------------- /sql/syntax/insert_test.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "testing" 5 | 6 | "../lex" 7 | ) 8 | 9 | func Test_rowParser(t *testing.T) { 10 | ts, _ := lex.Parse(*lex.NewByteReader([]byte("(123.5, 'a')"))) 11 | stn, err := rowParser(&TokenReader{data: ts}) 12 | if err != nil { 13 | t.Error(err) 14 | } 15 | stn.Print(1) 16 | } 17 | -------------------------------------------------------------------------------- /sql/syntax/parser.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | /* 8 | createquery = create table identical ( columndefine ) 9 | columndefine = identical type | identical type , columndefine 10 | type = int | float 11 | query = selectquery | insertquery | updatequery | deletequery | createquery 12 | selectquery = select fileds [from relation] [where logical] 13 | logical = expression reloperation expression | expression relperation expression logoperation logical 14 | fileds = filed | filed, fields 15 | realation = expression | relation.expression 16 | filed = identical | identical.filed 17 | expression = identical | `identical` | value 18 | value = int | number 19 | */ 20 | 21 | const ( 22 | NULL = iota 23 | INT 24 | FLOAT 25 | NAME 26 | STRING 27 | ) 28 | 29 | type SyntaxTreeNode struct { 30 | Name string 31 | Child []*SyntaxTreeNode 32 | Value interface{} 33 | ValueType int 34 | } 35 | 36 | func (stn *SyntaxTreeNode) Print(tabs int) { 37 | if stn == nil { 38 | return 39 | } 40 | tab := "" 41 | for i := 0; i < tabs; i++ { 42 | tab += "\t" 43 | } 44 | if stn.Value != nil { 45 | fmt.Println(tab+stn.Name, ":", stn.Value) 46 | } else { 47 | fmt.Println(tab + stn.Name) 48 | } 49 | 50 | for _, c := range stn.Child { 51 | c.Print(tabs + 1) 52 | } 53 | } 54 | 55 | type parser func(*TokenReader) *SyntaxTreeNode 56 | -------------------------------------------------------------------------------- /sql/syntax/parser_test.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "testing" 5 | "../lex" 6 | ) 7 | 8 | func Test_filedParser(t *testing.T) { 9 | ts, _ := lex.Parse(*lex.NewByteReader([]byte("abc.abc.efd"))) 10 | stn, err := filedParser(&TokenReader{data: ts}) 11 | if err != nil { 12 | t.Error(err) 13 | } 14 | stn.Print(1) 15 | } -------------------------------------------------------------------------------- /sql/syntax/query.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func Parser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | fork := tr.Fork() 9 | t := fork.Read() 10 | if t.Kind == "keyword" && string(t.Raw) == "create" { 11 | fork2 := tr.Fork() 12 | stn, err := createtableParser(fork2) 13 | if err != nil { 14 | stn, err := createIndexParser(tr) 15 | if err != nil { 16 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 17 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 18 | } 19 | return nil, err 20 | } 21 | return stn, nil 22 | } 23 | tr.pos = fork2.pos 24 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 25 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 26 | } 27 | return stn, nil 28 | } 29 | if t.Kind == "keyword" && string(t.Raw) == "createkv" { 30 | stn, err := createKVParser(tr) 31 | if err != nil { 32 | return nil, err 33 | } 34 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 35 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 36 | } 37 | return stn, nil 38 | } 39 | if t.Kind == "keyword" && string(t.Raw) == "set" { 40 | stn, err := setKVParser(tr) 41 | if err != nil { 42 | return nil, err 43 | } 44 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 45 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 46 | } 47 | return stn, nil 48 | } 49 | if t.Kind == "keyword" && string(t.Raw) == "get" { 50 | stn, err := getParser(tr) 51 | if err != nil { 52 | return nil, err 53 | } 54 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 55 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 56 | } 57 | return stn, nil 58 | } 59 | if t.Kind == "keyword" && string(t.Raw) == "remove" { 60 | stn, err := removeParser(tr) 61 | if err != nil { 62 | return nil, err 63 | } 64 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 65 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 66 | } 67 | return stn, nil 68 | } 69 | if t.Kind == "keyword" && string(t.Raw) == "insert" { 70 | stn, err := insertParser(tr) 71 | if err != nil { 72 | return nil, err 73 | } 74 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 75 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 76 | } 77 | return stn, nil 78 | } 79 | if t.Kind == "keyword" && string(t.Raw) == "dump" { 80 | stn, err := dumpParser(tr) 81 | if err != nil { 82 | return nil, err 83 | } 84 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 85 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 86 | } 87 | return stn, nil 88 | } 89 | if t.Kind == "keyword" && string(t.Raw) == "select" { 90 | stn, err := selectParser(tr) 91 | if err != nil { 92 | return nil, err 93 | } 94 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 95 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 96 | } 97 | return stn, nil 98 | } 99 | if t.Kind == "keyword" && string(t.Raw) == "delete" { 100 | stn, err := deleteParser(tr) 101 | if err != nil { 102 | return nil, err 103 | } 104 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 105 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 106 | } 107 | return stn, nil 108 | } 109 | if t.Kind == "keyword" && string(t.Raw) == "drop" { 110 | fork2 := tr.Fork() 111 | stn, err := dropParser(fork2) 112 | if err != nil { 113 | stn, err := dropIndexParser(tr) 114 | if err != nil { 115 | return nil, err 116 | } 117 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 118 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 119 | } 120 | return stn, nil 121 | } 122 | tr.pos = fork2.pos 123 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 124 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 125 | } 126 | return stn, nil 127 | } 128 | if t.Kind == "keyword" && string(t.Raw) == "update" { 129 | stn, err := updateParser(tr) 130 | if err != nil { 131 | return nil, err 132 | } 133 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 134 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 135 | } 136 | return stn, nil 137 | } 138 | if t.Kind == "keyword" && string(t.Raw) == "show" { 139 | stn, err := showParser(tr) 140 | if err != nil { 141 | return nil, err 142 | } 143 | if t := tr.Read(); t.Kind != "" && string(t.Raw) != ";" { 144 | return nil, errors.New("Unexpect end:" + string(t.Raw)) 145 | } 146 | return stn, nil 147 | } 148 | return nil, errors.New("Unsupported syntax!") 149 | } 150 | -------------------------------------------------------------------------------- /sql/syntax/reader.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "../lex" 5 | ) 6 | 7 | type TokenReader struct { 8 | data []lex.Token 9 | pos int 10 | } 11 | 12 | func (r *TokenReader) Read() lex.Token { 13 | r.pos++ 14 | if r.pos > len(r.data) { 15 | return lex.Token{} 16 | } 17 | if r.data[r.pos-1].Kind != "split" { 18 | return r.data[r.pos-1] 19 | } else { 20 | return r.Read() 21 | } 22 | } 23 | 24 | func (r *TokenReader) DirectRead() lex.Token { 25 | r.pos++ 26 | if r.pos > len(r.data) { 27 | return lex.Token{} 28 | } 29 | return r.data[r.pos-1] 30 | } 31 | 32 | func (r *TokenReader) Empty() bool { 33 | return r.pos >= len(r.data)-1 34 | } 35 | 36 | func (r *TokenReader) Fork() *TokenReader { 37 | return &TokenReader{ 38 | data: r.data, 39 | pos: r.pos, 40 | } 41 | } 42 | 43 | func (r *TokenReader) Next(n int) { 44 | for i := 0; i < n; i++ { 45 | r.Read() 46 | } 47 | } 48 | 49 | func NewTokenReader(data []lex.Token) *TokenReader { 50 | return &TokenReader{ 51 | data: data, 52 | pos: 0, 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /sql/syntax/refer.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import "errors" 4 | 5 | func referParser(tr *TokenReader) (*SyntaxTreeNode, error) { 6 | t := tr.Read() 7 | if t.Kind != "unreference" { 8 | return nil, 9 | errors.New("You have a syntax error near:" + string(t.Raw)) 10 | } 11 | raws := []byte{} 12 | for t = tr.Read(); t.Kind != "unrefrence" && !tr.Empty(); { 13 | raws = append(raws, t.Raw...) 14 | } 15 | if t.Kind != "unreference" { 16 | return nil, 17 | errors.New("You have a syntax error near:" + string(t.Raw)) 18 | } 19 | return &SyntaxTreeNode{ 20 | Name: "indentical", 21 | Value: raws, 22 | ValueType: NAME, 23 | }, nil 24 | } 25 | -------------------------------------------------------------------------------- /sql/syntax/remove.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | //For KV 8 | func removeParser(tr *TokenReader) (*SyntaxTreeNode, error) { 9 | t := tr.Read() 10 | if t.Kind != "keyword" || string(t.Raw) != "remove" { 11 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 12 | } 13 | t = tr.Read() 14 | if t.Kind != "identical" { 15 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 16 | } 17 | tableName := t.Raw 18 | k, err := valueParser(tr) 19 | if err != nil { 20 | return nil, err 21 | } 22 | return &SyntaxTreeNode{ 23 | Name: "removekv", 24 | Value: tableName, 25 | ValueType: NAME, 26 | Child: []*SyntaxTreeNode{ 27 | k, 28 | }, 29 | }, nil 30 | } 31 | -------------------------------------------------------------------------------- /sql/syntax/select.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | //Unensurable 8 | func selectParser(tr *TokenReader) (*SyntaxTreeNode, error) { 9 | t := tr.Read() 10 | if t.Kind != "keyword" || string(t.Raw) != "select" { 11 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 12 | } 13 | projects, err := selectFiledsParser(tr) 14 | if err != nil { 15 | return nil, err 16 | } 17 | t = tr.Read() 18 | if t.Kind != "keyword" || string(t.Raw) != "from" { 19 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 20 | } 21 | froms, err := selectFiledsParser(tr) 22 | if err != nil { 23 | return nil, err 24 | } 25 | where, err := whereParser(tr) 26 | if where == nil && !tr.Empty() { 27 | return nil, err 28 | } 29 | return &SyntaxTreeNode{ 30 | Name: "select", 31 | Child: []*SyntaxTreeNode{projects, froms, where}, 32 | }, nil 33 | } 34 | 35 | //Unensurable 36 | func selectFiledsParser(tr *TokenReader) (*SyntaxTreeNode, error) { 37 | vs := make([]*SyntaxTreeNode, 0) 38 | for { 39 | v, err := filedParser(tr) 40 | if err == nil { 41 | vs = append(vs, v) 42 | } else { 43 | return nil, err 44 | } 45 | fork := tr.Fork() 46 | t := fork.Read() 47 | if t.Kind == "structs" && string(t.Raw) == "," { 48 | tr.Next(1) 49 | continue 50 | } else { 51 | break 52 | } 53 | } 54 | return &SyntaxTreeNode{ 55 | Name: "fields", 56 | Child: vs, 57 | }, nil 58 | } 59 | -------------------------------------------------------------------------------- /sql/syntax/set.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | //For KV 8 | func setKVParser(tr *TokenReader) (*SyntaxTreeNode, error) { 9 | t := tr.Read() 10 | if t.Kind != "keyword" || string(t.Raw) != "set" { 11 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 12 | } 13 | t = tr.Read() 14 | if t.Kind != "identical" { 15 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 16 | } 17 | tableName := t.Raw 18 | k, err := valueParser(tr) 19 | if err != nil { 20 | return nil, err 21 | } 22 | v, err := valueParser(tr) 23 | if err != nil { 24 | return nil, err 25 | } 26 | return &SyntaxTreeNode{ 27 | Name: "setkv", 28 | Value: tableName, 29 | ValueType: NAME, 30 | Child: []*SyntaxTreeNode{ 31 | k, v, 32 | }, 33 | }, nil 34 | } 35 | -------------------------------------------------------------------------------- /sql/syntax/show.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func showParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | t := tr.Read() 9 | if t.Kind != "keyword" || string(t.Raw) != "show" { 10 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 11 | } 12 | t = tr.Read() 13 | if t.Kind != "keyword" || string(t.Raw) != "table" { 14 | if t.Kind == "keyword" && string(t.Raw) == "tables" { 15 | return &SyntaxTreeNode{ 16 | Name: "showtables", 17 | }, nil 18 | } 19 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 20 | } 21 | t = tr.Read() 22 | if t.Kind != "identical" { 23 | return nil, errors.New("You have a syntax error near : " + string(t.Raw)) 24 | } 25 | tableName := t.Raw 26 | return &SyntaxTreeNode{ 27 | Name: "showtable", 28 | Value: tableName, 29 | ValueType: NAME, 30 | }, nil 31 | } 32 | -------------------------------------------------------------------------------- /sql/syntax/string.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import "errors" 4 | 5 | func stringParser(tr *TokenReader) (*SyntaxTreeNode, error) { 6 | 7 | t := tr.Read() /* 8 | if t.Kind != "reference" { 9 | return nil, 10 | errors.New("You have a syntax error near:" + string(t.Raw)) 11 | } 12 | raws := []byte{} 13 | for t = tr.DirectRead(); t.Kind != "reference" && !tr.Empty(); t = tr.DirectRead() { 14 | raws = append(raws, t.Raw...) 15 | } 16 | if t.Kind != "reference" { 17 | return nil, 18 | errors.New("You have a syntax error near:" + string(t.Raw)) 19 | }*/ 20 | if t.Kind != "string" { 21 | panic(1) 22 | return nil, 23 | errors.New("You have a syntax error near:" + string(t.Raw)) 24 | } 25 | return &SyntaxTreeNode{ 26 | Name: "string", 27 | Value: t.Raw, 28 | ValueType: STRING, 29 | }, nil 30 | } 31 | -------------------------------------------------------------------------------- /sql/syntax/update.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | //Unensurable 8 | func updateParser(tr *TokenReader) (*SyntaxTreeNode, error) { 9 | t := tr.Read() 10 | if t.Kind != "keyword" || string(t.Raw) != "update" { 11 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 12 | } 13 | t = tr.Read() 14 | if t.Kind != "identical" { 15 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 16 | } 17 | tName := t.Raw 18 | t = tr.Read() 19 | if t.Kind != "keyword" || string(t.Raw) != "set" { 20 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 21 | } 22 | sets, err := setsParser(tr) 23 | if err != nil { 24 | return nil, err 25 | } 26 | where, err := whereParser(tr) 27 | if where == nil && !tr.Empty() { 28 | return nil, err 29 | } 30 | return &SyntaxTreeNode{ 31 | Name: "update", 32 | Value: tName, 33 | ValueType: NAME, 34 | Child: []*SyntaxTreeNode{sets, where}, 35 | }, nil 36 | } 37 | 38 | //Ensuable 39 | func setParser(tr *TokenReader) (*SyntaxTreeNode, error) { 40 | fork := tr.Fork() 41 | t := fork.Read() 42 | if t.Kind != "identical" { 43 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 44 | } 45 | i := t.Raw 46 | t = fork.Read() 47 | if t.Kind != "relations" || string(t.Raw) != "=" { 48 | return nil, errors.New("You have a syntax error near: " + string(t.Raw)) 49 | } 50 | value, err := valueParser(fork) 51 | if err != nil { 52 | return nil, err 53 | } 54 | tr.pos = fork.pos 55 | return &SyntaxTreeNode{ 56 | Name: "set", 57 | Value: i, 58 | ValueType: NAME, 59 | Child: []*SyntaxTreeNode{ 60 | value, 61 | }, 62 | }, nil 63 | } 64 | 65 | //Ensuable 66 | func setsParser(tr *TokenReader) (*SyntaxTreeNode, error) { 67 | sets := make([]*SyntaxTreeNode, 0) 68 | fork := tr.Fork() 69 | for { 70 | set, err := setParser(fork) 71 | if err != nil { 72 | return nil, err 73 | } 74 | sets = append(sets, set) 75 | fork2 := fork.Fork() 76 | t := fork2.Read() 77 | if t.Kind == "structs" && string(t.Raw) == "," { 78 | fork.pos = fork2.pos 79 | continue 80 | } else { 81 | tr.pos = fork.pos 82 | return &SyntaxTreeNode{ 83 | Name: "sets", 84 | Child: sets, 85 | }, nil 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /sql/syntax/value.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "errors" 5 | ) 6 | 7 | func valueParser(tr *TokenReader) (*SyntaxTreeNode, error) { 8 | fork := tr.Fork() 9 | t := fork.Read() 10 | if t.Kind == "intval" { 11 | tr.Next(1) 12 | return &SyntaxTreeNode{ 13 | Name: "value", 14 | Value: calculateInt(t.Raw), 15 | ValueType: INT, 16 | }, nil 17 | } 18 | if t.Kind == "floatval" { 19 | tr.Next(1) 20 | return &SyntaxTreeNode{ 21 | Name: "value", 22 | Value: calculateFloat(t.Raw), 23 | ValueType: FLOAT, 24 | }, nil 25 | } 26 | if t.Kind == "string" { 27 | str, err := stringParser(tr) 28 | if err != nil { 29 | return nil, err 30 | } 31 | return str, nil 32 | } 33 | return nil, errors.New("You have a syntax error near:" + string(t.Raw)) 34 | } 35 | -------------------------------------------------------------------------------- /sql/syntax/value_test.go: -------------------------------------------------------------------------------- 1 | package syntax 2 | 3 | import ( 4 | "testing" 5 | 6 | "../lex" 7 | ) 8 | 9 | func Test_valueParser(t *testing.T) { 10 | ts, _ := lex.Parse(*lex.NewByteReader([]byte("123.5"))) 11 | stn, err := valueParser(&TokenReader{data: ts}) 12 | if err != nil { 13 | t.Error(err) 14 | } 15 | stn.Print(1) 16 | } 17 | -------------------------------------------------------------------------------- /table/create.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "errors" 5 | 6 | "../index" 7 | ) 8 | 9 | var TableList []*Table 10 | 11 | func CreateTable(tableName string) *Table { 12 | ret := &Table{ 13 | Name: tableName, 14 | Primary: -1, 15 | } 16 | ret.FirstPage = ret.NewPage() 17 | ret.LastPage = ret.FirstPage 18 | TableList = append(TableList, ret) 19 | return ret 20 | } 21 | 22 | func (t *Table) AddFiled(fieldName string, fixedSize bool, size int, ttype int, keyType int) error { 23 | if t.Primary != -1 && keyType == index.PRIMARY { 24 | return errors.New("Table has a primary key already") 25 | } 26 | if keyType == index.PRIMARY { 27 | t.Primary = len(t.Fields) 28 | } 29 | ind := index.CreateIndex(keyType, "db", t.Name, fieldName+"_key") 30 | filed := Field{ 31 | Name: fieldName, 32 | FixedSize: fixedSize, 33 | Size: size, 34 | Type: ttype, 35 | Index: ind, 36 | } 37 | t.Fields = append(t.Fields, filed) 38 | return nil 39 | } 40 | -------------------------------------------------------------------------------- /table/delete.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "log" 5 | 6 | "../exe" 7 | "../index" 8 | ) 9 | 10 | func (t *Table) Delete(ids *exe.BitSet) { 11 | reader := t.FirstPage.NewReader() 12 | for i := 0; i < ids.Len(); i++ { 13 | pos := reader.currentPtr 14 | page := reader.currentPage 15 | 16 | if ids.Get(i) { 17 | reader.DeleteRecordIndex() 18 | var skip uint 19 | if page == reader.currentPage { 20 | skip = reader.currentPtr - pos - 8 21 | page.Write(pos, uint2bytes(skip)) 22 | log.Println("in-page delete") 23 | } else { 24 | skip = reader.currentPtr - 72 25 | reader.currentPage.Write(64, uint2bytes(skip)) 26 | log.Println("out-page delete") 27 | } 28 | 29 | } else { 30 | reader.NextRecord() 31 | } 32 | } 33 | } 34 | 35 | func (p *Page) DeleteFromOffset(offset uint) { 36 | reader := p.NewReader() 37 | reader.currentPtr = offset 38 | reader.NextRecord() 39 | end := reader.currentPtr 40 | skip := end - offset 41 | p.Write(offset, uint2bytes(skip)) 42 | } 43 | 44 | //Delete current record Index and goto next record 45 | func (p *Reader) DeleteRecordIndex() { 46 | p.CheckPage() 47 | if p.currentPage == nil { 48 | log.Println("attempt to delete from nil page") 49 | return 50 | } 51 | v, _ := p.currentPage.Read(p.currentPtr, 8) 52 | p.currentPtr += 8 53 | skip := bytes2uint(v) 54 | if skip != 0 { 55 | p.currentPtr += skip 56 | p.NextRecord() 57 | return 58 | } 59 | table := p.currentPage.GetTable() 60 | for _, f := range table.Fields { 61 | if f.FixedSize { 62 | v, _ := p.currentPage.Read(p.currentPtr, uint(f.Size)) 63 | if f.Index != nil { 64 | f.Index.I.Delete(index.BKDRHash(v)) 65 | } 66 | p.currentPtr += uint(f.Size) 67 | } else { 68 | data, _ := p.currentPage.Read(p.currentPtr, 4) 69 | size := bytes2uint32(data) 70 | p.currentPtr += 4 71 | v, _ := p.currentPage.Read(p.currentPtr, uint(size)) 72 | if f.Index != nil { 73 | f.Index.I.Delete(index.BKDRHash(v)) 74 | } 75 | p.currentPtr += uint(size) 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /table/drop.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | func (t *Table) Drop() { 4 | for _, v := range t.Fields { 5 | if v.Index != nil { 6 | v.Index.Delete() 7 | } 8 | } 9 | for p := t.FirstPage; p != nil; { 10 | pNext := p.NextPage() 11 | p.Delete() 12 | p = pNext 13 | } 14 | for k, v := range TableList { 15 | if v == t { 16 | TableList = append(TableList[0:k], TableList[k+1:]...) 17 | return 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /table/insert.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "strconv" 5 | "time" 6 | 7 | "../common" 8 | "../index" 9 | ) 10 | 11 | //Dunplicated 12 | func (t *Table) Insert_dunplicated(columnNames []string, data [][][]byte) { 13 | fields := t.Fields 14 | for _, row := range data { 15 | t.LastPage.Append(uint2bytes(0)) //Skip 16 | columnNamesP := 0 17 | for i := 0; i < len(fields); i++ { 18 | if columnNames == nil || len(columnNames) == 0 || 19 | columnNamesP < len(columnNames) && columnNames[columnNamesP] == fields[i].Name { 20 | t.LastPage.AppendField(&fields[i], row[columnNamesP]) 21 | columnNamesP++ 22 | if len(columnNames) != 0 && columnNames != nil && columnNamesP >= len(columnNames) { 23 | break 24 | } 25 | } else { 26 | t.LastPage.AppendField(&fields[i], nil) 27 | } 28 | } 29 | 30 | } 31 | } 32 | 33 | //Map Table -> Data 34 | func (t *Table) Insert(fieldMap map[int]int, data [][][]byte) error { 35 | fields := t.Fields 36 | for _, row := range data { 37 | //check free space 38 | freeS := t.LastPage.Size - t.LastPage.GetFreePos() 39 | rowProvided := len(fieldMap) 40 | autoFill := (len(t.Fields) - rowProvided) * 16 41 | needSpace := autoFill + 8 + rowProvided*8 42 | for _, v := range row { 43 | needSpace += len(v) 44 | } 45 | if freeS < uint(needSpace) { 46 | t.LastPage.AppendPage() 47 | } 48 | 49 | pos := t.LastPage.GetFreePos() 50 | var indexLog = make(map[index.Indexer]uint32) 51 | t.LastPage.Append(uint2bytes(0)) //Skip 52 | for i := 0; i < len(fields); i++ { 53 | if k, ok := fieldMap[i]; ok { 54 | if fields[i].Index != nil { 55 | var p uint 56 | p = uint(t.LastPage.RawPtr) << 24 57 | p = p | pos 58 | start := time.Now().UnixNano() 59 | key := index.BKDRHash(row[k]) 60 | err := fields[i].Index.I.Insert(key, uintptr(p)) 61 | if err != nil { 62 | for k, v := range indexLog { 63 | k.Delete(v) 64 | } 65 | t.LastPage.SetFreePos(pos) 66 | return err 67 | } 68 | common.Print2("Insert in Index within " + strconv.Itoa(int(time.Now().UnixNano()-start)) + " ns.") 69 | indexLog[fields[i].Index.I] = key 70 | } 71 | t.LastPage.AppendField(&fields[i], row[k]) 72 | } else { 73 | t.LastPage.AppendField(&fields[i], nil) 74 | } 75 | } 76 | 77 | } 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /table/kvtable.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "errors" 5 | 6 | "../exe" 7 | "../index" 8 | "../memory" 9 | ) 10 | 11 | const ( 12 | KV_INT = iota 13 | KV_FLOAT 14 | KV_STRING 15 | ) 16 | 17 | func CreateKVTable(tableName string, keyType int, valueType int) *Table { 18 | ret := CreateTable(tableName) 19 | switch keyType { 20 | case KV_INT: 21 | ret.AddFiled("key", true, 8, exe.INT, index.PRIMARY) 22 | case KV_FLOAT: 23 | ret.AddFiled("key", true, 8, exe.FLOAT, index.PRIMARY) 24 | case KV_STRING: 25 | ret.AddFiled("key", false, 0, exe.STRING, index.PRIMARY) 26 | } 27 | switch valueType { 28 | case KV_INT: 29 | ret.AddFiled("value", true, 8, exe.INT, -1) 30 | case KV_FLOAT: 31 | ret.AddFiled("value", true, 8, exe.FLOAT, -1) 32 | case KV_STRING: 33 | ret.AddFiled("value", false, 0, exe.STRING, -1) 34 | } 35 | return ret 36 | } 37 | 38 | func (t *Table) KVGetValue(key []byte) ([]byte, error) { 39 | if t.Primary < 0 { 40 | return nil, errors.New("this table cannot be used as a kv table") 41 | } 42 | ind := t.Fields[t.Primary].Index 43 | if ind == nil { 44 | return nil, errors.New(("this table cannot be used as a kv table")) 45 | } 46 | cur := ind.I.Select(index.BKDRHash(key)) 47 | if cur == nil { 48 | return nil, errors.New("not found key") 49 | } 50 | ptr, offset := cur.Read() 51 | if ptr == 0 { 52 | return nil, errors.New("not found key") 53 | } 54 | p := &Page{ 55 | DataBlock: *memory.DataBlockTable[ptr], 56 | } 57 | reader := p.NewReader() 58 | 59 | reader.currentPtr = offset 60 | rel := reader.PeekRecord() 61 | return rel.Rows[0][1].Raw, nil 62 | } 63 | 64 | func (t *Table) KVSetValue(key []byte, value []byte) error { 65 | if t.Primary < 0 { 66 | return errors.New("this table cannot be used as a kv table") 67 | } 68 | ind := t.Fields[t.Primary].Index 69 | if ind == nil { 70 | return errors.New(("this table cannot be used as a kv table")) 71 | } 72 | cur := ind.I.Select(index.BKDRHash(key)) 73 | m := make(map[int]int) 74 | m[0] = 0 75 | m[1] = 1 76 | data := make([][][]byte, 1) 77 | data[0] = append([][]byte{}, key) 78 | data[0] = append(data[0], value) 79 | if cur == nil { 80 | err := t.Insert(m, data) 81 | if err != nil { 82 | return err 83 | } 84 | return nil 85 | } 86 | tab, offset := cur.Read() 87 | if tab == 0 { 88 | err := t.Insert(m, data) 89 | if err != nil { 90 | return err 91 | } 92 | return nil 93 | } 94 | cur.Delete() 95 | page := &Page{ 96 | DataBlock: *memory.DataBlockTable[tab], 97 | } 98 | page.DeleteFromOffset(offset) 99 | t.Insert(m, data) 100 | return nil 101 | } 102 | 103 | func (t *Table) KVRemove(key []byte) error { 104 | if t.Primary < 0 { 105 | return errors.New("this table cannot be used as a kv table") 106 | } 107 | ind := t.Fields[t.Primary].Index 108 | if ind == nil { 109 | return errors.New(("this table cannot be used as a kv table")) 110 | } 111 | cur := ind.I.Select(index.BKDRHash(key)) 112 | if cur == nil { 113 | return errors.New("the key has already been deleted") 114 | } 115 | tab, offset := cur.Read() 116 | if tab == 0 { 117 | return errors.New("there's a internal error") 118 | } 119 | cur.Delete() 120 | page := &Page{ 121 | DataBlock: *memory.DataBlockTable[tab], 122 | } 123 | page.DeleteFromOffset(offset) 124 | return nil 125 | } 126 | -------------------------------------------------------------------------------- /table/page.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "unsafe" 5 | 6 | "../config" 7 | "../exe" 8 | "../index" 9 | "../memory" 10 | ) 11 | 12 | var ( 13 | NORMAL_PAGE_SIZE = 1024 * 1024 //Test 14 | ) 15 | 16 | const ( 17 | PREV_OFFSET = 8 18 | NEXT_OFFSET = 16 19 | FREE_P_OFFSET = 24 20 | END_OF_PAGE = 32 21 | ) 22 | 23 | func init() { 24 | m := config.LoadConfig("page") 25 | if m == nil { 26 | return 27 | } 28 | size, ok := m["page_size"].(float64) 29 | if !ok { 30 | return 31 | } 32 | NORMAL_PAGE_SIZE = int(size) 33 | } 34 | 35 | type Page struct { 36 | memory.DataBlock 37 | } 38 | 39 | // This struct is only to refrence to programer 40 | type page struct { 41 | table uintptr 42 | prev uintptr //DataBlock RawPtr 43 | next uintptr //DataBlock RawPtr 44 | fp uint 45 | } 46 | 47 | func (p *Page) GetTable() *Table { 48 | ptr, _ := p.Read(0, 8) 49 | return (*Table)(unsafe.Pointer(uintptr(bytes2uint(ptr)))) 50 | } 51 | 52 | func (t *Table) NewPage() *Page { 53 | db, _ := memory.CreateImage(NORMAL_PAGE_SIZE) 54 | db.Write(0, uint2bytes(uint(uintptr(unsafe.Pointer(t))))) 55 | db.Write(PREV_OFFSET, uint2bytes(0)) 56 | db.Write(NEXT_OFFSET, uint2bytes(0)) 57 | // db.Write(END_OF_PAGE, uint2bytes(64)) //BUG 58 | db.Write(FREE_P_OFFSET, uint2bytes(64)) 59 | return &Page{ 60 | DataBlock: *db, 61 | } 62 | } 63 | 64 | func (p *Page) NextPage() *Page { 65 | ptr, _ := p.Read(NEXT_OFFSET, 8) 66 | if bytes2uint(ptr) == 0 { 67 | return nil 68 | } 69 | return &Page{ 70 | DataBlock: *(memory.DataBlockTable[uintptr(bytes2uint(ptr))]), 71 | } 72 | } 73 | 74 | func (p *Page) PrevPage() *Page { 75 | ptr, _ := p.Read(PREV_OFFSET, 8) 76 | if bytes2uint(ptr) == 0 { 77 | return nil 78 | } 79 | return &Page{ 80 | DataBlock: *(memory.DataBlockTable[uintptr(bytes2uint(ptr))]), 81 | } 82 | } 83 | 84 | func (p *Page) AppendPage() { 85 | t := p.GetTable() 86 | pNew := t.NewPage() 87 | p.Write(NEXT_OFFSET, uint2bytes(uint(uintptr(pNew.RawPtr)))) 88 | pNew.Write(PREV_OFFSET, uint2bytes(uint(uintptr(p.RawPtr)))) 89 | if t.LastPage == p { 90 | t.LastPage = pNew 91 | } 92 | } 93 | 94 | func (p *Page) GetFreePos() uint { 95 | data, _ := p.Read(FREE_P_OFFSET, 8) 96 | return bytes2uint(data) 97 | } 98 | 99 | //func (p *Page) GetEOP() uint { 100 | // data, _ := p.Read(END_OF_PAGE, 8) 101 | // return bytes2uint(data) 102 | //} 103 | 104 | func (p *Page) ForwardFreePos(i uint) { 105 | fp := p.GetFreePos() 106 | fp += i 107 | p.Write(FREE_P_OFFSET, uint2bytes(fp)) 108 | } 109 | 110 | func (p *Page) BackFreePos(i uint) { 111 | fp := p.GetFreePos() 112 | fp -= i 113 | p.Write(FREE_P_OFFSET, uint2bytes(fp)) 114 | } 115 | 116 | func (p *Page) SetFreePos(i uint) { 117 | p.Write(FREE_P_OFFSET, uint2bytes(i)) 118 | } 119 | 120 | func (p *Page) AppendField(f *Field, data []byte) { 121 | if data == nil || len(data) == 0 { 122 | switch f.Type { 123 | case exe.INT, exe.FLOAT, exe.OBJECT, exe.ARRAY: 124 | data = make([]byte, 8) 125 | case exe.STRING: 126 | data = make([]byte, 0) 127 | } 128 | } 129 | if !f.FixedSize { 130 | p.Append(uint322bytes(uint32(len(data)))) 131 | } 132 | if f.Index != nil { 133 | ptr := uint(p.RawPtr) 134 | ptr <<= 24 135 | fp := p.GetFreePos() 136 | ptr |= fp 137 | f.Index.I.Insert(index.BKDRHash(data), uintptr(ptr)) 138 | } 139 | p.Append(data) 140 | } 141 | 142 | func (p *Page) Append(data []byte) { 143 | fp := p.GetFreePos() 144 | p.Write(fp, data) 145 | fp += uint(len(data)) 146 | p.Write(FREE_P_OFFSET, uint2bytes(fp)) 147 | p.Write(END_OF_PAGE, uint2bytes(fp)) 148 | } 149 | -------------------------------------------------------------------------------- /table/pageRecovery.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "unsafe" 5 | 6 | "../memory" 7 | ) 8 | 9 | // Recovery page list and return the last page 10 | func (p *Page) Recovery(t *Table, prev *Page) *Page { 11 | p.Write(0, uint2bytes(uint(uintptr(unsafe.Pointer(t))))) 12 | if prev != nil { 13 | p.Write(PREV_OFFSET, uint2bytes(uint(prev.RawPtr))) 14 | } else { 15 | p.Write(PREV_OFFSET, uint2bytes(uint(0))) 16 | } 17 | 18 | ptr, _ := p.Read(NEXT_OFFSET, 8) 19 | db := memory.RecoveryTable[uintptr(bytes2uint(ptr))] 20 | if db != nil { 21 | pNext := &Page{ 22 | DataBlock: *db, 23 | } 24 | p.Write(NEXT_OFFSET, uint2bytes(uint(pNext.RawPtr))) 25 | return pNext.Recovery(t, p) 26 | } 27 | return p 28 | } 29 | -------------------------------------------------------------------------------- /table/reader.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "../exe" 5 | "../index" 6 | ) 7 | 8 | var RECORD_MAX_LENGTH = 4096 9 | 10 | type Reader struct { 11 | currentPtr uint 12 | currentPage *Page 13 | } 14 | 15 | func (p *Page) NewReader() *Reader { 16 | return &Reader{ 17 | currentPtr: 64, 18 | currentPage: p, 19 | } 20 | } 21 | 22 | func (p *Reader) CheckPage() { 23 | if p.currentPtr >= p.currentPage.GetFreePos() && p.currentPage.NextPage() != nil && p.currentPage.NextPage() != p.currentPage { 24 | p.currentPage = p.currentPage.NextPage() 25 | p.currentPtr = 64 26 | } 27 | } 28 | 29 | func (p *Reader) PeekRecord() *exe.Relation { 30 | // if p.currentPtr == p.currentPage.GetEOP() { 31 | // p.currentPage = p.currentPage.NextPage() 32 | // p.currentPtr = 64 33 | // } 34 | p.CheckPage() 35 | v, _ := p.currentPage.Read(p.currentPtr, 8) 36 | p.currentPtr += 8 37 | skip := bytes2uint(v) 38 | if skip != 0 { 39 | p.currentPtr += skip 40 | return p.PeekRecord() 41 | } 42 | ret := exe.NewRelation() 43 | table := p.currentPage.GetTable() 44 | row := make(exe.Row, 0) 45 | for _, f := range table.Fields { 46 | if f.FixedSize { 47 | v, _ := p.currentPage.Read(p.currentPtr, uint(f.Size)) 48 | row = append(row, exe.NewValue(f.Type, v)) 49 | p.currentPtr += uint(f.Size) 50 | } else { 51 | data, _ := p.currentPage.Read(p.currentPtr, 4) 52 | size := bytes2uint32(data) 53 | p.currentPtr += 4 54 | v, _ := p.currentPage.Read(p.currentPtr, uint(size)) 55 | row = append(row, exe.NewValue(f.Type, v)) 56 | p.currentPtr += uint(size) 57 | } 58 | } 59 | ret.AddRow(row) 60 | return ret 61 | } 62 | 63 | func (p *Reader) NextRecord() { 64 | p.CheckPage() 65 | v, _ := p.currentPage.Read(p.currentPtr, 8) 66 | p.currentPtr += 8 67 | skip := bytes2uint(v) 68 | if skip != 0 { 69 | p.currentPtr += skip 70 | p.NextRecord() 71 | return 72 | } 73 | table := p.currentPage.GetTable() 74 | for _, f := range table.Fields { 75 | if f.FixedSize { 76 | p.currentPtr += uint(f.Size) 77 | } else { 78 | data, _ := p.currentPage.Read(p.currentPtr, 4) 79 | size := bytes2uint32(data) 80 | p.currentPtr += 4 81 | p.currentPtr += uint(size) 82 | } 83 | } 84 | } 85 | 86 | func (p *Reader) DumpPage() *exe.Relation { 87 | oldP := p.currentPtr 88 | p.currentPtr = 64 89 | ret := exe.NewRelation() 90 | tab := p.currentPage.GetTable() 91 | columns := make([]string, 0) 92 | for i := 0; i < len(tab.Fields); i++ { 93 | columns = append(columns, tab.Fields[i].Name) 94 | } 95 | ret.SetColumnNames(columns) 96 | 97 | // v, _ := p.currentPage.Read(0, 512) 98 | // fmt.Println(v) 99 | for p.currentPtr < p.currentPage.GetFreePos() { 100 | v, _ := p.currentPage.Read(p.currentPtr, 8) 101 | p.currentPtr += 8 102 | skip := bytes2uint(v) 103 | // fmt.Println(skip) 104 | if skip != 0 { 105 | p.currentPtr += skip 106 | continue 107 | } 108 | table := p.currentPage.GetTable() 109 | row := make(exe.Row, 0) 110 | for _, f := range table.Fields { 111 | if f.FixedSize { 112 | v, _ := p.currentPage.Read(p.currentPtr, uint(f.Size)) 113 | // fmt.Println(v) 114 | row = append(row, exe.NewValue(f.Type, v)) 115 | p.currentPtr += uint(f.Size) 116 | } else { 117 | data, _ := p.currentPage.Read(p.currentPtr, 4) 118 | size := bytes2uint32(data) 119 | // fmt.Println(size) 120 | p.currentPtr += 4 121 | v, _ := p.currentPage.Read(p.currentPtr, uint(size)) 122 | // fmt.Println(v) 123 | row = append(row, exe.NewValue(f.Type, v)) 124 | p.currentPtr += uint(size) 125 | } 126 | } 127 | ret.AddRow(row) 128 | } 129 | p.currentPtr = oldP 130 | return ret 131 | } 132 | 133 | func (p *Reader) DumpTable() *exe.Relation { 134 | oldPage := p.currentPage 135 | oldPtr := p.currentPtr 136 | ret := exe.NewRelation() 137 | for p.currentPage != nil { 138 | p.currentPtr = 64 139 | r := p.DumpPage() 140 | ret.Rows = append(ret.Rows, r.Rows...) 141 | ret.SetColumnNames(r.ColumnNames) 142 | p.currentPage = p.currentPage.NextPage() 143 | } 144 | p.currentPage = oldPage 145 | p.currentPtr = oldPtr 146 | return ret 147 | } 148 | 149 | func (p *Reader) LoadIndex(i *index.Index, kField int) error { 150 | oldPage := p.currentPage 151 | oldPtr := p.currentPtr 152 | for p.currentPage != nil { 153 | p.currentPtr = 64 154 | for p.currentPtr < p.currentPage.GetFreePos() { 155 | pos := p.currentPage.RawPtr 156 | v, _ := p.currentPage.Read(p.currentPtr, 8) 157 | p.currentPtr += 8 158 | skip := bytes2uint(v) 159 | if skip != 0 { 160 | p.currentPtr += skip 161 | continue 162 | } 163 | ptr := uint(pos) 164 | ptr <<= 24 165 | ptr |= p.currentPtr 166 | table := p.currentPage.GetTable() 167 | for k, f := range table.Fields { 168 | if f.FixedSize { 169 | if kField == k { 170 | v, _ := p.currentPage.Read(p.currentPtr, uint(f.Size)) 171 | err := i.I.Insert(index.BKDRHash(v), uintptr(ptr)) 172 | if err != nil { 173 | return err 174 | } 175 | } 176 | p.currentPtr += uint(f.Size) 177 | } else { 178 | data, _ := p.currentPage.Read(p.currentPtr, 4) 179 | size := bytes2uint32(data) 180 | p.currentPtr += 4 181 | if kField == k { 182 | v, _ := p.currentPage.Read(p.currentPtr, uint(size)) 183 | err := i.I.Insert(index.BKDRHash(v), uintptr(ptr)) 184 | if err != nil { 185 | return err 186 | } 187 | } 188 | p.currentPtr += uint(size) 189 | } 190 | } 191 | } 192 | p.currentPage = p.currentPage.NextPage() 193 | } 194 | p.currentPage = oldPage 195 | p.currentPtr = oldPtr 196 | return nil 197 | } 198 | -------------------------------------------------------------------------------- /table/recovery.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "encoding/json" 5 | "io/ioutil" 6 | "strconv" 7 | "unsafe" 8 | 9 | "../common" 10 | "../index" 11 | "../log" 12 | "../memory" 13 | ) 14 | 15 | type SavedField struct { 16 | Name string 17 | FixedSize bool 18 | Index uint 19 | Size int 20 | Type int 21 | } 22 | 23 | type SavedTable struct { 24 | Name string 25 | Fields []SavedField 26 | FirstPage uint 27 | LastPage uint 28 | Primary int 29 | } 30 | 31 | func syncTablesToFile() { 32 | svts := make([]SavedTable, 0) 33 | for _, v := range TableList { 34 | svt := SavedTable{ 35 | Name: v.Name, 36 | FirstPage: uint(v.FirstPage.RawPtr), 37 | LastPage: uint(v.LastPage.RawPtr), 38 | Primary: v.Primary, 39 | } 40 | for _, f := range v.Fields { 41 | sf := SavedField{ 42 | Name: f.Name, 43 | FixedSize: f.FixedSize, 44 | Index: uint(uintptr(unsafe.Pointer(f.Index))), 45 | Size: f.Size, 46 | Type: f.Type, 47 | } 48 | svt.Fields = append(svt.Fields, sf) 49 | } 50 | svts = append(svts, svt) 51 | } 52 | data, _ := json.Marshal(svts) 53 | ioutil.WriteFile(common.COMMON_DIR+"\\tables.json", data, 0666) 54 | } 55 | 56 | func Restore() { 57 | syncTablesToFile() 58 | } 59 | 60 | // Before run this function please run memory.RecoveryFirst 61 | func Recovery() { 62 | TableList = []*Table{} //WARNING 63 | data, err := ioutil.ReadFile(common.COMMON_DIR + "\\tables.json") 64 | if err != nil { 65 | log.WriteLog("sys", "Tables recovery interrupt with an error :"+err.Error()) 66 | return 67 | } 68 | var svt []map[string]interface{} 69 | err = json.Unmarshal(data, &svt) 70 | if err != nil { 71 | log.WriteLog("sys", "Tables recovery interrupt with an error :"+err.Error()) 72 | return 73 | } 74 | for _, v := range svt { 75 | t := &Table{ 76 | Name: v["Name"].(string), 77 | Primary: int(v["Primary"].(float64)), 78 | } 79 | for _, f := range v["Fields"].([]interface{}) { 80 | fd := f.(map[string]interface{}) 81 | field := Field{ 82 | Name: fd["Name"].(string), 83 | FixedSize: fd["FixedSize"].(bool), 84 | Size: int(fd["Size"].(float64)), 85 | Type: int(fd["Type"].(float64)), 86 | } 87 | ind := uintptr(uint(fd["Index"].(float64))) 88 | field.Index = index.RecoveryTable[ind] 89 | t.Fields = append(t.Fields, field) 90 | } 91 | firstPagePtr := uintptr(uint(v["FirstPage"].(float64))) 92 | firstPage := &Page{ 93 | DataBlock: *(memory.RecoveryTable[firstPagePtr]), 94 | } 95 | t.FirstPage = firstPage 96 | t.LastPage = firstPage.Recovery(t, nil) 97 | TableList = append(TableList, t) 98 | } 99 | log.WriteLog("sys", "Recovery "+strconv.Itoa(len(TableList))+" Tables.") 100 | } 101 | -------------------------------------------------------------------------------- /table/table.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | import ( 4 | "../index" 5 | ) 6 | 7 | const ( 8 | FIELD_TYPE_INT = iota 9 | FIELD_TYPE_FLOAT 10 | FIELD_TYPE_VARCHAR 11 | ) 12 | 13 | type Field struct { 14 | Name string 15 | FixedSize bool 16 | Index *index.Index 17 | Size int 18 | Type int 19 | } 20 | 21 | type savedRow struct { 22 | skip uint //in every row there is a uint skip to indicate this row was deleted and how many to skip to next record 23 | size uint32 //if not fixed 24 | data []byte 25 | } 26 | 27 | type Table struct { 28 | Name string 29 | Fields []Field 30 | FirstPage *Page 31 | LastPage *Page 32 | Primary int 33 | } 34 | 35 | type Index struct { 36 | Name string 37 | Fields []Field 38 | } 39 | 40 | func GetTableByName(name string) *Table { 41 | for _, v := range TableList { 42 | if v.Name == name { 43 | return v 44 | } 45 | } 46 | return nil 47 | } 48 | -------------------------------------------------------------------------------- /table/util.go: -------------------------------------------------------------------------------- 1 | package table 2 | 3 | func uint162bytes(u uint16) []byte { 4 | b := make([]byte, 2) 5 | for i := 0;i < 2;i++ { 6 | b[i] = (byte)(u) 7 | u >>= 8 8 | } 9 | return b 10 | } 11 | 12 | func bytes2uint16(b []byte) uint16 { 13 | p := uint16(0) 14 | for i := 1;i >= 0;i-- { 15 | p <<= 8 16 | p |= uint16(b[i]) 17 | } 18 | return p 19 | } 20 | 21 | func uint322bytes(u uint32) []byte { 22 | b := make([]byte, 4) 23 | for i := 0;i < 4;i++ { 24 | b[i] = (byte)(u) 25 | u >>= 8 26 | } 27 | return b 28 | } 29 | 30 | func bytes2uint32(b []byte) uint32 { 31 | p := uint32(0) 32 | for i := 3;i >= 0;i-- { 33 | p <<= 8 34 | p |= uint32(b[i]) 35 | } 36 | return p 37 | } 38 | 39 | func uint2bytes(p uint) []byte { 40 | b := make([]byte, 8) 41 | for i := 0;i < 8;i++ { 42 | b[i] = (byte)(p) 43 | p >>= 8 44 | } 45 | return b 46 | } 47 | 48 | func bytes2uint(b []byte) uint { 49 | p := uint(0) 50 | for i := 7;i >= 0;i-- { 51 | p <<= 8 52 | p |= uint(b[i]) 53 | } 54 | return p 55 | } 56 | -------------------------------------------------------------------------------- /test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | a := "我是一个人ABC" 7 | fmt.Println([]byte(a)) 8 | } --------------------------------------------------------------------------------