Skip to content

Commit 7b94756

Browse files
committed
First pass at new interfaces for insert / update / delete that should make them more performant for inserting multipled rows in a single statement.
Signed-off-by: Zach Musgrave <zach@liquidata.co>
1 parent d1ae6a2 commit 7b94756

File tree

6 files changed

+75
-27
lines changed

6 files changed

+75
-27
lines changed

engine_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3812,7 +3812,7 @@ func TestGenerators(t *testing.T) {
38123812
}
38133813
}
38143814

3815-
func insertRows(t *testing.T, table sql.Inserter, rows ...sql.Row) {
3815+
func insertRows(t *testing.T, table sql.InsertableTable, rows ...sql.Row) {
38163816
t.Helper()
38173817

38183818
for _, r := range rows {

memory/table.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type Table struct {
2828
}
2929

3030
var _ sql.Table = (*Table)(nil)
31-
var _ sql.Inserter = (*Table)(nil)
31+
var _ sql.InsertableTable = (*Table)(nil)
3232
var _ sql.FilteredTable = (*Table)(nil)
3333
var _ sql.ProjectedTable = (*Table)(nil)
3434
var _ sql.IndexableTable = (*Table)(nil)

sql/core.go

Lines changed: 59 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -205,28 +205,76 @@ type IndexableTable interface {
205205
IndexKeyValues(*Context, []string) (PartitionIndexKeyValueIter, error)
206206
}
207207

208-
// Inserter allow rows to be inserted in them.
209-
type Inserter interface {
210-
// Insert the given row.
208+
// InsertableTable is a table that can process insertion of new rows.
209+
type InsertableTable interface {
210+
// Inserter returns an Inserter for this table. The Inserter will get one call to Insert() for each row to be
211+
// inserted, and will end with a call to Close() to finalize the insert operation.
212+
Inserter(*Context) RowInserter
213+
}
214+
215+
// RowInserter is an insert cursor that can insert one or more values to a table.
216+
type RowInserter interface {
217+
// Insert inserts the row given, returning an error if it cannot. Insert will be called once for each row to process
218+
// for the insert operation, which may involve many rows. After all rows in an operation have been processed, Close
219+
// is called.
211220
Insert(*Context, Row) error
221+
// Close finalizes the insert operation, persisting its result.
222+
Close(*Context) error
223+
}
224+
225+
// DeleteableTable is a table that can process the deletion of rows
226+
type DeletableTable interface {
227+
// Deleter returns a RowDeleter for this table. The RowDeleter will get one call to Delete for each row to be deleted,
228+
// and will end with a call to Close() to finalize the delete operation.
229+
Deleter(*Context, Row) RowDeleter
230+
}
231+
232+
// RowDeleter is a delete cursor that can delete one or more rows from a table.
233+
type RowDeleter interface {
234+
// Delete deletes the given row. Returns ErrDeleteRowNotFound if the row was not found. Delete will be called once for
235+
// each row to process for the delete operation, which may involve many rows. After all rows have been processed,
236+
// Close is called.
237+
Delete(*Context, Row) error
238+
// Close finalizes the delete operation, persisting the result.
239+
Close(*Context) error
240+
}
241+
242+
type Closer interface {
243+
Close(*Context) error
212244
}
213245

214-
// Deleter allow rows to be deleted from tables.
215-
type Deleter interface {
216-
// Delete the given row. Returns ErrDeleteRowNotFound if the row was not found.
246+
type RowReplacer interface {
247+
// Insert inserts the row given, returning an error if it cannot. Insert will be called once for each row to process
248+
// for the replace operation, which may involve many rows. After all rows in an operation have been processed, Close
249+
// is called.
250+
Insert(*Context, Row) error
251+
// Delete deletes the given row. Returns ErrDeleteRowNotFound if the row was not found. Delete will be called once for
252+
// each row to process for the delete operation, which may involve many rows. After all rows have been processed,
253+
// Close is called.
217254
Delete(*Context, Row) error
255+
// Close finalizes the replace operation, persisting the result.
256+
Close(*Context) error
218257
}
219258

220259
// Replacer allows rows to be replaced through a Delete (if applicable) then Insert.
221-
type Replacer interface {
222-
Deleter
223-
Inserter
260+
type ReplaceableTable interface {
261+
// Replacer returns a RowReplacer for this table. The RowReplacer will have Insert and optionally Delete called once
262+
// for each row, followed by a call to Close() when all rows have been processed.
263+
Replacer() RowReplacer
264+
}
265+
266+
// UpdateableTable is a table that can process updates of existing rows via update statements.
267+
type UpdatableTable interface {
268+
// Updater returns a RowUpdater for this table. The RowUpdater will have Update called once for each row to be
269+
// updated, followed by a call to Close() when all rows have been processed.
270+
Updater(ctx *Context) RowUpdater
224271
}
225272

226-
// Updater allows rows to be updated.
227-
type Updater interface {
273+
type RowUpdater interface {
228274
// Update the given row. Provides both the old and new rows.
229275
Update(ctx *Context, old Row, new Row) error
276+
// Close finalizes the delete operation, persisting the result.
277+
Close(*Context) error
230278
}
231279

232280
// Database represents the database.

sql/plan/delete.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ func (p *DeleteFrom) Children() []sql.Node {
3737
return []sql.Node{p.Node}
3838
}
3939

40-
func getDeletable(node sql.Node) (sql.Deleter, error) {
40+
func getDeletable(node sql.Node) (sql.DeletableTable, error) {
4141
switch node := node.(type) {
42-
case sql.Deleter:
42+
case sql.DeletableTable:
4343
return node, nil
4444
case *ResolvedTable:
4545
return getDeletableTable(node.Table)
@@ -53,9 +53,9 @@ func getDeletable(node sql.Node) (sql.Deleter, error) {
5353
return nil, ErrDeleteFromNotSupported.New()
5454
}
5555

56-
func getDeletableTable(t sql.Table) (sql.Deleter, error) {
56+
func getDeletableTable(t sql.Table) (sql.DeletableTable, error) {
5757
switch t := t.(type) {
58-
case sql.Deleter:
58+
case sql.DeletableTable:
5959
return t, nil
6060
case sql.TableWrapper:
6161
return getDeletableTable(t.Underlying())

sql/plan/insert.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ func (p *InsertInto) Schema() sql.Schema {
4545
}}
4646
}
4747

48-
func getInsertable(node sql.Node) (sql.Inserter, error) {
48+
func getInsertable(node sql.Node) (sql.InsertableTable, error) {
4949
switch node := node.(type) {
50-
case sql.Inserter:
50+
case sql.InsertableTable:
5151
return node, nil
5252
case *ResolvedTable:
5353
return getInsertableTable(node.Table)
@@ -56,9 +56,9 @@ func getInsertable(node sql.Node) (sql.Inserter, error) {
5656
}
5757
}
5858

59-
func getInsertableTable(t sql.Table) (sql.Inserter, error) {
59+
func getInsertableTable(t sql.Table) (sql.InsertableTable, error) {
6060
switch t := t.(type) {
61-
case sql.Inserter:
61+
case sql.InsertableTable:
6262
return t, nil
6363
case sql.TableWrapper:
6464
return getInsertableTable(t.Underlying())
@@ -74,10 +74,10 @@ func (p *InsertInto) Execute(ctx *sql.Context) (int, error) {
7474
return 0, err
7575
}
7676

77-
var replaceable sql.Replacer
77+
var replaceable sql.ReplaceableTable
7878
if p.IsReplace {
7979
var ok bool
80-
replaceable, ok = insertable.(sql.Replacer)
80+
replaceable, ok = insertable.(sql.ReplaceableTable)
8181
if !ok {
8282
return 0, ErrReplaceIntoNotSupported.New()
8383
}

sql/plan/update.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ func (p *Update) Children() []sql.Node {
6060
return []sql.Node{p.Node}
6161
}
6262

63-
func getUpdatable(node sql.Node) (sql.Updater, error) {
63+
func getUpdatable(node sql.Node) (sql.UpdatableTable, error) {
6464
switch node := node.(type) {
65-
case sql.Updater:
65+
case sql.UpdatableTable:
6666
return node, nil
6767
case *ResolvedTable:
6868
return getUpdatableTable(node.Table)
@@ -76,9 +76,9 @@ func getUpdatable(node sql.Node) (sql.Updater, error) {
7676
return nil, ErrUpdateNotSupported.New()
7777
}
7878

79-
func getUpdatableTable(t sql.Table) (sql.Updater, error) {
79+
func getUpdatableTable(t sql.Table) (sql.UpdatableTable, error) {
8080
switch t := t.(type) {
81-
case sql.Updater:
81+
case sql.UpdatableTable:
8282
return t, nil
8383
case sql.TableWrapper:
8484
return getUpdatableTable(t.Underlying())

0 commit comments

Comments
 (0)