// query initializes a planNode from a SQL statement string. This // should not be used directly; queryRow() and exec() below should be // used instead. func (p *planner) query(sql string, args ...interface{}) (planNode, error) { stmt, err := parser.ParseOneTraditional(sql) if err != nil { return nil, err } golangFillQueryArguments(p.semaCtx.Placeholders, args) return p.makePlan(stmt, false) }
func (p *planner) query(sql string, args ...interface{}) (planNode, *roachpb.Error) { stmt, err := parser.ParseOneTraditional(sql) if err != nil { return nil, roachpb.NewError(err) } if err := parser.FillArgs(stmt, golangParameters(args)); err != nil { return nil, roachpb.NewError(err) } return p.makePlan(stmt, false) }
func initVirtualTableDesc(t virtualSchemaTable) *sqlbase.TableDescriptor { stmt, err := parser.ParseOneTraditional(t.schema) if err != nil { panic(err) } desc, err := MakeTableDesc(stmt.(*parser.CreateTable), 0) if err != nil { panic(err) } desc.ID = keys.VirtualDescriptorID desc.Privileges = emptyPrivileges return &desc }
func TestPrimaryKeyUnspecified(t *testing.T) { defer leaktest.AfterTest(t)() stmt, err := parser.ParseOneTraditional( "CREATE TABLE foo.test (a INT, b INT, CONSTRAINT c UNIQUE (b))") if err != nil { t.Fatal(err) } create := stmt.(*parser.CreateTable) desc, err := MakeTableDesc(create, 1) if err != nil { t.Fatal(err) } err = desc.AllocateIDs() if !testutils.IsError(err, sqlbase.ErrMissingPrimaryKey.Error()) { t.Fatalf("unexpected error: %s", err) } }
func TestPrimaryKeyUnspecified(t *testing.T) { defer leaktest.AfterTest(t) stmt, err := parser.ParseOneTraditional( "CREATE TABLE foo.test (a INT, b INT, CONSTRAINT c UNIQUE (b))") if err != nil { t.Fatal(err) } create := stmt.(*parser.CreateTable) if err := create.Table.NormalizeTableName(""); err != nil { t.Fatal(err) } desc, err := makeTableDesc(create, 1) if err != nil { t.Fatal(err) } if err := desc.AllocateIDs(); err != errMissingPrimaryKey { t.Fatal(err) } }
func TestMakeDatabaseDesc(t *testing.T) { defer leaktest.AfterTest(t)() stmt, err := parser.ParseOneTraditional("CREATE DATABASE test") if err != nil { t.Fatal(err) } desc := makeDatabaseDesc(stmt.(*parser.CreateDatabase)) if desc.Name != "test" { t.Fatalf("expected Name == test, got %s", desc.Name) } // ID is not set yet. if desc.ID != 0 { t.Fatalf("expected ID == 0, got %d", desc.ID) } if len(desc.GetPrivileges().Users) != 1 { t.Fatalf("wrong number of privilege users, expected 1, got: %d", len(desc.GetPrivileges().Users)) } }
// Prepare returns the result types of the given statement. Args may be a // partially populated val args map. Prepare will populate the missing val // args. The column result types are returned (or nil if there are no results). func (e *Executor) Prepare(user string, query string, args parser.MapArgs) ([]ResultColumn, *roachpb.Error) { stmt, err := parser.ParseOneTraditional(query) if err != nil { return nil, roachpb.NewError(err) } planMaker := plannerPool.Get().(*planner) defer plannerPool.Put(planMaker) cfg, cache := e.getSystemConfig() *planMaker = planner{ user: user, evalCtx: parser.EvalContext{ NodeID: e.nodeID, ReCache: e.reCache, // Copy existing GetLocation closure. See plannerPool.New() for the // initial setting. GetLocation: planMaker.evalCtx.GetLocation, Args: args, }, leaseMgr: e.leaseMgr, systemConfig: cfg, databaseCache: cache, } timestamp := time.Now() txn := client.NewTxn(e.db) planMaker.setTxn(txn, timestamp) planMaker.evalCtx.StmtTimestamp = parser.DTimestamp{Time: timestamp} plan, pErr := planMaker.prepare(stmt) if pErr != nil { return nil, pErr } if plan == nil { return nil, nil } cols := plan.Columns() for _, c := range cols { if err := checkResultDatum(c.Typ); err != nil { return nil, roachpb.NewError(err) } } return cols, nil }
func createTableDescriptor(id, parentID ID, schema string, privileges *PrivilegeDescriptor) TableDescriptor { stmt, err := parser.ParseOneTraditional(schema) if err != nil { log.Fatal(err) } desc, pErr := makeTableDesc(stmt.(*parser.CreateTable), parentID) if pErr != nil { log.Fatal(pErr) } desc.Privileges = privileges desc.ID = id if err := desc.AllocateIDs(); err != nil { log.Fatalf("%s: %v", desc.Name, err) } return desc }
func TestPrimaryKeyUnspecified(t *testing.T) { defer leaktest.AfterTest(t) stmt, err := parser.ParseOneTraditional( "CREATE TABLE foo.test (a INT, b INT, CONSTRAINT c UNIQUE (b))") if err != nil { t.Fatal(err) } create := stmt.(*parser.CreateTable) if err := create.Table.NormalizeTableName(""); err != nil { t.Fatal(err) } desc, pErr := makeTableDesc(create, 1) if pErr != nil { t.Fatal(pErr) } pErr = desc.AllocateIDs() if !testutils.IsError(pErr.GoError(), errMissingPrimaryKey.Error()) { t.Fatalf("unexpected error: %s", pErr) } }
func TestMakeTableDescColumns(t *testing.T) { defer leaktest.AfterTest(t)() testData := []struct { sqlType string colType ColumnType nullable bool }{ { "BIT(1)", ColumnType{Kind: ColumnType_INT, Width: 1}, true, }, { "BOOLEAN", ColumnType{Kind: ColumnType_BOOL}, true, }, { "INT", ColumnType{Kind: ColumnType_INT}, true, }, { "FLOAT(3)", ColumnType{Kind: ColumnType_FLOAT, Precision: 3}, true, }, { "DECIMAL(6,5)", ColumnType{Kind: ColumnType_DECIMAL, Precision: 6, Width: 5}, true, }, { "DATE", ColumnType{Kind: ColumnType_DATE}, true, }, { "TIMESTAMP", ColumnType{Kind: ColumnType_TIMESTAMP}, true, }, { "INTERVAL", ColumnType{Kind: ColumnType_INTERVAL}, true, }, { "CHAR", ColumnType{Kind: ColumnType_STRING}, true, }, { "TEXT", ColumnType{Kind: ColumnType_STRING}, true, }, { "BLOB", ColumnType{Kind: ColumnType_BYTES}, true, }, { "INT NOT NULL", ColumnType{Kind: ColumnType_INT}, false, }, { "INT NULL", ColumnType{Kind: ColumnType_INT}, true, }, } for i, d := range testData { stmt, err := parser.ParseOneTraditional( "CREATE TABLE foo.test (a " + d.sqlType + " PRIMARY KEY, b " + d.sqlType + ")") if err != nil { t.Fatalf("%d: %v", i, err) } create := stmt.(*parser.CreateTable) if err := create.Table.NormalizeTableName(""); err != nil { t.Fatalf("%d: %v", i, err) } schema, pErr := makeTableDesc(create, 1) if pErr != nil { t.Fatalf("%d: %v", i, pErr) } if !reflect.DeepEqual(d.colType, schema.Columns[0].Type) { t.Fatalf("%d: expected %+v, but got %+v", i, d.colType, schema.Columns[0]) } if schema.Columns[0].Nullable { t.Fatalf("%d: expected non-nullable primary key, but got %+v", i, schema.Columns[0].Nullable) } if !reflect.DeepEqual(d.colType, schema.Columns[1].Type) { t.Fatalf("%d: expected %+v, but got %+v", i, d.colType, schema.Columns[1]) } if d.nullable != schema.Columns[1].Nullable { t.Fatalf("%d: expected %+v, but got %+v", i, d.nullable, schema.Columns[1].Nullable) } } }
func TestMakeTableDescIndexes(t *testing.T) { defer leaktest.AfterTest(t)() testData := []struct { sql string primary IndexDescriptor indexes []IndexDescriptor }{ { "a INT PRIMARY KEY", IndexDescriptor{ Name: PrimaryKeyIndexName, Unique: true, ColumnNames: []string{"a"}, ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, }, []IndexDescriptor{}, }, { "a INT UNIQUE, b INT PRIMARY KEY", IndexDescriptor{ Name: "primary", Unique: true, ColumnNames: []string{"b"}, ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, }, []IndexDescriptor{ { Name: "", Unique: true, ColumnNames: []string{"a"}, ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, }, }, }, { "a INT, b INT, CONSTRAINT c PRIMARY KEY (a, b)", IndexDescriptor{ Name: "c", Unique: true, ColumnNames: []string{"a", "b"}, ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC}, }, []IndexDescriptor{}, }, { "a INT, b INT, CONSTRAINT c UNIQUE (b), PRIMARY KEY (a, b)", IndexDescriptor{ Name: "primary", Unique: true, ColumnNames: []string{"a", "b"}, ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC}, }, []IndexDescriptor{ { Name: "c", Unique: true, ColumnNames: []string{"b"}, ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC}, }, }, }, { "a INT, b INT, PRIMARY KEY (a, b)", IndexDescriptor{ Name: PrimaryKeyIndexName, Unique: true, ColumnNames: []string{"a", "b"}, ColumnDirections: []IndexDescriptor_Direction{IndexDescriptor_ASC, IndexDescriptor_ASC}, }, []IndexDescriptor{}, }, } for i, d := range testData { stmt, err := parser.ParseOneTraditional("CREATE TABLE foo.test (" + d.sql + ")") if err != nil { t.Fatalf("%d: %v", i, err) } create := stmt.(*parser.CreateTable) if err := create.Table.NormalizeTableName(""); err != nil { t.Fatalf("%d: %v", i, err) } schema, pErr := makeTableDesc(create, 1) if err != nil { t.Fatalf("%d: %v", i, pErr) } if !reflect.DeepEqual(d.primary, schema.PrimaryIndex) { t.Fatalf("%d: expected %+v, but got %+v", i, d.primary, schema.PrimaryIndex) } if !reflect.DeepEqual(d.indexes, append([]IndexDescriptor{}, schema.Indexes...)) { t.Fatalf("%d: expected %+v, but got %+v", i, d.indexes, schema.Indexes) } } }
func (c *v3Conn) handleParse(buf *readBuffer) error { name, err := buf.getString() if err != nil { return err } // The unnamed prepared statement can be freely overwritten. if name != "" { if _, ok := c.preparedStatements[name]; ok { return c.sendError(fmt.Sprintf("prepared statement %q already exists", name)) } } query, err := buf.getString() if err != nil { return err } numParamTypes, err := buf.getInt16() if err != nil { return err } inTypeHints := make([]oid.Oid, numParamTypes) for i := range inTypeHints { typ, err := buf.getInt32() if err != nil { return err } inTypeHints[i] = oid.Oid(typ) } stmt, err := parser.ParseOneTraditional(query) if err != nil { return c.sendError(err.Error()) } args := make(parser.MapArgs) for i, t := range inTypeHints { if t == 0 { continue } v, ok := oidToDatum[t] if !ok { return c.sendError(fmt.Sprintf("unknown oid type: %v", t)) } args[fmt.Sprint(i+1)] = v } if err := parser.InferArgs(stmt, args); err != nil { return c.sendError(err.Error()) } pq := preparedStatement{ query: query, inTypes: make([]oid.Oid, len(args)), portalNames: make(map[string]struct{}), } copy(pq.inTypes, inTypeHints) for k, v := range args { i, err := strconv.Atoi(k) if err != nil { return c.sendError(fmt.Sprintf("non-integer parameter name: %s", k)) } // OID to Datum is not a 1-1 mapping (for example, int4 and int8 both map // to DummyInt), so we need to maintain the types sent by the client. if pq.inTypes[i-1] != 0 { continue } id, ok := datumToOid[v] if !ok { return c.sendError(fmt.Sprintf("unknown datum type: %s", v.Type())) } pq.inTypes[i-1] = id } cols, pErr := c.executor.StatementResult(c.opts.user, stmt, args) if pErr != nil { return c.sendError(pErr.GoError().Error()) } pq.columns = cols c.preparedStatements[name] = pq c.writeBuf.initMsg(serverMsgParseComplete) return c.writeBuf.finishMsg(c.wr) }