-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommands.go
130 lines (106 loc) · 2.72 KB
/
commands.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main
import (
"errors"
"godb/table"
)
func (db *Database) Insert(tbl *table.Table, row table.Row) error {
if !tbl.Schema.CheckSchema(row) {
return errors.New("Insert failed. Row doesn't conform to table schema.")
}
rowLen := row.Length()
page, err := tbl.FindFreePage(rowLen)
if err != nil {
return err
}
entryBuffer, err := page.FindFreeEntry(rowLen)
if err != nil {
return err
}
row.Encode(entryBuffer)
err = page.Flush()
if err != nil {
return err
}
err = db.FlushTableDictionary(tbl)
if err != nil {
return err
}
return nil
}
// TODO: Allow multiple rows to be returned
func (db *Database) Select(tbl *table.Table, column string, targetValue table.ColumnValue) (table.Row, error) {
colDef, colIdx, err := tbl.Schema.FindColumnByName(column)
if err != nil {
return nil, err
}
if colDef.Type != targetValue.Type() {
return nil, errors.New("Select failed. Value type doesn't match")
}
page, err := tbl.FetchDataPage(tbl.FirstPageIdx)
for {
if err != nil { // pageIdx out of range. Key not found.
return nil, errors.New("Select failed. Key not found!")
}
for entryIdx := int16(0); entryIdx < page.Header.RowPointersLength; entryIdx++ {
entryBuffer, err := page.GetEntry(entryIdx)
if err != nil {
continue
}
row, _, err := tbl.DecodeRow(entryBuffer, tbl.Schema)
if err != nil {
return nil, err
}
compVal, err := row[colIdx].Compare(targetValue)
if err != nil {
return nil, err
}
if compVal == 0 {
// FOUND!
return row, nil
}
}
page, err = tbl.NextPage(page)
}
}
func (db *Database) Update(tbl *table.Table, targetColumn string, targetValue table.ColumnValue, newRow table.Row) error {
if !tbl.Schema.CheckSchema(newRow) {
return errors.New("Updated row has different schema")
}
colDef, colIdx, err := tbl.Schema.FindColumnByName(targetColumn)
if err != nil {
return err
}
if colDef.Type != targetValue.Type() {
return errors.New("Update failed. Target value type doesn't match")
}
page, err := tbl.FetchDataPage(tbl.FirstPageIdx)
for {
if err != nil { // pageIdx out of range. Key not found.
return errors.New("Update failed. Key not found!")
}
for entryIdx := int16(0); entryIdx < page.Header.RowPointersLength; entryIdx++ {
entryBuffer, err := page.GetEntry(entryIdx)
if err != nil {
continue
}
row, _, err := tbl.DecodeRow(entryBuffer, tbl.Schema)
if err != nil {
return err
}
compVal, err := row[colIdx].Compare(targetValue)
if err != nil {
return err
}
if compVal == 0 {
// TODO: Handle variable size data types.
newRow.Encode(entryBuffer)
err = page.Flush()
if err != nil {
return err
}
return nil
}
}
page, err = tbl.NextPage(page)
}
}