// CreateTransaction saves the metadata of a 2pc transaction as Prepared. func (tpc *TwoPC) CreateTransaction(ctx context.Context, conn *TxConnection, dtid string, participants []*querypb.Target) error { bindVars := map[string]interface{}{ "dtid": dtid, "cur_time": int64(time.Now().UnixNano()), } _, err := tpc.exec(ctx, conn, tpc.insertTransaction, bindVars) if err != nil { return err } rows := make([][]sqltypes.Value, len(participants)) for i, participant := range participants { rows[i] = []sqltypes.Value{ sqltypes.MakeTrusted(sqltypes.VarBinary, []byte(dtid)), sqltypes.MakeTrusted(sqltypes.Int64, strconv.AppendInt(nil, int64(i+1), 10)), sqltypes.MakeTrusted(sqltypes.VarBinary, []byte(participant.Keyspace)), sqltypes.MakeTrusted(sqltypes.VarBinary, []byte(participant.Shard)), } } bindVars = map[string]interface{}{ "vals": rows, } _, err = tpc.exec(ctx, conn, tpc.insertParticipants, bindVars) return err }
func TestCodexResolveListArg(t *testing.T) { testUtils := newTestUtils() tableInfo := createTableInfo("Table", []string{"pk1", "pk2", "col1"}, []querypb.Type{sqltypes.Int64, sqltypes.VarBinary, sqltypes.Int32}, []string{"pk1", "pk2"}) key := "var" bindVariables := make(map[string]interface{}) bindVariables[key] = []interface{}{fmt.Errorf("error is not supported")} _, err := resolveListArg(tableInfo.GetPKColumn(0), "::"+key, bindVariables) testUtils.checkTabletError(t, err, ErrFail, "") // This should successfully convert. bindVariables[key] = []interface{}{"1"} v, err := resolveListArg(tableInfo.GetPKColumn(0), "::"+key, bindVariables) if err != nil { t.Error(err) } wantV := []sqltypes.Value{sqltypes.MakeTrusted(sqltypes.Int64, []byte("1"))} if !reflect.DeepEqual(v, wantV) { t.Errorf("resolvePKValues: %#v, want %#v", v, wantV) } bindVariables[key] = []interface{}{10} result, err := resolveListArg(tableInfo.GetPKColumn(0), "::"+key, bindVariables) if err != nil { t.Fatalf("should not get an error, but got error: %v", err) } testUtils.checkEqual(t, []sqltypes.Value{sqltypes.MakeTrusted(sqltypes.Int64, []byte("10"))}, result) }
func TestMiscTypes(t *testing.T) { client := framework.NewClient() defer client.Execute("delete from vitess_misc", nil) _, err := client.Execute( "insert into vitess_misc values(:id, :b, :d, :dt, :t)", map[string]interface{}{ "id": 1, "b": "\x01", "d": "2012-01-01", "dt": "2012-01-01 15:45:45", "t": "15:45:45", }, ) if err != nil { t.Error(err) return } qr, err := client.Execute("select * from vitess_misc where id = 1", nil) if err != nil { t.Error(err) return } want := sqltypes.Result{ Fields: []*querypb.Field{ { Name: "id", Type: sqltypes.Int32, }, { Name: "b", Type: sqltypes.Bit, }, { Name: "d", Type: sqltypes.Date, }, { Name: "dt", Type: sqltypes.Datetime, }, { Name: "t", Type: sqltypes.Time, }, }, RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Bit, []byte("\x01")), sqltypes.MakeTrusted(sqltypes.Date, []byte("2012-01-01")), sqltypes.MakeTrusted(sqltypes.Datetime, []byte("2012-01-01 15:45:45")), sqltypes.MakeTrusted(sqltypes.Time, []byte("15:45:45")), }, }, } if !reflect.DeepEqual(*qr, want) { t.Errorf("Execute: \n%#v, want \n%#v", *qr, want) } }
func TestFractionals(t *testing.T) { client := framework.NewClient() defer client.Execute("delete from vitess_fracts", nil) _, err := client.Execute( "insert into vitess_fracts values(:id, :deci, :num, :f, :d)", map[string]interface{}{ "id": 1, "deci": "1.99", "num": "2.99", "f": 3.99, "d": 4.99, }, ) if err != nil { t.Error(err) return } qr, err := client.Execute("select * from vitess_fracts where id = 1", nil) if err != nil { t.Error(err) return } want := sqltypes.Result{ Fields: []*querypb.Field{ { Name: "id", Type: sqltypes.Int32, }, { Name: "deci", Type: sqltypes.Decimal, }, { Name: "num", Type: sqltypes.Decimal, }, { Name: "f", Type: sqltypes.Float32, }, { Name: "d", Type: sqltypes.Float64, }, }, RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Decimal, []byte("1.99")), sqltypes.MakeTrusted(sqltypes.Decimal, []byte("2.99")), sqltypes.MakeTrusted(sqltypes.Float32, []byte("3.99")), sqltypes.MakeTrusted(sqltypes.Float64, []byte("4.99")), }, }, } if !reflect.DeepEqual(*qr, want) { t.Errorf("Execute: \n%#v, want \n%#v", *qr, want) } }
func createTestTableUpdatedStats(tableName string) []sqltypes.Value { return []sqltypes.Value{ sqltypes.MakeString([]byte(tableName)), sqltypes.MakeString([]byte("USER TABLE")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("0")), sqltypes.MakeString([]byte("")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("4")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("5")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("6")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("7")), } }
func createTestTableBaseShowTable(tableName string) []sqltypes.Value { return []sqltypes.Value{ sqltypes.MakeString([]byte(tableName)), sqltypes.MakeString([]byte("USER TABLE")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("1427325875")), sqltypes.MakeString([]byte("")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("2")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("3")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("4")), } }
func TestCodexBuildKey(t *testing.T) { testUtils := newTestUtils() newKey := buildKey([]sqltypes.Value{ sqltypes.MakeTrusted(sqltypes.Int64, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int64, []byte("2")), }) testUtils.checkEqual(t, "1.2", newKey) newKey = buildKey([]sqltypes.Value{ sqltypes.MakeString([]byte("a")), sqltypes.NULL, }) testUtils.checkEqual(t, "", newKey) }
func TestDBAStatements(t *testing.T) { client := framework.NewClient() qr, err := client.Execute("show variables like 'version'", nil) if err != nil { t.Error(err) return } wantCol := sqltypes.MakeTrusted(sqltypes.VarChar, []byte("version")) if !reflect.DeepEqual(qr.Rows[0][0], wantCol) { t.Errorf("Execute: \n%#v, want \n%#v", qr.Rows[0][0], wantCol) } qr, err = client.Execute("describe vitess_a", nil) if err != nil { t.Error(err) return } if qr.RowsAffected != 4 { t.Errorf("RowsAffected: %d, want 4", qr.RowsAffected) } qr, err = client.Execute("explain vitess_a", nil) if err != nil { t.Error(err) return } if qr.RowsAffected != 4 { t.Errorf("RowsAffected: %d, want 4", qr.RowsAffected) } }
func TestQueryExecutorPlanDmlSubQuery(t *testing.T) { db := setUpQueryExecutorTest() query := "update test_table set addr = 3 where name = 1 limit 1000" expandedQuery := "select pk from test_table where name = 1 limit 1000 for update" want := &sqltypes.Result{} db.AddQuery(query, want) db.AddQuery(expandedQuery, &sqltypes.Result{ RowsAffected: 1, Rows: [][]sqltypes.Value{ {sqltypes.MakeTrusted(sqltypes.Int32, []byte("2"))}, }, }) updateQuery := "update test_table set addr = 3 where pk in (2) /* _stream test_table (pk ) (2 ); */" db.AddQuery(updateQuery, want) ctx := context.Background() tsv := newTestTabletServer(ctx, enableStrict, db) txid := newTransaction(tsv) qre := newTestQueryExecutor(ctx, tsv, query, txid) defer tsv.StopService() defer testCommitHelper(t, tsv, qre) checkPlanID(t, planbuilder.PlanDMLSubquery, qre.plan.PlanID) got, err := qre.Execute() if err != nil { t.Fatalf("qre.Execute() = %v, want nil", err) } if !reflect.DeepEqual(got, want) { t.Fatalf("got: %v, want: %v", got, want) } wantqueries := []string{updateQuery} gotqueries := fetchRecordedQueries(qre) if !reflect.DeepEqual(gotqueries, wantqueries) { t.Errorf("queries: %v, want %v", gotqueries, wantqueries) } }
func TestLookupHashAutoMapBadData(t *testing.T) { result := &sqltypes.Result{ Fields: []*querypb.Field{{ Type: sqltypes.Float64, }}, Rows: [][]sqltypes.Value{ []sqltypes.Value{ sqltypes.MakeTrusted(sqltypes.Float64, []byte("1.1")), }, }, RowsAffected: 1, } vc := &vcursor{result: result} _, err := lha.(planbuilder.NonUnique).Map(vc, []interface{}{1, int32(2)}) want := "unexpected type" if err == nil || !strings.Contains(err.Error(), want) { t.Errorf("lha.Map: %v, must contain %v", err, want) } result.Fields = []*querypb.Field{{ Type: sqltypes.Float32, }} vc = &vcursor{result: result} _, err = lha.(planbuilder.NonUnique).Map(vc, []interface{}{1, int32(2)}) want = `lookup.Map: unexpected type for 1.1: float64` if err == nil || err.Error() != want { t.Errorf("lha.Map: %v, want %v", err, want) } }
func (vc *vcursor) Execute(query *querytypes.BoundQuery) (*sqltypes.Result, error) { vc.query = query if vc.mustFail { return nil, errors.New("execute failed") } switch { case strings.HasPrefix(query.Sql, "select"): if vc.result != nil { return vc.result, nil } result := &sqltypes.Result{ Fields: []*querypb.Field{{ Type: sqltypes.Int32, }}, RowsAffected: uint64(vc.numRows), } for i := 0; i < vc.numRows; i++ { result.Rows = append(result.Rows, []sqltypes.Value{ sqltypes.MakeTrusted(sqltypes.Int64, []byte(fmt.Sprintf("%d", i+1))), }) } return result, nil case strings.HasPrefix(query.Sql, "insert"): return &sqltypes.Result{InsertID: 1}, nil case strings.HasPrefix(query.Sql, "delete"): return &sqltypes.Result{}, nil } panic("unexpected") }
func TestQueryExecutorPlanInsertSubQuery(t *testing.T) { db := setUpQueryExecutorTest() query := "insert into test_table(pk) select pk from test_table where pk = 1 limit 1000" want := &sqltypes.Result{ Rows: [][]sqltypes.Value{}, } db.AddQuery(query, want) selectQuery := "select pk from test_table where pk = 1 limit 1000" db.AddQuery(selectQuery, &sqltypes.Result{ RowsAffected: 1, Rows: [][]sqltypes.Value{ {sqltypes.MakeTrusted(sqltypes.Int32, []byte("2"))}, }, }) insertQuery := "insert into test_table(pk) values (2) /* _stream test_table (pk ) (2 ); */" db.AddQuery(insertQuery, &sqltypes.Result{}) ctx := context.Background() tsv := newTestTabletServer(ctx, enableRowCache|enableStrict, db) qre := newTestQueryExecutor(ctx, tsv, query, newTransaction(tsv)) defer tsv.StopService() defer testCommitHelper(t, tsv, qre) checkPlanID(t, planbuilder.PlanInsertSubquery, qre.plan.PlanID) got, err := qre.Execute() if err != nil { t.Fatalf("qre.Execute() = %v, want nil", err) } if !reflect.DeepEqual(got, want) { t.Fatalf("got: %v, want: %v", got, want) } }
// FetchNext returns the next row for a query func (conn *Connection) FetchNext() (row []sqltypes.Value, err error) { vtrow := C.vt_fetch_next(&conn.c) if vtrow.has_error != 0 { return nil, conn.lastError("") } rowPtr := (*[maxSize]*[maxSize]byte)(unsafe.Pointer(vtrow.mysql_row)) if rowPtr == nil { return nil, nil } colCount := int(conn.c.num_fields) cfields := (*[maxSize]C.MYSQL_FIELD)(unsafe.Pointer(conn.c.fields)) row = make([]sqltypes.Value, colCount) lengths := (*[maxSize]uint64)(unsafe.Pointer(vtrow.lengths)) totalLength := uint64(0) for i := 0; i < colCount; i++ { totalLength += lengths[i] } arena := make([]byte, 0, int(totalLength)) for i := 0; i < colCount; i++ { colLength := lengths[i] colPtr := rowPtr[i] if colPtr == nil { continue } start := len(arena) arena = append(arena, colPtr[:colLength]...) // MySQL values can be trusted. row[i] = sqltypes.MakeTrusted( sqltypes.MySQLToType(int64(cfields[i]._type), int64(cfields[i].flags)), arena[start:start+int(colLength)], ) } return row, nil }
func (qre *QueryExecutor) execNextval() (*sqltypes.Result, error) { t := qre.plan.TableInfo t.Seq.Lock() defer t.Seq.Unlock() if t.NextVal >= t.LastVal { _, err := qre.execAsTransaction(func(conn *TxConnection) (*sqltypes.Result, error) { query := fmt.Sprintf("select next_id, cache, increment from `%s` where id = 0 for update", qre.plan.TableName) qr, err := qre.execSQL(conn, query, false) if err != nil { return nil, err } if len(qr.Rows) != 1 { return nil, fmt.Errorf("unexpected rows from reading sequence %s (possible mis-route): %d", qre.plan.TableName, len(qr.Rows)) } nextID, err := qr.Rows[0][0].ParseInt64() if err != nil { return nil, fmt.Errorf("error loading sequence %s: %v", qre.plan.TableName, err) } cache, err := qr.Rows[0][1].ParseInt64() if err != nil { return nil, fmt.Errorf("error loading sequence %s: %v", qre.plan.TableName, err) } if cache < 1 { return nil, fmt.Errorf("invalid cache value for sequence %s: %d", qre.plan.TableName, cache) } inc, err := qr.Rows[0][2].ParseInt64() if err != nil { return nil, fmt.Errorf("error loading sequence %s: %v", qre.plan.TableName, err) } if inc < 1 { return nil, fmt.Errorf("invalid increment for sequence %s: %d", qre.plan.TableName, inc) } newLast := nextID + cache*inc query = fmt.Sprintf("update `%s` set next_id = %d where id = 0", qre.plan.TableName, newLast) conn.RecordQuery(query) _, err = qre.execSQL(conn, query, false) if err != nil { return nil, err } t.NextVal = nextID t.Increment = inc t.LastVal = newLast return nil, nil }) if err != nil { return nil, err } } ret := t.NextVal t.NextVal += t.Increment return &sqltypes.Result{ Fields: sequenceFields, Rows: [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int64, strconv.AppendInt(nil, ret, 10)), }}, RowsAffected: 1, }, nil }
func TestBinary(t *testing.T) { client := framework.NewClient() defer client.Execute("delete from vitess_test where intval in (4,5)", nil) binaryData := "\x00'\"\b\n\r\t\x1a\\\x00\x0f\xf0\xff" // Test without bindvars. _, err := client.Execute( "insert into vitess_test values "+ "(4, null, null, '\\0\\'\\\"\\b\\n\\r\\t\\Z\\\\\x00\x0f\xf0\xff')", nil, ) if err != nil { t.Error(err) return } qr, err := client.Execute("select binval from vitess_test where intval=4", nil) if err != nil { t.Error(err) return } want := sqltypes.Result{ Fields: []*querypb.Field{ { Name: "binval", Type: sqltypes.VarBinary, }, }, RowsAffected: 1, Rows: [][]sqltypes.Value{ []sqltypes.Value{ sqltypes.MakeTrusted(sqltypes.VarBinary, []byte(binaryData)), }, }, } if !reflect.DeepEqual(*qr, want) { t.Errorf("Execute: \n%#v, want \n%#v", *qr, want) } // Test with bindvars. _, err = client.Execute( "insert into vitess_test values(5, null, null, :bindata)", map[string]interface{}{"bindata": binaryData}, ) if err != nil { t.Error(err) return } qr, err = client.Execute("select binval from vitess_test where intval=5", nil) if err != nil { t.Error(err) return } if !reflect.DeepEqual(*qr, want) { t.Errorf("Execute: \n%#v, want \n%#v", *qr, want) } }
func TestMultiInsertGenerator(t *testing.T) { router, sbc, _, sbclookup := createRouterEnv() sbclookup.SetResults([]*sqltypes.Result{{ Rows: [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int64, []byte("1")), }}, RowsAffected: 1, InsertID: 1, }}) result, err := routerExec(router, "insert into user(v, name) values (2, 'myname1'), (3, 'myname2')", nil) if err != nil { t.Error(err) } wantQueries := []querytypes.BoundQuery{{ Sql: "insert into user(v, name, Id) values (2, :_name0, :_Id0), (3, :_name1, :_Id1) /* vtgate:: keyspace_id:166b40b44aba4bd6 */", BindVariables: map[string]interface{}{ "_Id0": int64(1), "__seq0": int64(1), "_name0": []byte("myname1"), "_Id1": int64(1), "__seq1": int64(1), "_name1": []byte("myname2"), }, }} if !reflect.DeepEqual(sbc.Queries, wantQueries) { t.Errorf("sbc.Queries: %+v, want %+v\n", sbc.Queries, wantQueries) } wantQueries = []querytypes.BoundQuery{{ Sql: "select next value from `user_seq`", BindVariables: map[string]interface{}{}, }, { Sql: "insert into name_user_map(name, user_id) values (:name, :user_id)", BindVariables: map[string]interface{}{ "name": []byte("myname1"), "user_id": int64(1), }, }, { Sql: "select next value from `user_seq`", BindVariables: map[string]interface{}{}, }, { Sql: "insert into name_user_map(name, user_id) values (:name, :user_id)", BindVariables: map[string]interface{}{ "name": []byte("myname2"), "user_id": int64(1), }, }} if !reflect.DeepEqual(sbclookup.Queries, wantQueries) { t.Errorf("sbclookup.Queries: \n%#v, want \n%#v\n", sbclookup.Queries, wantQueries) } wantResult := *sandboxconn.SingleRowResult wantResult.InsertID = 1 if !reflect.DeepEqual(result, &wantResult) { t.Errorf("result: %+v, want %+v", result, &wantResult) } }
// TODO(erez): Rename to TestTabletServerSplitQuery once migration to SplitQuery is done. func TestTabletServerSplitQueryV2(t *testing.T) { db := setUpTabletServerTest() db.AddQuery("SELECT MIN(pk), MAX(pk) FROM test_table", &sqltypes.Result{ Fields: []*querypb.Field{ {Name: "pk", Type: sqltypes.Int32}, }, RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("100")), }, }, }) testUtils := newTestUtils() config := testUtils.newQueryServiceConfig() tsv := NewTabletServer(config) dbconfigs := testUtils.newDBConfigs(db) target := querypb.Target{TabletType: topodatapb.TabletType_RDONLY} err := tsv.StartService(target, dbconfigs, testUtils.newMysqld(&dbconfigs)) if err != nil { t.Fatalf("StartService failed: %v", err) } defer tsv.StopService() ctx := context.Background() sql := "select * from test_table where count > :count" splits, err := tsv.SplitQueryV2( ctx, &querypb.Target{TabletType: topodatapb.TabletType_RDONLY}, sql, nil, /* bindVariables */ []string{}, /* splitColumns */ 10, /* splitCount */ 0, /* numRowsPerQueryPart */ querypb.SplitQueryRequest_EQUAL_SPLITS) if err != nil { t.Fatalf("TabletServer.SplitQuery should succeed: %v, but get error: %v", sql, err) } if len(splits) != 10 { t.Fatalf("got: %v, want: %v.\nsplits: %+v", len(splits), 10, splits) } }
func TestLeftJoinStream(t *testing.T) { router, sbc1, sbc2, _ := createRouterEnv() result1 := []*sqltypes.Result{{ Fields: []*querypb.Field{ {"id", sqltypes.Int32}, {"col", sqltypes.Int32}, }, RowsAffected: 1, InsertID: 0, Rows: [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("3")), }}, }} emptyResult := []*sqltypes.Result{{ Fields: []*querypb.Field{ {"id", sqltypes.Int32}, }, }} sbc1.setResults(result1) sbc2.setResults(emptyResult) result, err := routerStream(router, "select u1.id, u2.id from user u1 left join user u2 on u2.id = u1.col where u1.id = 1") if err != nil { t.Error(err) } wantResult := &sqltypes.Result{ Fields: []*querypb.Field{ singleRowResult.Fields[0], singleRowResult.Fields[0], }, Rows: [][]sqltypes.Value{ { singleRowResult.Rows[0][0], {}, }, }, RowsAffected: 0, } if !reflect.DeepEqual(result, wantResult) { t.Errorf("result: %+v, want %+v", result, wantResult) } }
// DeleteRedo deletes the redo log for the dtid. func (tpc *TwoPC) DeleteRedo(ctx context.Context, conn *TxConnection, dtid string) error { bindVars := map[string]interface{}{ "dtid": sqltypes.MakeTrusted(sqltypes.VarBinary, []byte(dtid)), } _, err := tpc.exec(ctx, conn, tpc.deleteRedoTx, bindVars) if err != nil { return err } _, err = tpc.exec(ctx, conn, tpc.deleteRedoStmt, bindVars) return err }
func TestTabletServerSplitQuery(t *testing.T) { db := setUpTabletServerTest() db.AddQuery("SELECT MIN(pk), MAX(pk) FROM test_table", &sqltypes.Result{ Fields: []*querypb.Field{ {Name: "pk", Type: sqltypes.Int32}, }, RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("100")), }, }, }) db.AddQuery("SELECT pk FROM test_table LIMIT 0", &sqltypes.Result{ Fields: []*querypb.Field{ {Name: "pk", Type: sqltypes.Int32}, }, RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), }, }, }) testUtils := newTestUtils() config := testUtils.newQueryServiceConfig() tsv := NewTabletServer(config) dbconfigs := testUtils.newDBConfigs(db) target := querypb.Target{TabletType: topodatapb.TabletType_MASTER} err := tsv.StartService(target, dbconfigs, testUtils.newMysqld(&dbconfigs)) if err != nil { t.Fatalf("StartService failed: %v", err) } defer tsv.StopService() ctx := context.Background() sql := "select * from test_table where count > :count" if _, err := tsv.SplitQuery(ctx, &target, sql, nil, "", 10); err != nil { t.Fatalf("TabletServer.SplitQuery should success: %v, but get error: %v", sql, err) } }
func TestSequence(t *testing.T) { want := sqltypes.Result{ Fields: []*querypb.Field{{ Name: "nextval", Type: sqltypes.Int64, }}, RowsAffected: 1, Rows: [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int64, []byte("0")), }}, } for wantval := int64(1); wantval < 10; wantval += 2 { want.Rows[0][0] = sqltypes.MakeTrusted(sqltypes.Int64, strconv.AppendInt(nil, wantval, 10)) qr, err := framework.NewClient().Execute("select next value from vitess_seq", nil) if err != nil { t.Error(err) return } if !reflect.DeepEqual(*qr, want) { t.Errorf("Execute: \n%#v, want \n%#v", *qr, want) } } // Verify that the table got updated according to chunk size. want = sqltypes.Result{ RowsAffected: 1, Rows: [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int64, []byte("13")), sqltypes.MakeTrusted(sqltypes.Int64, []byte("3")), sqltypes.MakeTrusted(sqltypes.Int64, []byte("2")), }}, } qr, err := framework.NewClient().Execute("select next_id, cache, increment from vitess_seq", nil) if err != nil { t.Error(err) return } qr.Fields = nil if !reflect.DeepEqual(*qr, want) { t.Errorf("Execute: \n%#v, want \n%#v", *qr, want) } }
func TestSQLValue(t *testing.T) { val := sqltypes.MakeTrusted(sqltypes.VarBinary, []byte("Test")) got, err := binVindex.(Unique).Map(nil, []interface{}{val}) if err != nil { t.Error(err) } out := string(got[0]) want := "\f\xbcf\x11\xf5T\vЀ\x9a8\x8d\xc9Za[" if out != want { t.Errorf("Map(%#v): %#v, want %#v", val, out, want) } }
func TestBatchRead(t *testing.T) { client := framework.NewClient() queries := []querytypes.BoundQuery{{ Sql: "select * from vitess_a where id = :a", BindVariables: map[string]interface{}{"a": 2}, }, { Sql: "select * from vitess_b where id = :b", BindVariables: map[string]interface{}{"b": 2}, }} qr1 := sqltypes.Result{ Fields: []*querypb.Field{{ Name: "eid", Type: sqltypes.Int64, }, { Name: "id", Type: sqltypes.Int32, }, { Name: "name", Type: sqltypes.VarChar, }, { Name: "foo", Type: sqltypes.VarBinary, }}, RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int64, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("2")), sqltypes.MakeTrusted(sqltypes.VarChar, []byte("bcde")), sqltypes.MakeTrusted(sqltypes.VarBinary, []byte("fghi")), }, }, } qr2 := sqltypes.Result{ Fields: []*querypb.Field{{ Name: "eid", Type: sqltypes.Int64, }, { Name: "id", Type: sqltypes.Int32, }}, RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int64, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("2")), }, }, } want := []sqltypes.Result{qr1, qr2} qrl, err := client.ExecuteBatch(queries, false) if err != nil { t.Error(err) return } if !reflect.DeepEqual(qrl, want) { t.Errorf("ExecueBatch: \n%#v, want \n%#v", qrl, want) } }
func TestQueryExecutorPlanPKIn(t *testing.T) { db := setUpQueryExecutorTest() query := "select * from test_table where pk in (1, 2, 3) limit 1000" expandedQuery := "select pk, name, addr from test_table where pk in (1, 2, 3)" want := &sqltypes.Result{ Fields: getTestTableFields(), RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("20")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("30")), }, }, } db.AddQuery(query, want) db.AddQuery(expandedQuery, want) db.AddQuery("select * from test_table where 1 != 1", &sqltypes.Result{ Fields: getTestTableFields(), }) ctx := context.Background() tsv := newTestTabletServer(ctx, enableRowCache|enableSchemaOverrides|enableStrict, db) qre := newTestQueryExecutor(ctx, tsv, query, 0) defer tsv.StopService() checkPlanID(t, planbuilder.PlanPKIn, qre.plan.PlanID) got, err := qre.Execute() if err != nil { t.Fatalf("qre.Execute() = %v, want nil", err) } if !reflect.DeepEqual(got, want) { t.Fatalf("got: %v, want: %v", got, want) } cachedQuery := "select pk, name, addr from test_table where pk in (1)" db.AddQuery(cachedQuery, &sqltypes.Result{ Fields: getTestTableFields(), RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("20")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("30")), }, }, }) nonCachedQuery := "select pk, name, addr from test_table where pk in (2, 3)" db.AddQuery(nonCachedQuery, &sqltypes.Result{}) db.AddQuery(cachedQuery, want) // run again, this time pk=1 should hit the rowcache got, err = qre.Execute() if err != nil { t.Fatalf("qre.Execute() = %v, want nil", err) } if !reflect.DeepEqual(got, want) { t.Fatalf("got: %v, want: %v", got, want) } }
func TestVarJoinStream(t *testing.T) { router, sbc1, sbc2, _ := createRouterEnv() result1 := []*sqltypes.Result{{ Fields: []*querypb.Field{ {"id", sqltypes.Int32}, {"col", sqltypes.Int32}, }, RowsAffected: 1, InsertID: 0, Rows: [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int32, []byte("3")), }}, }} sbc1.setResults(result1) _, err := routerStream(router, "select u1.id, u2.id from user u1 join user u2 on u2.id = u1.col where u1.id = 1") if err != nil { t.Error(err) } wantQueries := []querytypes.BoundQuery{{ Sql: "select u1.id, u1.col from user as u1 where u1.id = 1", BindVariables: map[string]interface{}{}, }} if !reflect.DeepEqual(sbc1.Queries, wantQueries) { t.Errorf("sbc1.Queries: %+v, want %+v\n", sbc1.Queries, wantQueries) } wantQueries = []querytypes.BoundQuery{{ Sql: "select u2.id from user as u2 where u2.id = :u1_col", BindVariables: map[string]interface{}{}, }} // We have to use string representation because bindvars type is too complex. got := fmt.Sprintf("%+v", sbc2.Queries) want := "[{Sql:select u2.id from user as u2 where u2.id = :u1_col BindVariables:map[u1_col:3]}]" if got != want { t.Errorf("sbc2.Queries: %s, want %s\n", got, want) } }
// SaveRedo saves the statements in the redo log using the supplied connection. func (tpc *TwoPC) SaveRedo(ctx context.Context, conn *TxConnection, dtid string, queries []string) error { bindVars := map[string]interface{}{ "dtid": dtid, "time_created": int64(time.Now().UnixNano()), } _, err := tpc.exec(ctx, conn, tpc.insertRedoTx, bindVars) if err != nil { return err } rows := make([][]sqltypes.Value, len(queries)) for i, query := range queries { rows[i] = []sqltypes.Value{ sqltypes.MakeTrusted(sqltypes.VarBinary, []byte(dtid)), sqltypes.MakeTrusted(sqltypes.Int64, strconv.AppendInt(nil, int64(i+1), 10)), sqltypes.MakeTrusted(sqltypes.VarBinary, []byte(query)), } } bindVars = map[string]interface{}{ "vals": rows, } _, err = tpc.exec(ctx, conn, tpc.insertRedoStmt, bindVars) return err }
// TestUnorthodox is for testing syntactically invalid constructs // that we use internally for efficient SQL generation. func TestUnorthodox(t *testing.T) { query := "insert into `%s` values %a" bindVars := map[string]interface{}{ "vals": [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int64, []byte("1")), sqltypes.MakeString([]byte("foo('a')")), }, { sqltypes.MakeTrusted(sqltypes.Int64, []byte("2")), sqltypes.MakeString([]byte("bar(`b`)")), }}, } buf := NewTrackedBuffer(nil) buf.Myprintf(query, "t", ":vals") pq := buf.ParsedQuery() bytes, err := pq.GenerateQuery(bindVars) if err != nil { t.Error(err) } got := string(bytes) want := "insert into `t` values (1, 'foo(\\'a\\')'), (2, 'bar(`b`)')" if got != want { t.Errorf("GenerateQuery: %s, want %s", got, want) } }
// AddColumn adds a column to the Table. func (ta *Table) AddColumn(name string, columnType querypb.Type, defval sqltypes.Value, extra string) { index := len(ta.Columns) ta.Columns = append(ta.Columns, TableColumn{Name: strings.ToLower(name)}) ta.Columns[index].Type = columnType if extra == "auto_increment" { ta.Columns[index].IsAuto = true // Ignore default value, if any return } if defval.IsNull() { return } // Schema values are trusted. ta.Columns[index].Default = sqltypes.MakeTrusted(ta.Columns[index].Type, defval.Raw()) }
func TestQueryExecutorPlanNextval(t *testing.T) { db := setUpQueryExecutorTest() selQuery := "select next_id, cache, increment from `seq` where id = 0 for update" db.AddQuery(selQuery, &sqltypes.Result{ RowsAffected: 1, Rows: [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int64, []byte("1")), sqltypes.MakeTrusted(sqltypes.Int64, []byte("3")), sqltypes.MakeTrusted(sqltypes.Int64, []byte("2")), }}, }) updateQuery := "update `seq` set next_id = 7 where id = 0" db.AddQuery(updateQuery, &sqltypes.Result{}) ctx := context.Background() tsv := newTestTabletServer(ctx, enableRowCache|enableStrict, db) defer tsv.StopService() qre := newTestQueryExecutor(ctx, tsv, "select next value from seq", 0) checkPlanID(t, planbuilder.PlanNextval, qre.plan.PlanID) got, err := qre.Execute() if err != nil { t.Fatalf("qre.Execute() = %v, want nil", err) } want := &sqltypes.Result{ Fields: []*querypb.Field{{ Name: "nextval", Type: sqltypes.Int64, }}, RowsAffected: 1, Rows: [][]sqltypes.Value{{ sqltypes.MakeTrusted(sqltypes.Int64, []byte("1")), }}, } if !reflect.DeepEqual(got, want) { t.Fatalf("qre.Execute() =\n%#v, want:\n%#v", got, want) } }
func TestCharaterSet(t *testing.T) { qr, err := framework.NewClient().Execute("select * from vitess_test where intval=1", nil) if err != nil { t.Error(err) return } want := sqltypes.Result{ Fields: []*querypb.Field{ { Name: "intval", Type: sqltypes.Int32, }, { Name: "floatval", Type: sqltypes.Float32, }, { Name: "charval", Type: sqltypes.VarChar, }, { Name: "binval", Type: sqltypes.VarBinary, }, }, RowsAffected: 1, Rows: [][]sqltypes.Value{ { sqltypes.MakeTrusted(sqltypes.Int32, []byte("1")), sqltypes.MakeTrusted(sqltypes.Float32, []byte("1.12345")), sqltypes.MakeTrusted(sqltypes.VarChar, []byte("\xc2\xa2")), sqltypes.MakeTrusted(sqltypes.VarBinary, []byte("\x00\xff")), }, }, } if !reflect.DeepEqual(*qr, want) { t.Errorf("Execute: \n%#v, want \n%#v", *qr, want) } }