You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

insert_executor_test.go 22 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package at
  18. import (
  19. "context"
  20. "database/sql/driver"
  21. "reflect"
  22. "testing"
  23. "github.com/agiledragon/gomonkey/v2"
  24. "github.com/arana-db/parser/ast"
  25. "github.com/arana-db/parser/model"
  26. "github.com/arana-db/parser/test_driver"
  27. "github.com/stretchr/testify/assert"
  28. "seata.apache.org/seata-go/pkg/datasource/sql/datasource"
  29. "seata.apache.org/seata-go/pkg/datasource/sql/datasource/mysql"
  30. "seata.apache.org/seata-go/pkg/datasource/sql/exec"
  31. "seata.apache.org/seata-go/pkg/datasource/sql/parser"
  32. "seata.apache.org/seata-go/pkg/datasource/sql/types"
  33. "seata.apache.org/seata-go/pkg/datasource/sql/util"
  34. )
  35. func TestBuildSelectSQLByInsert(t *testing.T) {
  36. tests := []struct {
  37. name string
  38. query string
  39. queryArgs []driver.Value
  40. NamedValues []driver.NamedValue
  41. metaData types.TableMeta
  42. expectQuery string
  43. expectQueryArgs []driver.Value
  44. orExpectQuery string
  45. orExpectQueryArgs []driver.Value
  46. mockInsertResult mockInsertResult
  47. IncrementStep int
  48. }{
  49. {
  50. name: "test-1",
  51. query: "insert into user(id,name) values (19,'Tony'),(21,'tony')",
  52. metaData: types.TableMeta{
  53. ColumnNames: []string{"id", "name"},
  54. Indexs: map[string]types.IndexMeta{
  55. "id": {
  56. IType: types.IndexTypePrimaryKey,
  57. ColumnName: "id",
  58. Columns: []types.ColumnMeta{
  59. {
  60. ColumnName: "id",
  61. DatabaseType: types.GetSqlDataType("BIGINT"),
  62. },
  63. },
  64. },
  65. },
  66. Columns: map[string]types.ColumnMeta{
  67. "id": {
  68. ColumnName: "id",
  69. },
  70. "name": {
  71. ColumnName: "name",
  72. },
  73. },
  74. },
  75. expectQuery: "SELECT * FROM user WHERE (`id`) IN ((?),(?)) ",
  76. expectQueryArgs: []driver.Value{int64(19), int64(21)},
  77. },
  78. {
  79. name: "test-2",
  80. query: "insert into user(user_id,name) values (20,'Tony')",
  81. metaData: types.TableMeta{
  82. ColumnNames: []string{"user_id", "name"},
  83. Indexs: map[string]types.IndexMeta{
  84. "user_id": {
  85. IType: types.IndexTypePrimaryKey,
  86. ColumnName: "user_id",
  87. Columns: []types.ColumnMeta{
  88. {
  89. ColumnName: "user_id",
  90. DatabaseType: types.GetSqlDataType("BIGINT"),
  91. },
  92. },
  93. },
  94. },
  95. Columns: map[string]types.ColumnMeta{
  96. "user_id": {
  97. ColumnName: "user_id",
  98. },
  99. "name": {
  100. ColumnName: "name",
  101. },
  102. },
  103. },
  104. expectQuery: "SELECT * FROM user WHERE (`user_id`) IN ((?)) ",
  105. expectQueryArgs: []driver.Value{int64(20)},
  106. },
  107. }
  108. for _, test := range tests {
  109. t.Run(test.name, func(t *testing.T) {
  110. datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil))
  111. stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta",
  112. func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) {
  113. return &test.metaData, nil
  114. })
  115. c, err := parser.DoParser(test.query)
  116. assert.Nil(t, err)
  117. executor := NewInsertExecutor(c, &types.ExecContext{
  118. Values: test.queryArgs,
  119. NamedValues: test.NamedValues,
  120. }, []exec.SQLHook{})
  121. executor.(*insertExecutor).businesSQLResult = &test.mockInsertResult
  122. executor.(*insertExecutor).incrementStep = test.IncrementStep
  123. sql, values, err := executor.(*insertExecutor).buildAfterImageSQL(context.Background())
  124. assert.Nil(t, err)
  125. if test.orExpectQuery != "" && test.orExpectQueryArgs != nil {
  126. if test.orExpectQuery == sql {
  127. assert.Equal(t, test.orExpectQueryArgs, values)
  128. return
  129. }
  130. }
  131. assert.Equal(t, test.expectQuery, sql)
  132. assert.Equal(t, test.expectQueryArgs, util.NamedValueToValue(values))
  133. stub.Reset()
  134. })
  135. }
  136. }
  137. func TestMySQLInsertUndoLogBuilder_containsPK(t *testing.T) {
  138. type fields struct {
  139. InsertResult types.ExecResult
  140. IncrementStep int
  141. }
  142. type args struct {
  143. meta types.TableMeta
  144. parseCtx *types.ParseContext
  145. }
  146. tests := []struct {
  147. name string
  148. fields fields
  149. args args
  150. want bool
  151. }{
  152. {name: "test-true", fields: fields{}, args: args{meta: types.TableMeta{
  153. Indexs: map[string]types.IndexMeta{
  154. "id": {
  155. IType: types.IndexTypePrimaryKey,
  156. Columns: []types.ColumnMeta{{
  157. ColumnName: "id",
  158. }},
  159. },
  160. },
  161. }, parseCtx: &types.ParseContext{
  162. InsertStmt: &ast.InsertStmt{
  163. Columns: []*ast.ColumnName{{
  164. Name: model.CIStr{O: "id", L: "id"},
  165. }},
  166. },
  167. }}, want: true},
  168. {name: "test-false", fields: fields{}, args: args{meta: types.TableMeta{
  169. Indexs: map[string]types.IndexMeta{
  170. "id": {
  171. IType: types.IndexTypePrimaryKey,
  172. Columns: []types.ColumnMeta{{
  173. ColumnName: "id",
  174. }},
  175. },
  176. },
  177. }, parseCtx: &types.ParseContext{
  178. InsertStmt: &ast.InsertStmt{
  179. Columns: []*ast.ColumnName{{
  180. Name: model.CIStr{O: "name", L: "name"},
  181. }},
  182. },
  183. }}, want: false},
  184. {name: "test-false", fields: fields{}, args: args{meta: types.TableMeta{
  185. Indexs: map[string]types.IndexMeta{
  186. "id": {
  187. IType: types.IndexTypePrimaryKey,
  188. Columns: []types.ColumnMeta{{
  189. ColumnName: "id",
  190. }},
  191. },
  192. },
  193. }, parseCtx: &types.ParseContext{}}, want: false},
  194. {name: "test-false", fields: fields{}, args: args{meta: types.TableMeta{
  195. Indexs: map[string]types.IndexMeta{
  196. "id": {
  197. IType: types.IndexTypePrimaryKey,
  198. Columns: []types.ColumnMeta{{
  199. ColumnName: "id",
  200. }},
  201. },
  202. },
  203. }, parseCtx: &types.ParseContext{
  204. InsertStmt: &ast.InsertStmt{
  205. Columns: []*ast.ColumnName{{}},
  206. },
  207. }}, want: false},
  208. }
  209. for _, tt := range tests {
  210. t.Run(tt.name, func(t *testing.T) {
  211. executor := NewInsertExecutor(nil, &types.ExecContext{}, []exec.SQLHook{})
  212. executor.(*insertExecutor).businesSQLResult = tt.fields.InsertResult
  213. executor.(*insertExecutor).incrementStep = tt.fields.IncrementStep
  214. assert.Equalf(t, tt.want, executor.(*insertExecutor).containsPK(tt.args.meta, tt.args.parseCtx), "containsPK(%v, %v)", tt.args.meta, tt.args.parseCtx)
  215. })
  216. }
  217. }
  218. func TestMySQLInsertUndoLogBuilder_containPK(t *testing.T) {
  219. type fields struct {
  220. InsertResult types.ExecResult
  221. IncrementStep int
  222. }
  223. type args struct {
  224. columnName string
  225. meta types.TableMeta
  226. }
  227. tests := []struct {
  228. name string
  229. fields fields
  230. args args
  231. want bool
  232. }{
  233. {
  234. name: "test-true",
  235. fields: fields{},
  236. args: args{
  237. columnName: "id",
  238. meta: types.TableMeta{
  239. Indexs: map[string]types.IndexMeta{
  240. "id": {
  241. IType: types.IndexTypePrimaryKey,
  242. Columns: []types.ColumnMeta{{
  243. ColumnName: "id",
  244. }},
  245. },
  246. },
  247. },
  248. },
  249. want: true,
  250. },
  251. {
  252. name: "test-false",
  253. fields: fields{},
  254. args: args{
  255. columnName: "id",
  256. meta: types.TableMeta{
  257. Indexs: map[string]types.IndexMeta{
  258. "id": {
  259. IType: types.IndexTypePrimaryKey,
  260. Columns: []types.ColumnMeta{{
  261. ColumnName: "bizId",
  262. }},
  263. },
  264. },
  265. },
  266. },
  267. want: false,
  268. },
  269. {
  270. name: "test-false",
  271. fields: fields{},
  272. args: args{
  273. columnName: "id",
  274. meta: types.TableMeta{
  275. Indexs: map[string]types.IndexMeta{},
  276. },
  277. },
  278. want: false,
  279. },
  280. }
  281. for _, tt := range tests {
  282. t.Run(tt.name, func(t *testing.T) {
  283. executor := NewInsertExecutor(nil, &types.ExecContext{}, []exec.SQLHook{})
  284. executor.(*insertExecutor).businesSQLResult = tt.fields.InsertResult
  285. executor.(*insertExecutor).incrementStep = tt.fields.IncrementStep
  286. assert.Equalf(t, tt.want, executor.(*insertExecutor).containPK(tt.args.columnName, tt.args.meta), "isPKColumn(%v, %v)", tt.args.columnName, tt.args.meta)
  287. })
  288. }
  289. }
  290. func TestMySQLInsertUndoLogBuilder_getPkIndex(t *testing.T) {
  291. type fields struct {
  292. InsertResult types.ExecResult
  293. IncrementStep int
  294. }
  295. type args struct {
  296. InsertStmt *ast.InsertStmt
  297. meta types.TableMeta
  298. }
  299. tests := []struct {
  300. name string
  301. fields fields
  302. args args
  303. want map[string]int
  304. }{
  305. {name: "test-0", fields: fields{}, args: args{
  306. InsertStmt: &ast.InsertStmt{
  307. Columns: []*ast.ColumnName{
  308. {
  309. Name: model.CIStr{O: "id", L: "id"},
  310. },
  311. {
  312. Name: model.CIStr{O: "name", L: "name"},
  313. },
  314. },
  315. },
  316. meta: types.TableMeta{
  317. ColumnNames: []string{"id"},
  318. Columns: map[string]types.ColumnMeta{
  319. "id": {
  320. ColumnName: "id",
  321. },
  322. },
  323. Indexs: map[string]types.IndexMeta{
  324. "id": {
  325. IType: types.IndexTypePrimaryKey,
  326. Columns: []types.ColumnMeta{{
  327. ColumnName: "id",
  328. }},
  329. },
  330. },
  331. },
  332. }, want: map[string]int{
  333. "id": 0,
  334. }},
  335. {name: "test-1", fields: fields{}, args: args{
  336. InsertStmt: &ast.InsertStmt{
  337. Columns: []*ast.ColumnName{
  338. {
  339. Name: model.CIStr{O: "name", L: "name"},
  340. },
  341. {
  342. Name: model.CIStr{O: "id", L: "id"},
  343. },
  344. },
  345. },
  346. meta: types.TableMeta{
  347. ColumnNames: []string{"id"},
  348. Columns: map[string]types.ColumnMeta{
  349. "id": {
  350. ColumnName: "id",
  351. },
  352. },
  353. Indexs: map[string]types.IndexMeta{
  354. "id": {
  355. IType: types.IndexTypePrimaryKey,
  356. Columns: []types.ColumnMeta{{
  357. ColumnName: "id",
  358. }},
  359. },
  360. },
  361. },
  362. }, want: map[string]int{
  363. "id": 1,
  364. }},
  365. {name: "test-null", fields: fields{}, args: args{
  366. InsertStmt: &ast.InsertStmt{},
  367. meta: types.TableMeta{
  368. ColumnNames: []string{"id"},
  369. Columns: map[string]types.ColumnMeta{
  370. "id": {
  371. ColumnName: "id",
  372. },
  373. },
  374. Indexs: map[string]types.IndexMeta{
  375. "id": {
  376. IType: types.IndexTypePrimaryKey,
  377. Columns: []types.ColumnMeta{{
  378. ColumnName: "id",
  379. }},
  380. },
  381. },
  382. },
  383. }, want: map[string]int{}},
  384. {name: "test-1", fields: fields{}, args: args{
  385. InsertStmt: &ast.InsertStmt{
  386. Columns: []*ast.ColumnName{
  387. {
  388. Name: model.CIStr{O: "name", L: "name"},
  389. },
  390. {
  391. Name: model.CIStr{O: "id", L: "id"},
  392. },
  393. },
  394. },
  395. meta: types.TableMeta{},
  396. }, want: map[string]int{}},
  397. }
  398. for _, tt := range tests {
  399. t.Run(tt.name, func(t *testing.T) {
  400. executor := NewInsertExecutor(nil, &types.ExecContext{}, []exec.SQLHook{})
  401. executor.(*insertExecutor).businesSQLResult = tt.fields.InsertResult
  402. executor.(*insertExecutor).incrementStep = tt.fields.IncrementStep
  403. assert.Equalf(t, tt.want, executor.(*insertExecutor).getPkIndex(tt.args.InsertStmt, tt.args.meta), "getPkIndexArray(%v, %v)", tt.args.InsertStmt, tt.args.meta)
  404. })
  405. }
  406. }
  407. func genIntDatum(id int64) test_driver.Datum {
  408. tmp := test_driver.Datum{}
  409. tmp.SetInt64(id)
  410. return tmp
  411. }
  412. func genStrDatum(str string) test_driver.Datum {
  413. tmp := test_driver.Datum{}
  414. tmp.SetBytesAsString([]byte(str))
  415. return tmp
  416. }
  417. func TestMySQLInsertUndoLogBuilder_parsePkValuesFromStatement(t *testing.T) {
  418. type fields struct {
  419. InsertResult types.ExecResult
  420. IncrementStep int
  421. }
  422. type args struct {
  423. insertStmt *ast.InsertStmt
  424. meta types.TableMeta
  425. nameValues []driver.NamedValue
  426. }
  427. tests := []struct {
  428. name string
  429. fields fields
  430. args args
  431. want map[string][]interface{}
  432. }{
  433. {
  434. name: "test-1",
  435. fields: fields{},
  436. args: args{
  437. insertStmt: &ast.InsertStmt{
  438. Columns: []*ast.ColumnName{
  439. {
  440. Name: model.CIStr{O: "id", L: "id"},
  441. },
  442. },
  443. Lists: [][]ast.ExprNode{
  444. {
  445. &test_driver.ValueExpr{
  446. Datum: genIntDatum(1),
  447. },
  448. },
  449. },
  450. },
  451. meta: types.TableMeta{
  452. ColumnNames: []string{"id"},
  453. Columns: map[string]types.ColumnMeta{
  454. "id": {
  455. ColumnName: "id",
  456. },
  457. },
  458. Indexs: map[string]types.IndexMeta{
  459. "id": {
  460. IType: types.IndexTypePrimaryKey,
  461. Columns: []types.ColumnMeta{{
  462. ColumnName: "id",
  463. }},
  464. },
  465. },
  466. },
  467. nameValues: []driver.NamedValue{
  468. {
  469. Name: "name",
  470. Value: "Tom",
  471. },
  472. {
  473. Name: "id",
  474. Value: 1,
  475. },
  476. },
  477. },
  478. want: map[string][]interface{}{
  479. "id": {int64(1)},
  480. },
  481. },
  482. {
  483. name: "test-placeholder",
  484. fields: fields{},
  485. args: args{
  486. insertStmt: &ast.InsertStmt{
  487. Columns: []*ast.ColumnName{
  488. {
  489. Name: model.CIStr{O: "id", L: "id"},
  490. },
  491. },
  492. Lists: [][]ast.ExprNode{
  493. {
  494. &test_driver.ValueExpr{
  495. Datum: genStrDatum("?"),
  496. },
  497. },
  498. },
  499. },
  500. meta: types.TableMeta{
  501. ColumnNames: []string{"id"},
  502. Columns: map[string]types.ColumnMeta{
  503. "id": {
  504. ColumnName: "id",
  505. },
  506. },
  507. Indexs: map[string]types.IndexMeta{
  508. "id": {
  509. IType: types.IndexTypePrimaryKey,
  510. Columns: []types.ColumnMeta{{
  511. ColumnName: "id",
  512. }},
  513. },
  514. },
  515. },
  516. nameValues: []driver.NamedValue{
  517. {
  518. Name: "id",
  519. Value: int64(1),
  520. },
  521. },
  522. },
  523. want: map[string][]interface{}{
  524. "id": {int64(1)},
  525. },
  526. },
  527. }
  528. for _, tt := range tests {
  529. t.Run(tt.name, func(t *testing.T) {
  530. executor := NewInsertExecutor(nil, &types.ExecContext{}, []exec.SQLHook{})
  531. executor.(*insertExecutor).businesSQLResult = tt.fields.InsertResult
  532. executor.(*insertExecutor).incrementStep = tt.fields.IncrementStep
  533. got, err := executor.(*insertExecutor).parsePkValuesFromStatement(tt.args.insertStmt, tt.args.meta, tt.args.nameValues)
  534. assert.Nil(t, err)
  535. assert.Equalf(t, tt.want, got, "parsePkValuesFromStatement(%v, %v, %v)", tt.args.insertStmt, tt.args.meta, tt.args.nameValues)
  536. })
  537. }
  538. }
  539. func TestMySQLInsertUndoLogBuilder_getPkValuesByColumn(t *testing.T) {
  540. type fields struct {
  541. InsertResult types.ExecResult
  542. IncrementStep int
  543. }
  544. type args struct {
  545. execCtx *types.ExecContext
  546. meta types.TableMeta
  547. }
  548. tests := []struct {
  549. name string
  550. fields fields
  551. args args
  552. want map[string][]interface{}
  553. }{
  554. {
  555. name: "test-1",
  556. fields: fields{},
  557. args: args{
  558. meta: types.TableMeta{
  559. ColumnNames: []string{"id"},
  560. Columns: map[string]types.ColumnMeta{
  561. "id": {
  562. ColumnName: "id",
  563. },
  564. },
  565. Indexs: map[string]types.IndexMeta{
  566. "id": {
  567. IType: types.IndexTypePrimaryKey,
  568. Columns: []types.ColumnMeta{{
  569. ColumnName: "id",
  570. }},
  571. },
  572. },
  573. },
  574. execCtx: &types.ExecContext{
  575. ParseContext: &types.ParseContext{
  576. InsertStmt: &ast.InsertStmt{
  577. Table: &ast.TableRefsClause{
  578. TableRefs: &ast.Join{
  579. Left: &ast.TableSource{
  580. Source: &ast.TableName{
  581. Name: model.CIStr{
  582. O: "test",
  583. },
  584. },
  585. },
  586. },
  587. },
  588. Columns: []*ast.ColumnName{
  589. {
  590. Name: model.CIStr{O: "id", L: "id"},
  591. },
  592. },
  593. Lists: [][]ast.ExprNode{
  594. {
  595. &test_driver.ValueExpr{
  596. Datum: genIntDatum(1),
  597. },
  598. },
  599. },
  600. },
  601. },
  602. },
  603. },
  604. want: map[string][]interface{}{
  605. "id": {int64(1)},
  606. },
  607. },
  608. }
  609. for _, tt := range tests {
  610. t.Run(tt.name, func(t *testing.T) {
  611. datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil))
  612. stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta",
  613. func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) {
  614. return &tt.args.meta, nil
  615. })
  616. executor := NewInsertExecutor(tt.args.execCtx.ParseContext, &types.ExecContext{}, []exec.SQLHook{})
  617. executor.(*insertExecutor).businesSQLResult = tt.fields.InsertResult
  618. executor.(*insertExecutor).incrementStep = tt.fields.IncrementStep
  619. got, err := executor.(*insertExecutor).getPkValuesByColumn(context.Background(), tt.args.execCtx)
  620. assert.Nil(t, err)
  621. assert.Equalf(t, tt.want, got, "getPkValuesByColumn(%v)", tt.args.execCtx)
  622. stub.Reset()
  623. })
  624. }
  625. }
  626. func TestMySQLInsertUndoLogBuilder_getPkValuesByAuto(t *testing.T) {
  627. type fields struct {
  628. InsertResult types.ExecResult
  629. IncrementStep int
  630. }
  631. type args struct {
  632. execCtx *types.ExecContext
  633. meta types.TableMeta
  634. }
  635. tests := []struct {
  636. name string
  637. fields fields
  638. args args
  639. want map[string][]interface{}
  640. wantErr assert.ErrorAssertionFunc
  641. }{
  642. {
  643. name: "test-2",
  644. fields: fields{
  645. InsertResult: &mockInsertResult{lastInsertID: 100, rowsAffected: 1},
  646. IncrementStep: 1,
  647. },
  648. args: args{
  649. meta: types.TableMeta{
  650. ColumnNames: []string{"id", "name"},
  651. Indexs: map[string]types.IndexMeta{
  652. "id": {
  653. IType: types.IndexTypePrimaryKey,
  654. ColumnName: "id",
  655. Columns: []types.ColumnMeta{
  656. {
  657. ColumnName: "id",
  658. DatabaseType: types.GetSqlDataType("BIGINT"),
  659. Autoincrement: true,
  660. },
  661. },
  662. },
  663. },
  664. Columns: map[string]types.ColumnMeta{
  665. "id": {
  666. ColumnName: "id",
  667. },
  668. "name": {
  669. ColumnName: "name",
  670. },
  671. },
  672. },
  673. execCtx: &types.ExecContext{
  674. ParseContext: &types.ParseContext{
  675. InsertStmt: &ast.InsertStmt{
  676. Table: &ast.TableRefsClause{
  677. TableRefs: &ast.Join{
  678. Left: &ast.TableSource{
  679. Source: &ast.TableName{
  680. Name: model.CIStr{
  681. O: "test",
  682. },
  683. },
  684. },
  685. },
  686. },
  687. Columns: []*ast.ColumnName{
  688. {
  689. Name: model.CIStr{O: "name", L: "name"},
  690. },
  691. },
  692. Lists: [][]ast.ExprNode{
  693. {
  694. &test_driver.ValueExpr{
  695. Datum: genStrDatum("Tom"),
  696. },
  697. },
  698. },
  699. },
  700. },
  701. },
  702. },
  703. want: map[string][]interface{}{
  704. "id": {int64(100)},
  705. },
  706. },
  707. }
  708. for _, tt := range tests {
  709. t.Run(tt.name, func(t *testing.T) {
  710. datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil))
  711. stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta",
  712. func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) {
  713. return &tt.args.meta, nil
  714. })
  715. executor := NewInsertExecutor(nil, &types.ExecContext{}, []exec.SQLHook{})
  716. executor.(*insertExecutor).businesSQLResult = tt.fields.InsertResult
  717. executor.(*insertExecutor).incrementStep = tt.fields.IncrementStep
  718. executor.(*insertExecutor).parserCtx = tt.args.execCtx.ParseContext
  719. got, err := executor.(*insertExecutor).getPkValuesByAuto(context.Background(), tt.args.execCtx)
  720. assert.Nil(t, err)
  721. assert.Equalf(t, tt.want, got, "getPkValuesByAuto(%v)", tt.args.execCtx)
  722. stub.Reset()
  723. })
  724. }
  725. }
  726. func TestMySQLInsertUndoLogBuilder_autoGeneratePks(t *testing.T) {
  727. type fields struct {
  728. InsertResult types.ExecResult
  729. IncrementStep int
  730. }
  731. type args struct {
  732. execCtx *types.ExecContext
  733. autoColumnName string
  734. lastInsetId int64
  735. updateCount int64
  736. meta types.TableMeta
  737. }
  738. tests := []struct {
  739. name string
  740. fields fields
  741. args args
  742. want map[string][]interface{}
  743. }{
  744. {name: "test", fields: fields{
  745. IncrementStep: 1,
  746. }, args: args{
  747. meta: types.TableMeta{
  748. ColumnNames: []string{"id"},
  749. Columns: map[string]types.ColumnMeta{
  750. "id": {
  751. ColumnName: "id",
  752. },
  753. },
  754. Indexs: map[string]types.IndexMeta{
  755. "id": {
  756. IType: types.IndexTypePrimaryKey,
  757. Columns: []types.ColumnMeta{{
  758. ColumnName: "id",
  759. }},
  760. },
  761. },
  762. },
  763. execCtx: &types.ExecContext{
  764. ParseContext: &types.ParseContext{
  765. InsertStmt: &ast.InsertStmt{
  766. Table: &ast.TableRefsClause{
  767. TableRefs: &ast.Join{
  768. Left: &ast.TableSource{
  769. Source: &ast.TableName{
  770. Name: model.CIStr{
  771. O: "test",
  772. },
  773. },
  774. },
  775. },
  776. },
  777. Columns: []*ast.ColumnName{
  778. {
  779. Name: model.CIStr{O: "id", L: "id"},
  780. },
  781. },
  782. Lists: [][]ast.ExprNode{
  783. {
  784. &test_driver.ValueExpr{
  785. Datum: genIntDatum(1),
  786. },
  787. },
  788. },
  789. },
  790. },
  791. },
  792. autoColumnName: "id",
  793. lastInsetId: 100,
  794. updateCount: 1,
  795. }, want: map[string][]interface{}{
  796. "id": {int64(100)},
  797. }},
  798. }
  799. for _, tt := range tests {
  800. t.Run(tt.name, func(t *testing.T) {
  801. datasource.RegisterTableCache(types.DBTypeMySQL, mysql.NewTableMetaInstance(nil))
  802. stub := gomonkey.ApplyMethod(reflect.TypeOf(datasource.GetTableCache(types.DBTypeMySQL)), "GetTableMeta",
  803. func(_ *mysql.TableMetaCache, ctx context.Context, dbName, tableName string) (*types.TableMeta, error) {
  804. return &tt.args.meta, nil
  805. })
  806. executor := NewInsertExecutor(nil, &types.ExecContext{}, []exec.SQLHook{})
  807. executor.(*insertExecutor).businesSQLResult = tt.fields.InsertResult
  808. executor.(*insertExecutor).incrementStep = tt.fields.IncrementStep
  809. got, err := executor.(*insertExecutor).autoGeneratePks(tt.args.execCtx, tt.args.autoColumnName, tt.args.lastInsetId, tt.args.updateCount)
  810. assert.Nil(t, err)
  811. assert.Equalf(t, tt.want, got, "autoGeneratePks(%v, %v, %v, %v)", tt.args.execCtx, tt.args.autoColumnName, tt.args.lastInsetId, tt.args.updateCount)
  812. stub.Reset()
  813. })
  814. }
  815. }