Beispiel #1
0
// 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)
}
Beispiel #2
0
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
}
Beispiel #4
0
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)
	}
}
Beispiel #5
0
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)
	}
}
Beispiel #6
0
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))
	}
}
Beispiel #7
0
// 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
}
Beispiel #8
0
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
}
Beispiel #9
0
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)
	}
}
Beispiel #10
0
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)
		}
	}
}
Beispiel #11
0
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)
		}

	}
}
Beispiel #12
0
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)
}