| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266 |
- // Copyright (c) 2014 ql Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package ql
- import (
- "bytes"
- "fmt"
- "strings"
- "github.com/cznic/strutil"
- )
- // NOTE: all stmt implementations must be safe for concurrent use by multiple
- // goroutines. If the exec method requires any execution domain local data,
- // they must be held out of the implementing instance.
- var (
- _ stmt = (*alterTableAddStmt)(nil)
- _ stmt = (*alterTableDropColumnStmt)(nil)
- _ stmt = (*createIndexStmt)(nil)
- _ stmt = (*createTableStmt)(nil)
- _ stmt = (*deleteStmt)(nil) //TODO optimizer plan
- _ stmt = (*dropIndexStmt)(nil)
- _ stmt = (*dropTableStmt)(nil)
- _ stmt = (*explainStmt)(nil)
- _ stmt = (*insertIntoStmt)(nil)
- _ stmt = (*selectStmt)(nil)
- _ stmt = (*truncateTableStmt)(nil)
- _ stmt = (*updateStmt)(nil) //TODO optimizer plan
- _ stmt = beginTransactionStmt{}
- _ stmt = commitStmt{}
- _ stmt = rollbackStmt{}
- )
- var (
- createColumn2 = mustCompile(`
- create table if not exists __Column2 (
- TableName string,
- Name string,
- NotNull bool,
- ConstraintExpr string,
- DefaultExpr string,
- );
- create index if not exists __Column2TableName on __Column2(TableName);
- `)
- insertColumn2 = mustCompile(`insert into __Column2 values($1, $2, $3, $4, $5)`)
- selectColumn2 = MustCompile(`
- select Name, NotNull, ConstraintExpr, DefaultExpr
- from __Column2
- where TableName == $1
- `)
- deleteColumn2 = mustCompile(`
- delete from __Column2
- where TableName == $1 && Name == $2
- `)
- createIndex2 = mustCompile(`
- // Index register 2.
- create table if not exists __Index2(
- TableName string,
- IndexName string,
- IsUnique bool,
- IsSimple bool, // Just a column name or id().
- Root int64, // BTree handle
- );
- // Expressions for given index. Compared in order of id(__Index2_Expr).
- create table if not exists __Index2_Expr(
- Index2_ID int,
- Expr string,
- );
- create index if not exists __xIndex2_TableName on __Index2(TableName);
- create unique index if not exists __xIndex2_IndexName on __Index2(IndexName);
- create index if not exists __xIndex2_ID on __Index2(id());
- create index if not exists __xIndex2_Expr_Index2_ID on __Index2_Expr(Index2_ID);
- `)
- insertIndex2 = mustCompile("insert into __Index2 values($1, $2, $3, $4, $5)")
- insertIndex2Expr = mustCompile("insert into __Index2_Expr values($1, $2)")
- deleteIndex2ByIndexName = mustCompile(`
- delete from __Index2_Expr
- where Index2_ID in (
- select id() from __Index2 where IndexName == $1;
- );
- delete from __Index2
- where IndexName == $1;
- `)
- deleteIndex2ByTableName = mustCompile(`
- delete from __Index2_Expr
- where Index2_ID in (
- select id() from __Index2 where TableName == $1;
- );
- delete from __Index2
- where TableName == $1;
- `)
- )
- type stmt interface {
- // never invoked for
- // - beginTransactionStmt
- // - commitStmt
- // - rollbackStmt
- exec(ctx *execCtx) (Recordset, error)
- explain(ctx *execCtx, w strutil.Formatter)
- // return value ignored for
- // - beginTransactionStmt
- // - commitStmt
- // - rollbackStmt
- isUpdating() bool
- String() string
- }
- type execCtx struct { //LATER +shared temp
- db *DB
- arg []interface{}
- }
- type explainStmt struct {
- s stmt
- }
- func (s *explainStmt) explain(ctx *execCtx, w strutil.Formatter) {
- for {
- x, ok := s.s.(*explainStmt)
- if !ok {
- s.s.explain(ctx, w)
- return
- }
- s = x
- }
- }
- func (s *explainStmt) String() string {
- return "EXPLAIN " + s.s.String()
- }
- func (*explainStmt) isUpdating() bool { return false }
- func (s *explainStmt) exec(ctx *execCtx) (_ Recordset, err error) {
- return recordset{ctx, &explainDefaultPlan{s.s}, ctx.db.cc}, nil
- }
- type updateStmt struct {
- tableName string
- list []assignment
- where expression
- }
- func (s *updateStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *updateStmt) String() string {
- u := fmt.Sprintf("UPDATE %s", s.tableName)
- a := make([]string, len(s.list))
- for i, v := range s.list {
- a[i] = v.String()
- }
- w := ""
- if s.where != nil {
- w = fmt.Sprintf(" WHERE %s", s.where)
- }
- return fmt.Sprintf("%s %s%s;", u, strings.Join(a, ", "), w)
- }
- func (s *updateStmt) exec(ctx *execCtx) (_ Recordset, err error) {
- t, ok := ctx.db.root.tables[s.tableName]
- if !ok {
- return nil, fmt.Errorf("UPDATE: table %s does not exist", s.tableName)
- }
- tcols := make([]*col, len(s.list))
- for i, asgn := range s.list {
- col := findCol(t.cols, asgn.colName)
- if col == nil {
- return nil, fmt.Errorf("UPDATE: unknown column %s", asgn.colName)
- }
- tcols[i] = col
- }
- m := map[interface{}]interface{}{}
- var nh int64
- expr := s.where
- blobCols := t.blobCols()
- cc := ctx.db.cc
- var old []interface{}
- var touched []bool
- if t.hasIndices() {
- old = make([]interface{}, len(t.cols0))
- touched = make([]bool, len(t.cols0))
- }
- for h := t.head; h != 0; h = nh {
- // Read can return lazily expanded chunks
- data, err := t.store.Read(nil, h, t.cols...)
- if err != nil {
- return nil, err
- }
- nh = data[0].(int64)
- for _, col := range t.cols {
- m[col.name] = data[2+col.index]
- }
- id := data[1].(int64)
- m["$id"] = id
- if expr != nil {
- val, err := s.where.eval(ctx, m)
- if err != nil {
- return nil, err
- }
- if val == nil {
- continue
- }
- x, ok := val.(bool)
- if !ok {
- return nil, fmt.Errorf("invalid WHERE expression %s (value of type %T)", val, val)
- }
- if !x {
- continue
- }
- }
- // hit
- for _, ix := range t.indices2 {
- vlist, err := ix.eval(ctx, t.cols, id, data[2:])
- if err != nil {
- return nil, err
- }
- if err := ix.x.Delete(vlist, h); err != nil {
- return nil, err
- }
- }
- for i, asgn := range s.list {
- val, err := asgn.expr.eval(ctx, m)
- if err != nil {
- return nil, err
- }
- colIndex := tcols[i].index
- if t.hasIndices() {
- old[colIndex] = data[2+colIndex]
- touched[colIndex] = true
- }
- data[2+colIndex] = val
- }
- if err = typeCheck(data[2:], t.cols); err != nil {
- return nil, err
- }
- if err = t.checkConstraintsAndDefaults(ctx, data[2:], m); err != nil {
- return nil, err
- }
- for i, v := range t.indices {
- if i == 0 { // id() N/A
- continue
- }
- if v == nil || !touched[i-1] {
- continue
- }
- if err = v.x.Delete([]interface{}{old[i-1]}, h); err != nil {
- return nil, err
- }
- }
- if err = t.store.UpdateRow(h, blobCols, data...); err != nil { //LATER detect which blobs are actually affected
- return nil, err
- }
- for i, v := range t.indices {
- if i == 0 { // id() N/A
- continue
- }
- if v == nil || !touched[i-1] {
- continue
- }
- if err = v.x.Create([]interface{}{data[2+i-1]}, h); err != nil {
- return nil, err
- }
- }
- for _, ix := range t.indices2 {
- vlist, err := ix.eval(ctx, t.cols, id, data[2:])
- if err != nil {
- return nil, err
- }
- if err := ix.x.Create(vlist, h); err != nil {
- return nil, err
- }
- }
- cc.RowsAffected++
- }
- return
- }
- func (s *updateStmt) isUpdating() bool { return true }
- type deleteStmt struct {
- tableName string
- where expression
- }
- func (s *deleteStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *deleteStmt) String() string {
- switch {
- case s.where == nil:
- return fmt.Sprintf("DELETE FROM %s;", s.tableName)
- default:
- return fmt.Sprintf("DELETE FROM %s WHERE %s;", s.tableName, s.where)
- }
- }
- func (s *deleteStmt) exec(ctx *execCtx) (_ Recordset, err error) {
- t, ok := ctx.db.root.tables[s.tableName]
- if !ok {
- return nil, fmt.Errorf("DELETE FROM: table %s does not exist", s.tableName)
- }
- m := map[interface{}]interface{}{}
- var ph, h, nh int64
- var data []interface{}
- blobCols := t.blobCols()
- cc := ctx.db.cc
- for h = t.head; h != 0; ph, h = h, nh {
- for i, v := range data {
- c, ok := v.(chunk)
- if !ok {
- continue
- }
- data[i] = c.b
- }
- // Read can return lazily expanded chunks
- data, err = t.store.Read(nil, h, t.cols...)
- if err != nil {
- return nil, err
- }
- nh = data[0].(int64)
- for _, col := range t.cols {
- m[col.name] = data[2+col.index]
- }
- id := data[1].(int64)
- m["$id"] = id
- val, err := s.where.eval(ctx, m)
- if err != nil {
- return nil, err
- }
- if val == nil {
- continue
- }
- x, ok := val.(bool)
- if !ok {
- return nil, fmt.Errorf("invalid WHERE expression %s (value of type %T)", val, val)
- }
- if !x {
- continue
- }
- // hit
- for i, v := range t.indices {
- if v == nil {
- continue
- }
- // overflow chunks left in place
- if err = v.x.Delete([]interface{}{data[i+1]}, h); err != nil {
- return nil, err
- }
- }
- for _, ix := range t.indices2 {
- vlist, err := ix.eval(ctx, t.cols, id, data[2:])
- if err != nil {
- return nil, err
- }
- if err := ix.x.Delete(vlist, h); err != nil {
- return nil, err
- }
- }
- // overflow chunks freed here
- if err = t.store.Delete(h, blobCols...); err != nil {
- return nil, err
- }
- cc.RowsAffected++
- switch {
- case ph == 0 && nh == 0: // "only"
- fallthrough
- case ph == 0 && nh != 0: // "first"
- if err = t.store.Update(t.hhead, nh); err != nil {
- return nil, err
- }
- t.head, h = nh, 0
- case ph != 0 && nh == 0: // "last"
- fallthrough
- case ph != 0 && nh != 0: // "inner"
- pdata, err := t.store.Read(nil, ph, t.cols...)
- if err != nil {
- return nil, err
- }
- for i, v := range pdata {
- if x, ok := v.(chunk); ok {
- pdata[i] = x.b
- }
- }
- pdata[0] = nh
- if err = t.store.Update(ph, pdata...); err != nil {
- return nil, err
- }
- h = ph
- }
- }
- return
- }
- func (s *deleteStmt) isUpdating() bool { return true }
- type truncateTableStmt struct {
- tableName string
- }
- func (s *truncateTableStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *truncateTableStmt) String() string { return fmt.Sprintf("TRUNCATE TABLE %s;", s.tableName) }
- func (s *truncateTableStmt) exec(ctx *execCtx) (Recordset, error) {
- t, ok := ctx.db.root.tables[s.tableName]
- if !ok {
- return nil, fmt.Errorf("TRUNCATE TABLE: table %s does not exist", s.tableName)
- }
- return nil, t.truncate()
- }
- func (s *truncateTableStmt) isUpdating() bool { return true }
- type dropIndexStmt struct {
- ifExists bool
- indexName string
- }
- func (s *dropIndexStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *dropIndexStmt) String() string { return fmt.Sprintf("DROP INDEX %s;", s.indexName) }
- func (s *dropIndexStmt) exec(ctx *execCtx) (Recordset, error) {
- t, x := ctx.db.root.findIndexByName(s.indexName)
- if x == nil {
- if s.ifExists {
- return nil, nil
- }
- return nil, fmt.Errorf("DROP INDEX: index %s does not exist", s.indexName)
- }
- if ctx.db.hasAllIndex2() {
- if err := ctx.db.deleteIndex2ByIndexName(s.indexName); err != nil {
- return nil, err
- }
- }
- switch ix := x.(type) {
- case *indexedCol:
- for i, v := range t.indices {
- if v == nil || v.name != s.indexName {
- continue
- }
- return nil, t.dropIndex(i)
- }
- case *index2:
- delete(t.indices2, s.indexName)
- return nil, ix.x.Drop()
- }
- panic("internal error 058")
- }
- func (s *dropIndexStmt) isUpdating() bool { return true }
- type dropTableStmt struct {
- ifExists bool
- tableName string
- }
- func (s *dropTableStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *dropTableStmt) String() string { return fmt.Sprintf("DROP TABLE %s;", s.tableName) }
- func (s *dropTableStmt) exec(ctx *execCtx) (Recordset, error) {
- t, ok := ctx.db.root.tables[s.tableName]
- if !ok {
- if s.ifExists {
- return nil, nil
- }
- return nil, fmt.Errorf("DROP TABLE: table %s does not exist", s.tableName)
- }
- if ctx.db.hasAllIndex2() {
- if err := ctx.db.deleteIndex2ByTableName(s.tableName); err != nil {
- return nil, err
- }
- }
- return nil, ctx.db.root.dropTable(t)
- }
- func (s *dropTableStmt) isUpdating() bool { return true }
- type alterTableDropColumnStmt struct {
- tableName, colName string
- }
- func (s *alterTableDropColumnStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *alterTableDropColumnStmt) String() string {
- return fmt.Sprintf("ALTER TABLE %s DROP COLUMN %s;", s.tableName, s.colName)
- }
- func (s *alterTableDropColumnStmt) exec(ctx *execCtx) (Recordset, error) {
- t, ok := ctx.db.root.tables[s.tableName]
- if !ok {
- return nil, fmt.Errorf("ALTER TABLE: table %s does not exist", s.tableName)
- }
- cols := t.cols
- for _, c := range cols {
- if c.name == s.colName {
- if len(cols) == 1 {
- return nil, fmt.Errorf("ALTER TABLE %s DROP COLUMN: cannot drop the only column: %s", s.tableName, s.colName)
- }
- if _, ok := ctx.db.root.tables["__Column2"]; ok {
- if _, err := deleteColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name}}); err != nil {
- return nil, err
- }
- }
- c.name = ""
- t.cols0[c.index].name = ""
- if t.hasIndices() {
- if len(t.indices) != 0 {
- if v := t.indices[c.index+1]; v != nil {
- if err := t.dropIndex(c.index + 1); err != nil {
- return nil, err
- }
- if ctx.db.hasAllIndex2() {
- if err := ctx.db.deleteIndex2ByIndexName(v.name); err != nil {
- return nil, err
- }
- }
- }
- }
- for nm, ix := range t.indices2 {
- for _, e := range ix.exprList {
- m := mentionedColumns(e)
- if _, ok := m[s.colName]; ok {
- if err := ctx.db.deleteIndex2ByIndexName(nm); err != nil {
- return nil, err
- }
- if err := ix.x.Drop(); err != nil {
- return nil, err
- }
- delete(t.indices2, nm)
- break
- }
- }
- }
- }
- if err := t.constraintsAndDefaults(ctx); err != nil {
- return nil, err
- }
- return nil, t.updated()
- }
- }
- return nil, fmt.Errorf("ALTER TABLE %s DROP COLUMN: column %s does not exist", s.tableName, s.colName)
- }
- func (s *alterTableDropColumnStmt) isUpdating() bool { return true }
- type alterTableAddStmt struct {
- tableName string
- c *col
- }
- func (s *alterTableAddStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *alterTableAddStmt) String() string {
- r := fmt.Sprintf("ALTER TABLE %s ADD %s %s", s.tableName, s.c.name, typeStr(s.c.typ))
- c := s.c
- if x := c.constraint; x != nil { //TODO add (*col).String()
- switch e := x.expr; {
- case e != nil:
- r += " " + e.String()
- default:
- r += " NOT NULL"
- }
- }
- if x := c.dflt; x != nil {
- r += " DEFAULT " + x.String()
- }
- return r + ";"
- }
- func (s *alterTableAddStmt) exec(ctx *execCtx) (Recordset, error) {
- t, ok := ctx.db.root.tables[s.tableName]
- if !ok {
- return nil, fmt.Errorf("ALTER TABLE: table %s does not exist", s.tableName)
- }
- hasRecords := t.head != 0
- c := s.c
- if c.constraint != nil && hasRecords {
- return nil, fmt.Errorf("ALTER TABLE %s ADD %s: cannot add constrained column to table with existing data", s.tableName, c.name)
- }
- cols := t.cols
- for _, c := range cols {
- nm := c.name
- if nm == s.c.name {
- return nil, fmt.Errorf("ALTER TABLE %s ADD: column %s exists", s.tableName, nm)
- }
- }
- if len(t.indices) != 0 {
- t.indices = append(t.indices, nil)
- t.xroots = append(t.xroots, 0)
- if err := t.store.Update(t.hxroots, t.xroots...); err != nil {
- return nil, err
- }
- }
- if c.constraint != nil || c.dflt != nil {
- for _, s := range createColumn2.l {
- _, err := s.exec(&execCtx{db: ctx.db})
- if err != nil {
- return nil, err
- }
- }
- notNull := c.constraint != nil && c.constraint.expr == nil
- var co, d string
- if c.constraint != nil && c.constraint.expr != nil {
- co = c.constraint.expr.String()
- }
- if e := c.dflt; e != nil {
- d = e.String()
- }
- if _, err := insertColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name, notNull, co, d}}); err != nil {
- return nil, err
- }
- }
- t.cols0 = append(t.cols0, s.c)
- if err := t.constraintsAndDefaults(ctx); err != nil {
- return nil, err
- }
- return nil, t.updated()
- }
- func (s *alterTableAddStmt) isUpdating() bool { return true }
- type selectStmt struct {
- distinct bool
- flds []*fld
- from *joinRset
- group *groupByRset
- hasAggregates bool
- limit *limitRset
- offset *offsetRset
- order *orderByRset
- where *whereRset
- }
- func (s *selectStmt) explain(ctx *execCtx, w strutil.Formatter) {
- p, err := s.plan(ctx)
- if err != nil {
- w.Format("ERROR: %v\n", err)
- return
- }
- p.explain(w)
- }
- func (s *selectStmt) String() string {
- var b bytes.Buffer
- b.WriteString("SELECT")
- if s.distinct {
- b.WriteString(" DISTINCT")
- }
- switch {
- case len(s.flds) == 0:
- b.WriteString(" *")
- default:
- a := make([]string, len(s.flds))
- for i, v := range s.flds {
- s := v.expr.String()
- if v.name != "" && v.name != s {
- s += " AS " + v.name
- }
- a[i] = s
- }
- b.WriteString(" " + strings.Join(a, ", "))
- }
- b.WriteString(" FROM ")
- b.WriteString(s.from.String())
- if s.where != nil {
- b.WriteString(" WHERE ")
- b.WriteString(s.where.expr.String())
- }
- if s.group != nil {
- b.WriteString(" GROUP BY ")
- b.WriteString(strings.Join(s.group.colNames, ", "))
- }
- if s.order != nil {
- b.WriteString(" ORDER BY ")
- b.WriteString(s.order.String())
- }
- if s.limit != nil {
- b.WriteString(" LIMIT ")
- b.WriteString(s.limit.expr.String())
- }
- if s.offset != nil {
- b.WriteString(" OFFSET ")
- b.WriteString(s.offset.expr.String())
- }
- b.WriteRune(';')
- return b.String()
- }
- func (s *selectStmt) plan(ctx *execCtx) (plan, error) { //LATER overlapping goroutines/pipelines
- r, err := s.from.plan(ctx)
- if err != nil {
- return nil, err
- }
- if w := s.where; w != nil {
- if r, err = (&whereRset{expr: w.expr, src: r}).plan(ctx); err != nil {
- return nil, err
- }
- }
- switch {
- case !s.hasAggregates && s.group == nil: // nop
- case !s.hasAggregates && s.group != nil:
- if r, err = (&groupByRset{colNames: s.group.colNames, src: r}).plan(ctx); err != nil {
- return nil, err
- }
- case s.hasAggregates && s.group == nil:
- if r, err = (&groupByRset{src: r}).plan(ctx); err != nil {
- return nil, err
- }
- case s.hasAggregates && s.group != nil:
- if r, err = (&groupByRset{colNames: s.group.colNames, src: r}).plan(ctx); err != nil {
- return nil, err
- }
- }
- if r, err = (&selectRset{flds: s.flds, src: r}).plan(ctx); err != nil {
- return nil, err
- }
- if s.distinct {
- if r, err = (&distinctRset{src: r}).plan(ctx); err != nil {
- return nil, err
- }
- }
- if s := s.order; s != nil {
- if r, err = (&orderByRset{asc: s.asc, by: s.by, src: r}).plan(ctx); err != nil {
- return nil, err
- }
- }
- if s := s.offset; s != nil {
- if r, err = (&offsetRset{s.expr, r}).plan(ctx); err != nil {
- return nil, err
- }
- }
- if s := s.limit; s != nil {
- if r, err = (&limitRset{s.expr, r}).plan(ctx); err != nil {
- return nil, err
- }
- }
- return r, nil
- }
- func (s *selectStmt) exec(ctx *execCtx) (rs Recordset, err error) {
- r, err := s.plan(ctx)
- if err != nil {
- return nil, err
- }
- return recordset{ctx, r, nil}, nil
- }
- func (s *selectStmt) isUpdating() bool { return false }
- type insertIntoStmt struct {
- colNames []string
- lists [][]expression
- sel *selectStmt
- tableName string
- }
- func (s *insertIntoStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *insertIntoStmt) String() string {
- cn := ""
- if len(s.colNames) != 0 {
- cn = fmt.Sprintf(" (%s)", strings.Join(s.colNames, ", "))
- }
- switch {
- case s.sel != nil:
- return fmt.Sprintf("INSERT INTO %s%s %s;", s.tableName, cn, s.sel)
- default:
- a := make([]string, len(s.lists))
- for i, v := range s.lists {
- b := make([]string, len(v))
- for i, v := range v {
- b[i] = v.String()
- }
- a[i] = fmt.Sprintf("(%s)", strings.Join(b, ", "))
- }
- return fmt.Sprintf("INSERT INTO %s%s VALUES %s;", s.tableName, cn, strings.Join(a, ", "))
- }
- }
- func (s *insertIntoStmt) execSelect(t *table, cols []*col, ctx *execCtx) (_ Recordset, err error) {
- //TODO missing rs column number eq check
- r, err := s.sel.plan(ctx)
- if err != nil {
- return nil, err
- }
- h := t.head
- data0 := make([]interface{}, len(t.cols0)+2)
- cc := ctx.db.cc
- m := map[interface{}]interface{}{}
- if err = r.do(ctx, func(_ interface{}, data []interface{}) (more bool, err error) {
- for i, d := range data {
- data0[cols[i].index+2] = d
- }
- if err = typeCheck(data0[2:], cols); err != nil {
- return
- }
- if err = t.checkConstraintsAndDefaults(ctx, data0[2:], m); err != nil {
- return false, err
- }
- id, err := t.store.ID()
- if err != nil {
- return false, err
- }
- data0[0] = h
- data0[1] = id
- // Any overflow chunks are written here.
- if h, err = t.store.Create(data0...); err != nil {
- return false, err
- }
- for i, v := range t.indices {
- if v == nil {
- continue
- }
- // Any overflow chunks are shared with the BTree key
- if err = v.x.Create([]interface{}{data0[i+1]}, h); err != nil {
- return false, err
- }
- }
- for _, ix := range t.indices2 {
- vlist, err := ix.eval(ctx, t.cols, id, data0[2:])
- if err != nil {
- return false, err
- }
- if err := ix.x.Create(vlist, h); err != nil {
- return false, err
- }
- }
- cc.RowsAffected++
- ctx.db.root.lastInsertID = id
- return true, nil
- }); err != nil {
- return nil, err
- }
- t.head = h
- return nil, t.store.Update(t.hhead, h)
- }
- func (s *insertIntoStmt) exec(ctx *execCtx) (_ Recordset, err error) {
- root := ctx.db.root
- t, ok := root.tables[s.tableName]
- if !ok {
- return nil, fmt.Errorf("INSERT INTO %s: table does not exist", s.tableName)
- }
- var cols []*col
- switch len(s.colNames) {
- case 0:
- cols = t.cols
- default:
- for _, colName := range s.colNames {
- if col := findCol(t.cols, colName); col != nil {
- cols = append(cols, col)
- continue
- }
- return nil, fmt.Errorf("INSERT INTO %s: unknown column %s", s.tableName, colName)
- }
- }
- if s.sel != nil {
- return s.execSelect(t, cols, ctx)
- }
- for _, list := range s.lists {
- if g, e := len(list), len(cols); g != e {
- return nil, fmt.Errorf("INSERT INTO %s: expected %d value(s), have %d", s.tableName, e, g)
- }
- }
- cc := ctx.db.cc
- r := make([]interface{}, len(t.cols0))
- m := map[interface{}]interface{}{}
- for _, list := range s.lists {
- for i, expr := range list {
- val, err := expr.eval(ctx, m)
- if err != nil {
- return nil, err
- }
- r[cols[i].index] = val
- }
- if err = typeCheck(r, cols); err != nil {
- return nil, err
- }
- if err = t.checkConstraintsAndDefaults(ctx, r, m); err != nil {
- return nil, err
- }
- id, err := t.addRecord(ctx, r)
- if err != nil {
- return nil, err
- }
- cc.RowsAffected++
- root.lastInsertID = id
- }
- return nil, nil
- }
- func (s *insertIntoStmt) isUpdating() bool { return true }
- type beginTransactionStmt struct{}
- func (s beginTransactionStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (beginTransactionStmt) String() string { return "BEGIN TRANSACTION;" }
- func (beginTransactionStmt) exec(*execCtx) (Recordset, error) {
- panic("internal error 059")
- }
- func (beginTransactionStmt) isUpdating() bool {
- panic("internal error 060")
- }
- type commitStmt struct{}
- func (s commitStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (commitStmt) String() string { return "COMMIT;" }
- func (commitStmt) exec(*execCtx) (Recordset, error) {
- panic("internal error 061")
- }
- func (commitStmt) isUpdating() bool {
- panic("internal error 062")
- }
- type rollbackStmt struct{}
- func (s rollbackStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (rollbackStmt) String() string { return "ROLLBACK;" }
- func (rollbackStmt) exec(*execCtx) (Recordset, error) {
- panic("internal error 063")
- }
- func (rollbackStmt) isUpdating() bool {
- panic("internal error 064")
- }
- type createIndexStmt struct {
- colName string // alt. "id()" for simple index on id()
- ifNotExists bool
- indexName string
- tableName string
- unique bool
- exprList []expression
- }
- func (s *createIndexStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *createIndexStmt) isSimpleIndex() bool { return s.colName != "" }
- func (s *createIndexStmt) String() string {
- u := ""
- if s.unique {
- u = "UNIQUE "
- }
- e := ""
- if s.ifNotExists {
- e = "IF NOT EXISTS "
- }
- expr := s.colName
- if !s.isSimpleIndex() {
- var a []string
- for _, v := range s.exprList {
- a = append(a, v.String())
- }
- expr = strings.Join(a, ", ")
- }
- return fmt.Sprintf("CREATE %sINDEX %s%s ON %s (%s);", u, e, s.indexName, s.tableName, expr)
- }
- func (s *createIndexStmt) exec(ctx *execCtx) (Recordset, error) {
- root := ctx.db.root
- if t, i := root.findIndexByName(s.indexName); i != nil {
- if s.ifNotExists {
- return nil, nil
- }
- return nil, fmt.Errorf("CREATE INDEX: table %s already has an index named %s", t.name, s.indexName)
- }
- if root.tables[s.indexName] != nil {
- return nil, fmt.Errorf("CREATE INDEX: index name collision with existing table: %s", s.indexName)
- }
- t, ok := root.tables[s.tableName]
- if !ok {
- return nil, fmt.Errorf("CREATE INDEX: table does not exist %s", s.tableName)
- }
- if findCol(t.cols, s.indexName) != nil {
- return nil, fmt.Errorf("CREATE INDEX: index name collision with existing column: %s", s.indexName)
- }
- var h int64
- var err error
- switch {
- case s.isSimpleIndex():
- colIndex := -1
- if s.colName != "id()" {
- c := findCol(t.cols, s.colName)
- if c == nil {
- return nil, fmt.Errorf("CREATE INDEX: column does not exist: %s", s.colName)
- }
- colIndex = c.index
- }
- if h, err = t.addIndex(s.unique, s.indexName, colIndex); err != nil {
- return nil, fmt.Errorf("CREATE INDEX: %v", err)
- }
- if err = t.updated(); err != nil {
- return nil, err
- }
- default:
- for _, e := range s.exprList {
- m := mentionedColumns(e)
- for colName := range m {
- c := findCol(t.cols, colName)
- if c == nil {
- return nil, fmt.Errorf("CREATE INDEX: column does not exist: %s", colName)
- }
- }
- }
- if h, err = t.addIndex2(ctx, s.unique, s.indexName, s.exprList); err != nil {
- return nil, fmt.Errorf("CREATE INDEX: %v", err)
- }
- }
- switch ctx.db.hasIndex2 {
- case 0:
- if err := ctx.db.createIndex2(); err != nil {
- return nil, err
- }
- if s.isSimpleIndex() {
- return nil, nil
- }
- case 1:
- return nil, nil
- case 2:
- if s.isSimpleIndex() {
- return nil, ctx.db.insertIndex2(s.tableName, s.indexName, []string{s.colName}, s.unique, true, h)
- }
- default:
- panic("internal error 011")
- }
- exprList := make([]string, 0, len(s.exprList))
- for _, e := range s.exprList {
- exprList = append(exprList, e.String())
- }
- return nil, ctx.db.insertIndex2(s.tableName, s.indexName, exprList, s.unique, false, h)
- }
- func (s *createIndexStmt) isUpdating() bool { return true }
- type createTableStmt struct {
- ifNotExists bool
- tableName string
- cols []*col
- }
- func (s *createTableStmt) explain(ctx *execCtx, w strutil.Formatter) {
- w.Format("%s\n", s)
- }
- func (s *createTableStmt) String() string {
- a := make([]string, len(s.cols))
- for i, v := range s.cols {
- var c, d string
- if x := v.constraint; x != nil {
- switch e := x.expr; {
- case e != nil:
- c = " " + e.String()
- default:
- c = " NOT NULL"
- }
- }
- if x := v.dflt; x != nil {
- d = " DEFAULT " + x.String()
- }
- a[i] = fmt.Sprintf("%s %s%s%s", v.name, typeStr(v.typ), c, d)
- }
- e := ""
- if s.ifNotExists {
- e = "IF NOT EXISTS "
- }
- return fmt.Sprintf("CREATE TABLE %s%s (%s);", e, s.tableName, strings.Join(a, ", "))
- }
- func (s *createTableStmt) exec(ctx *execCtx) (_ Recordset, err error) {
- var cols []*col
- for _, v := range s.cols {
- cols = append(cols, v.clone())
- }
- root := ctx.db.root
- if _, ok := root.tables[s.tableName]; ok {
- if s.ifNotExists {
- return nil, nil
- }
- return nil, fmt.Errorf("CREATE TABLE: table exists %s", s.tableName)
- }
- if t, x := root.findIndexByName(s.tableName); x != nil {
- return nil, fmt.Errorf("CREATE TABLE: table %s has index %s", t.name, s.tableName)
- }
- m := map[string]bool{}
- mustCreateColumn2 := true
- for i, c := range cols {
- nm := c.name
- if m[nm] {
- return nil, fmt.Errorf("CREATE TABLE: duplicate column %s", nm)
- }
- m[nm] = true
- c.index = i
- if c.constraint != nil || c.dflt != nil {
- if mustCreateColumn2 {
- for _, stmt := range createColumn2.l {
- _, err := stmt.exec(&execCtx{db: ctx.db})
- if err != nil {
- return nil, err
- }
- }
- }
- mustCreateColumn2 = false
- notNull := c.constraint != nil && c.constraint.expr == nil
- var co, d string
- if c.constraint != nil && c.constraint.expr != nil {
- co = c.constraint.expr.String()
- }
- if e := c.dflt; e != nil {
- d = e.String()
- }
- if _, err := insertColumn2.l[0].exec(&execCtx{db: ctx.db, arg: []interface{}{s.tableName, c.name, notNull, co, d}}); err != nil {
- return nil, err
- }
- }
- }
- t, err := root.createTable(s.tableName, cols)
- if err != nil {
- return nil, err
- }
- return nil, t.constraintsAndDefaults(ctx)
- }
- func (s *createTableStmt) isUpdating() bool { return true }
|