├── .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 | }
--------------------------------------------------------------------------------