1
1
package gitql
2
2
3
3
import (
4
+ gosql "database/sql"
5
+ "database/sql/driver"
6
+ "errors"
7
+ "fmt"
8
+
4
9
"github.com/gitql/gitql/sql"
5
10
"github.com/gitql/gitql/sql/analyzer"
6
11
"github.com/gitql/gitql/sql/expression"
7
12
"github.com/gitql/gitql/sql/parse"
8
13
)
9
14
15
+ var (
16
+ ErrNotSupported = errors .New ("feature not supported yet" )
17
+ )
18
+
19
+ const (
20
+ DriverName = "gitql"
21
+ )
22
+
23
+ func init () {
24
+ gosql .Register (DriverName , defaultDriver )
25
+ }
26
+
27
+ type drv struct {}
28
+
29
+ var defaultDriver = & drv {}
30
+
31
+ func (d * drv ) Open (name string ) (driver.Conn , error ) {
32
+ if name != "" {
33
+ return nil , fmt .Errorf ("data source not found: %s" , name )
34
+ }
35
+
36
+ e := DefaultEngine
37
+ return & session {Engine : e }, nil
38
+ }
39
+
40
+ // DefaultEngine is the default Engine instance, used when opening a connection
41
+ // to gitql:// when using database/sql.
42
+ var DefaultEngine = New ()
43
+
44
+ // Engine is a SQL engine.
45
+ // It implements the standard database/sql/driver/Driver interface, so it can
46
+ // be registered as a database/sql driver.
10
47
type Engine struct {
11
48
Catalog * sql.Catalog
12
49
Analyzer * analyzer.Analyzer
13
50
}
14
51
52
+ // New creates a new Engine.
15
53
func New () * Engine {
16
54
c := sql .NewCatalog ()
17
55
err := expression .RegisterDefaults (c )
@@ -23,11 +61,15 @@ func New() *Engine {
23
61
return & Engine {c , a }
24
62
}
25
63
26
- func (e * Engine ) AddDatabase (db sql.Database ) {
27
- e .Catalog .Databases = append (e .Catalog .Databases , db )
28
- e .Analyzer .CurrentDatabase = db .Name ()
64
+ // Open creates a new session for the engine and returns
65
+ // it as a driver.Conn.
66
+ //
67
+ // Name parameter is ignored.
68
+ func (e * Engine ) Open (name string ) (driver.Conn , error ) {
69
+ return & session {Engine : e }, nil
29
70
}
30
71
72
+ // Query executes a query without attaching to any session.
31
73
func (e * Engine ) Query (query string ) (sql.Schema , sql.RowIter , error ) {
32
74
parsed , err := parse .Parse (query )
33
75
if err != nil {
@@ -46,3 +88,134 @@ func (e *Engine) Query(query string) (sql.Schema, sql.RowIter, error) {
46
88
47
89
return analyzed .Schema (), iter , nil
48
90
}
91
+
92
+ func (e * Engine ) AddDatabase (db sql.Database ) {
93
+ e .Catalog .Databases = append (e .Catalog .Databases , db )
94
+ e .Analyzer .CurrentDatabase = db .Name ()
95
+ }
96
+
97
+ // Session represents a SQL session.
98
+ // It implements the standard database/sql/driver/Conn interface.
99
+ type session struct {
100
+ * Engine
101
+ closed bool
102
+ //TODO: Current database
103
+ }
104
+
105
+ // Prepare returns a prepared statement, bound to this connection.
106
+ // Placeholders are not supported yet.
107
+ func (s * session ) Prepare (query string ) (driver.Stmt , error ) {
108
+ if err := s .checkOpen (); err != nil {
109
+ return nil , err
110
+ }
111
+
112
+ return & stmt {session : s , query : query }, nil
113
+ }
114
+
115
+ // Close closes the session.
116
+ func (s * session ) Close () error {
117
+ if err := s .checkOpen (); err != nil {
118
+ return err
119
+ }
120
+
121
+ s .closed = true
122
+ return nil
123
+ }
124
+
125
+ // Begin starts and returns a new transaction.
126
+ func (s * session ) Begin () (driver.Tx , error ) {
127
+ return nil , fmt .Errorf ("transactions not supported" )
128
+ }
129
+
130
+ func (s * session ) checkOpen () error {
131
+ if s .closed {
132
+ return driver .ErrBadConn
133
+ }
134
+
135
+ return nil
136
+ }
137
+
138
+ type stmt struct {
139
+ * session
140
+ query string
141
+ closed bool
142
+ }
143
+
144
+ // Close closes the statement.
145
+ func (s * stmt ) Close () error {
146
+ if err := s .checkOpen (); err != nil {
147
+ return err
148
+ }
149
+
150
+ s .closed = true
151
+ return nil
152
+ }
153
+
154
+ // NumInput returns the number of placeholder parameters.
155
+ // Always returns -1 since placeholders are not supported yet.
156
+ func (s * stmt ) NumInput () int {
157
+ return - 1
158
+ }
159
+
160
+ // Exec executes a query that doesn't return rows, such as an INSERT or UPDATE.
161
+ func (s * stmt ) Exec (args []driver.Value ) (driver.Result , error ) {
162
+ return nil , ErrNotSupported
163
+ }
164
+
165
+ // Query executes a query that may return rows, such as a SELECT.
166
+ func (s * stmt ) Query (args []driver.Value ) (driver.Rows , error ) {
167
+ if len (args ) > 0 {
168
+ return nil , ErrNotSupported
169
+ }
170
+
171
+ schema , iter , err := s .session .Engine .Query (s .query )
172
+ if err != nil {
173
+ return nil , err
174
+ }
175
+
176
+ return & rows {schema : schema , iter : iter }, nil
177
+ }
178
+
179
+ func (s * stmt ) checkOpen () error {
180
+ if s .closed {
181
+ return driver .ErrBadConn
182
+ }
183
+
184
+ return nil
185
+ }
186
+
187
+ type rows struct {
188
+ schema sql.Schema
189
+ iter sql.RowIter
190
+ }
191
+
192
+ // Columns returns the names of the columns.
193
+ func (rs * rows ) Columns () []string {
194
+ c := make ([]string , len (rs .schema ))
195
+ for i := 0 ; i < len (rs .schema ); i ++ {
196
+ c [i ] = rs .schema [i ].Name
197
+ }
198
+
199
+ return c
200
+ }
201
+
202
+ // Close closes the rows iterator.
203
+ func (rs * rows ) Close () error {
204
+ return rs .iter .Close ()
205
+ }
206
+
207
+ // Next populates the given array with the next row values.
208
+ // Returns io.EOF when there are no more values.
209
+ func (rs * rows ) Next (dest []driver.Value ) error {
210
+ r , err := rs .iter .Next ()
211
+ if err != nil {
212
+ return err
213
+ }
214
+
215
+ for i := range dest {
216
+ f := rs .schema [i ]
217
+ dest [i ] = f .Type .Native (r [i ])
218
+ }
219
+
220
+ return nil
221
+ }
0 commit comments