/go/sql/builder_test.go

https://github.com/github/gh-ost · Go · 679 lines · 635 code · 33 blank · 11 comment · 1 complexity · f979da9cd70b47fda49517b6c5cd214b MD5 · raw file

  1. /*
  2. Copyright 2016 GitHub Inc.
  3. See https://github.com/github/gh-ost/blob/master/LICENSE
  4. */
  5. package sql
  6. import (
  7. "testing"
  8. "reflect"
  9. "regexp"
  10. "strings"
  11. "github.com/outbrain/golib/log"
  12. test "github.com/outbrain/golib/tests"
  13. )
  14. var (
  15. spacesRegexp = regexp.MustCompile(`[ \t\n\r]+`)
  16. )
  17. func init() {
  18. log.SetLevel(log.ERROR)
  19. }
  20. func normalizeQuery(name string) string {
  21. name = strings.Replace(name, "`", "", -1)
  22. name = spacesRegexp.ReplaceAllString(name, " ")
  23. name = strings.TrimSpace(name)
  24. return name
  25. }
  26. func TestEscapeName(t *testing.T) {
  27. names := []string{"my_table", `"my_table"`, "`my_table`"}
  28. for _, name := range names {
  29. escaped := EscapeName(name)
  30. test.S(t).ExpectEquals(escaped, "`my_table`")
  31. }
  32. }
  33. func TestBuildEqualsComparison(t *testing.T) {
  34. {
  35. columns := []string{"c1"}
  36. values := []string{"@v1"}
  37. comparison, err := BuildEqualsComparison(columns, values)
  38. test.S(t).ExpectNil(err)
  39. test.S(t).ExpectEquals(comparison, "((`c1` = @v1))")
  40. }
  41. {
  42. columns := []string{"c1", "c2"}
  43. values := []string{"@v1", "@v2"}
  44. comparison, err := BuildEqualsComparison(columns, values)
  45. test.S(t).ExpectNil(err)
  46. test.S(t).ExpectEquals(comparison, "((`c1` = @v1) and (`c2` = @v2))")
  47. }
  48. {
  49. columns := []string{"c1"}
  50. values := []string{"@v1", "@v2"}
  51. _, err := BuildEqualsComparison(columns, values)
  52. test.S(t).ExpectNotNil(err)
  53. }
  54. {
  55. columns := []string{}
  56. values := []string{}
  57. _, err := BuildEqualsComparison(columns, values)
  58. test.S(t).ExpectNotNil(err)
  59. }
  60. }
  61. func TestBuildEqualsPreparedComparison(t *testing.T) {
  62. {
  63. columns := []string{"c1", "c2"}
  64. comparison, err := BuildEqualsPreparedComparison(columns)
  65. test.S(t).ExpectNil(err)
  66. test.S(t).ExpectEquals(comparison, "((`c1` = ?) and (`c2` = ?))")
  67. }
  68. }
  69. func TestBuildSetPreparedClause(t *testing.T) {
  70. {
  71. columns := NewColumnList([]string{"c1"})
  72. clause, err := BuildSetPreparedClause(columns)
  73. test.S(t).ExpectNil(err)
  74. test.S(t).ExpectEquals(clause, "`c1`=?")
  75. }
  76. {
  77. columns := NewColumnList([]string{"c1", "c2"})
  78. clause, err := BuildSetPreparedClause(columns)
  79. test.S(t).ExpectNil(err)
  80. test.S(t).ExpectEquals(clause, "`c1`=?, `c2`=?")
  81. }
  82. {
  83. columns := NewColumnList([]string{})
  84. _, err := BuildSetPreparedClause(columns)
  85. test.S(t).ExpectNotNil(err)
  86. }
  87. }
  88. func TestBuildRangeComparison(t *testing.T) {
  89. {
  90. columns := []string{"c1"}
  91. values := []string{"@v1"}
  92. args := []interface{}{3}
  93. comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanComparisonSign)
  94. test.S(t).ExpectNil(err)
  95. test.S(t).ExpectEquals(comparison, "((`c1` < @v1))")
  96. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3}))
  97. }
  98. {
  99. columns := []string{"c1"}
  100. values := []string{"@v1"}
  101. args := []interface{}{3}
  102. comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
  103. test.S(t).ExpectNil(err)
  104. test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or ((`c1` = @v1)))")
  105. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3}))
  106. }
  107. {
  108. columns := []string{"c1", "c2"}
  109. values := []string{"@v1", "@v2"}
  110. args := []interface{}{3, 17}
  111. comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanComparisonSign)
  112. test.S(t).ExpectNil(err)
  113. test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)))")
  114. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17}))
  115. }
  116. {
  117. columns := []string{"c1", "c2"}
  118. values := []string{"@v1", "@v2"}
  119. args := []interface{}{3, 17}
  120. comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
  121. test.S(t).ExpectNil(err)
  122. test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)) or ((`c1` = @v1) and (`c2` = @v2)))")
  123. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17}))
  124. }
  125. {
  126. columns := []string{"c1", "c2", "c3"}
  127. values := []string{"@v1", "@v2", "@v3"}
  128. args := []interface{}{3, 17, 22}
  129. comparison, explodedArgs, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
  130. test.S(t).ExpectNil(err)
  131. test.S(t).ExpectEquals(comparison, "((`c1` < @v1) or (((`c1` = @v1)) AND (`c2` < @v2)) or (((`c1` = @v1) and (`c2` = @v2)) AND (`c3` < @v3)) or ((`c1` = @v1) and (`c2` = @v2) and (`c3` = @v3)))")
  132. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17, 22, 3, 17, 22}))
  133. }
  134. {
  135. columns := []string{"c1"}
  136. values := []string{"@v1", "@v2"}
  137. args := []interface{}{3, 17}
  138. _, _, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
  139. test.S(t).ExpectNotNil(err)
  140. }
  141. {
  142. columns := []string{}
  143. values := []string{}
  144. args := []interface{}{}
  145. _, _, err := BuildRangeComparison(columns, values, args, LessThanOrEqualsComparisonSign)
  146. test.S(t).ExpectNotNil(err)
  147. }
  148. }
  149. func TestBuildRangeInsertQuery(t *testing.T) {
  150. databaseName := "mydb"
  151. originalTableName := "tbl"
  152. ghostTableName := "ghost"
  153. sharedColumns := []string{"id", "name", "position"}
  154. {
  155. uniqueKey := "PRIMARY"
  156. uniqueKeyColumns := NewColumnList([]string{"id"})
  157. rangeStartValues := []string{"@v1s"}
  158. rangeEndValues := []string{"@v1e"}
  159. rangeStartArgs := []interface{}{3}
  160. rangeEndArgs := []interface{}{103}
  161. query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true, false)
  162. test.S(t).ExpectNil(err)
  163. expected := `
  164. insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, position)
  165. (select id, name, position from mydb.tbl force index (PRIMARY)
  166. where (((id > @v1s) or ((id = @v1s))) and ((id < @v1e) or ((id = @v1e))))
  167. )
  168. `
  169. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  170. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 103, 103}))
  171. }
  172. {
  173. uniqueKey := "name_position_uidx"
  174. uniqueKeyColumns := NewColumnList([]string{"name", "position"})
  175. rangeStartValues := []string{"@v1s", "@v2s"}
  176. rangeEndValues := []string{"@v1e", "@v2e"}
  177. rangeStartArgs := []interface{}{3, 17}
  178. rangeEndArgs := []interface{}{103, 117}
  179. query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true, false)
  180. test.S(t).ExpectNil(err)
  181. expected := `
  182. insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, position)
  183. (select id, name, position from mydb.tbl force index (name_position_uidx)
  184. where (((name > @v1s) or (((name = @v1s)) AND (position > @v2s)) or ((name = @v1s) and (position = @v2s))) and ((name < @v1e) or (((name = @v1e)) AND (position < @v2e)) or ((name = @v1e) and (position = @v2e))))
  185. )
  186. `
  187. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  188. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17, 103, 103, 117, 103, 117}))
  189. }
  190. }
  191. func TestBuildRangeInsertQueryRenameMap(t *testing.T) {
  192. databaseName := "mydb"
  193. originalTableName := "tbl"
  194. ghostTableName := "ghost"
  195. sharedColumns := []string{"id", "name", "position"}
  196. mappedSharedColumns := []string{"id", "name", "location"}
  197. {
  198. uniqueKey := "PRIMARY"
  199. uniqueKeyColumns := NewColumnList([]string{"id"})
  200. rangeStartValues := []string{"@v1s"}
  201. rangeEndValues := []string{"@v1e"}
  202. rangeStartArgs := []interface{}{3}
  203. rangeEndArgs := []interface{}{103}
  204. query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, mappedSharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true, false)
  205. test.S(t).ExpectNil(err)
  206. expected := `
  207. insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, location)
  208. (select id, name, position from mydb.tbl force index (PRIMARY)
  209. where (((id > @v1s) or ((id = @v1s))) and ((id < @v1e) or ((id = @v1e))))
  210. )
  211. `
  212. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  213. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 103, 103}))
  214. }
  215. {
  216. uniqueKey := "name_position_uidx"
  217. uniqueKeyColumns := NewColumnList([]string{"name", "position"})
  218. rangeStartValues := []string{"@v1s", "@v2s"}
  219. rangeEndValues := []string{"@v1e", "@v2e"}
  220. rangeStartArgs := []interface{}{3, 17}
  221. rangeEndArgs := []interface{}{103, 117}
  222. query, explodedArgs, err := BuildRangeInsertQuery(databaseName, originalTableName, ghostTableName, sharedColumns, mappedSharedColumns, uniqueKey, uniqueKeyColumns, rangeStartValues, rangeEndValues, rangeStartArgs, rangeEndArgs, true, false)
  223. test.S(t).ExpectNil(err)
  224. expected := `
  225. insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, location)
  226. (select id, name, position from mydb.tbl force index (name_position_uidx)
  227. where (((name > @v1s) or (((name = @v1s)) AND (position > @v2s)) or ((name = @v1s) and (position = @v2s))) and ((name < @v1e) or (((name = @v1e)) AND (position < @v2e)) or ((name = @v1e) and (position = @v2e))))
  228. )
  229. `
  230. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  231. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17, 103, 103, 117, 103, 117}))
  232. }
  233. }
  234. func TestBuildRangeInsertPreparedQuery(t *testing.T) {
  235. databaseName := "mydb"
  236. originalTableName := "tbl"
  237. ghostTableName := "ghost"
  238. sharedColumns := []string{"id", "name", "position"}
  239. {
  240. uniqueKey := "name_position_uidx"
  241. uniqueKeyColumns := NewColumnList([]string{"name", "position"})
  242. rangeStartArgs := []interface{}{3, 17}
  243. rangeEndArgs := []interface{}{103, 117}
  244. query, explodedArgs, err := BuildRangeInsertPreparedQuery(databaseName, originalTableName, ghostTableName, sharedColumns, sharedColumns, uniqueKey, uniqueKeyColumns, rangeStartArgs, rangeEndArgs, true, true)
  245. test.S(t).ExpectNil(err)
  246. expected := `
  247. insert /* gh-ost mydb.tbl */ ignore into mydb.ghost (id, name, position)
  248. (select id, name, position from mydb.tbl force index (name_position_uidx)
  249. where (((name > ?) or (((name = ?)) AND (position > ?)) or ((name = ?) and (position = ?))) and ((name < ?) or (((name = ?)) AND (position < ?)) or ((name = ?) and (position = ?))))
  250. lock in share mode )
  251. `
  252. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  253. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 3, 17, 103, 103, 117, 103, 117}))
  254. }
  255. }
  256. func TestBuildUniqueKeyRangeEndPreparedQuery(t *testing.T) {
  257. databaseName := "mydb"
  258. originalTableName := "tbl"
  259. var chunkSize int64 = 500
  260. {
  261. uniqueKeyColumns := NewColumnList([]string{"name", "position"})
  262. rangeStartArgs := []interface{}{3, 17}
  263. rangeEndArgs := []interface{}{103, 117}
  264. query, explodedArgs, err := BuildUniqueKeyRangeEndPreparedQueryViaTemptable(databaseName, originalTableName, uniqueKeyColumns, rangeStartArgs, rangeEndArgs, chunkSize, false, "test")
  265. test.S(t).ExpectNil(err)
  266. expected := `
  267. select /* gh-ost mydb.tbl test */ name, position
  268. from (
  269. select
  270. name, position
  271. from
  272. mydb.tbl
  273. where ((name > ?) or (((name = ?)) AND (position > ?))) and ((name < ?) or (((name = ?)) AND (position < ?)) or ((name = ?) and (position = ?)))
  274. order by
  275. name asc, position asc
  276. limit 500
  277. ) select_osc_chunk
  278. order by
  279. name desc, position desc
  280. limit 1
  281. `
  282. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  283. test.S(t).ExpectTrue(reflect.DeepEqual(explodedArgs, []interface{}{3, 3, 17, 103, 103, 117, 103, 117}))
  284. }
  285. }
  286. func TestBuildUniqueKeyMinValuesPreparedQuery(t *testing.T) {
  287. databaseName := "mydb"
  288. originalTableName := "tbl"
  289. uniqueKeyColumns := NewColumnList([]string{"name", "position"})
  290. {
  291. query, err := BuildUniqueKeyMinValuesPreparedQuery(databaseName, originalTableName, uniqueKeyColumns)
  292. test.S(t).ExpectNil(err)
  293. expected := `
  294. select /* gh-ost mydb.tbl */ name, position
  295. from
  296. mydb.tbl
  297. order by
  298. name asc, position asc
  299. limit 1
  300. `
  301. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  302. }
  303. {
  304. query, err := BuildUniqueKeyMaxValuesPreparedQuery(databaseName, originalTableName, uniqueKeyColumns)
  305. test.S(t).ExpectNil(err)
  306. expected := `
  307. select /* gh-ost mydb.tbl */ name, position
  308. from
  309. mydb.tbl
  310. order by
  311. name desc, position desc
  312. limit 1
  313. `
  314. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  315. }
  316. }
  317. func TestBuildDMLDeleteQuery(t *testing.T) {
  318. databaseName := "mydb"
  319. tableName := "tbl"
  320. tableColumns := NewColumnList([]string{"id", "name", "rank", "position", "age"})
  321. args := []interface{}{3, "testname", "first", 17, 23}
  322. {
  323. uniqueKeyColumns := NewColumnList([]string{"position"})
  324. query, uniqueKeyArgs, err := BuildDMLDeleteQuery(databaseName, tableName, tableColumns, uniqueKeyColumns, args)
  325. test.S(t).ExpectNil(err)
  326. expected := `
  327. delete /* gh-ost mydb.tbl */
  328. from
  329. mydb.tbl
  330. where
  331. ((position = ?))
  332. `
  333. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  334. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{17}))
  335. }
  336. {
  337. uniqueKeyColumns := NewColumnList([]string{"name", "position"})
  338. query, uniqueKeyArgs, err := BuildDMLDeleteQuery(databaseName, tableName, tableColumns, uniqueKeyColumns, args)
  339. test.S(t).ExpectNil(err)
  340. expected := `
  341. delete /* gh-ost mydb.tbl */
  342. from
  343. mydb.tbl
  344. where
  345. ((name = ?) and (position = ?))
  346. `
  347. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  348. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{"testname", 17}))
  349. }
  350. {
  351. uniqueKeyColumns := NewColumnList([]string{"position", "name"})
  352. query, uniqueKeyArgs, err := BuildDMLDeleteQuery(databaseName, tableName, tableColumns, uniqueKeyColumns, args)
  353. test.S(t).ExpectNil(err)
  354. expected := `
  355. delete /* gh-ost mydb.tbl */
  356. from
  357. mydb.tbl
  358. where
  359. ((position = ?) and (name = ?))
  360. `
  361. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  362. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{17, "testname"}))
  363. }
  364. {
  365. uniqueKeyColumns := NewColumnList([]string{"position", "name"})
  366. args := []interface{}{"first", 17}
  367. _, _, err := BuildDMLDeleteQuery(databaseName, tableName, tableColumns, uniqueKeyColumns, args)
  368. test.S(t).ExpectNotNil(err)
  369. }
  370. }
  371. func TestBuildDMLDeleteQuerySignedUnsigned(t *testing.T) {
  372. databaseName := "mydb"
  373. tableName := "tbl"
  374. tableColumns := NewColumnList([]string{"id", "name", "rank", "position", "age"})
  375. uniqueKeyColumns := NewColumnList([]string{"position"})
  376. {
  377. // test signed (expect no change)
  378. args := []interface{}{3, "testname", "first", -1, 23}
  379. query, uniqueKeyArgs, err := BuildDMLDeleteQuery(databaseName, tableName, tableColumns, uniqueKeyColumns, args)
  380. test.S(t).ExpectNil(err)
  381. expected := `
  382. delete /* gh-ost mydb.tbl */
  383. from
  384. mydb.tbl
  385. where
  386. ((position = ?))
  387. `
  388. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  389. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{-1}))
  390. }
  391. {
  392. // test unsigned
  393. args := []interface{}{3, "testname", "first", int8(-1), 23}
  394. uniqueKeyColumns.SetUnsigned("position")
  395. query, uniqueKeyArgs, err := BuildDMLDeleteQuery(databaseName, tableName, tableColumns, uniqueKeyColumns, args)
  396. test.S(t).ExpectNil(err)
  397. expected := `
  398. delete /* gh-ost mydb.tbl */
  399. from
  400. mydb.tbl
  401. where
  402. ((position = ?))
  403. `
  404. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  405. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{uint8(255)}))
  406. }
  407. }
  408. func TestBuildDMLInsertQuery(t *testing.T) {
  409. databaseName := "mydb"
  410. tableName := "tbl"
  411. tableColumns := NewColumnList([]string{"id", "name", "rank", "position", "age"})
  412. args := []interface{}{3, "testname", "first", 17, 23}
  413. {
  414. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  415. query, sharedArgs, err := BuildDMLInsertQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, args)
  416. test.S(t).ExpectNil(err)
  417. expected := `
  418. replace /* gh-ost mydb.tbl */
  419. into mydb.tbl
  420. (id, name, position, age)
  421. values
  422. (?, ?, ?, ?)
  423. `
  424. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  425. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", 17, 23}))
  426. }
  427. {
  428. sharedColumns := NewColumnList([]string{"position", "name", "age", "id"})
  429. query, sharedArgs, err := BuildDMLInsertQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, args)
  430. test.S(t).ExpectNil(err)
  431. expected := `
  432. replace /* gh-ost mydb.tbl */
  433. into mydb.tbl
  434. (position, name, age, id)
  435. values
  436. (?, ?, ?, ?)
  437. `
  438. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  439. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{17, "testname", 23, 3}))
  440. }
  441. {
  442. sharedColumns := NewColumnList([]string{"position", "name", "surprise", "id"})
  443. _, _, err := BuildDMLInsertQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, args)
  444. test.S(t).ExpectNotNil(err)
  445. }
  446. {
  447. sharedColumns := NewColumnList([]string{})
  448. _, _, err := BuildDMLInsertQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, args)
  449. test.S(t).ExpectNotNil(err)
  450. }
  451. }
  452. func TestBuildDMLInsertQuerySignedUnsigned(t *testing.T) {
  453. databaseName := "mydb"
  454. tableName := "tbl"
  455. tableColumns := NewColumnList([]string{"id", "name", "rank", "position", "age"})
  456. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  457. {
  458. // testing signed
  459. args := []interface{}{3, "testname", "first", int8(-1), 23}
  460. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  461. query, sharedArgs, err := BuildDMLInsertQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, args)
  462. test.S(t).ExpectNil(err)
  463. expected := `
  464. replace /* gh-ost mydb.tbl */
  465. into mydb.tbl
  466. (id, name, position, age)
  467. values
  468. (?, ?, ?, ?)
  469. `
  470. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  471. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", int8(-1), 23}))
  472. }
  473. {
  474. // testing unsigned
  475. args := []interface{}{3, "testname", "first", int8(-1), 23}
  476. sharedColumns.SetUnsigned("position")
  477. query, sharedArgs, err := BuildDMLInsertQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, args)
  478. test.S(t).ExpectNil(err)
  479. expected := `
  480. replace /* gh-ost mydb.tbl */
  481. into mydb.tbl
  482. (id, name, position, age)
  483. values
  484. (?, ?, ?, ?)
  485. `
  486. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  487. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", uint8(255), 23}))
  488. }
  489. {
  490. // testing unsigned
  491. args := []interface{}{3, "testname", "first", int32(-1), 23}
  492. sharedColumns.SetUnsigned("position")
  493. query, sharedArgs, err := BuildDMLInsertQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, args)
  494. test.S(t).ExpectNil(err)
  495. expected := `
  496. replace /* gh-ost mydb.tbl */
  497. into mydb.tbl
  498. (id, name, position, age)
  499. values
  500. (?, ?, ?, ?)
  501. `
  502. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  503. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", uint32(4294967295), 23}))
  504. }
  505. }
  506. func TestBuildDMLUpdateQuery(t *testing.T) {
  507. databaseName := "mydb"
  508. tableName := "tbl"
  509. tableColumns := NewColumnList([]string{"id", "name", "rank", "position", "age"})
  510. valueArgs := []interface{}{3, "testname", "newval", 17, 23}
  511. whereArgs := []interface{}{3, "testname", "findme", 17, 56}
  512. {
  513. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  514. uniqueKeyColumns := NewColumnList([]string{"position"})
  515. query, sharedArgs, uniqueKeyArgs, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  516. test.S(t).ExpectNil(err)
  517. expected := `
  518. update /* gh-ost mydb.tbl */
  519. mydb.tbl
  520. set id=?, name=?, position=?, age=?
  521. where
  522. ((position = ?))
  523. `
  524. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  525. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", 17, 23}))
  526. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{17}))
  527. }
  528. {
  529. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  530. uniqueKeyColumns := NewColumnList([]string{"position", "name"})
  531. query, sharedArgs, uniqueKeyArgs, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  532. test.S(t).ExpectNil(err)
  533. expected := `
  534. update /* gh-ost mydb.tbl */
  535. mydb.tbl
  536. set id=?, name=?, position=?, age=?
  537. where
  538. ((position = ?) and (name = ?))
  539. `
  540. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  541. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", 17, 23}))
  542. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{17, "testname"}))
  543. }
  544. {
  545. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  546. uniqueKeyColumns := NewColumnList([]string{"age"})
  547. query, sharedArgs, uniqueKeyArgs, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  548. test.S(t).ExpectNil(err)
  549. expected := `
  550. update /* gh-ost mydb.tbl */
  551. mydb.tbl
  552. set id=?, name=?, position=?, age=?
  553. where
  554. ((age = ?))
  555. `
  556. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  557. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", 17, 23}))
  558. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{56}))
  559. }
  560. {
  561. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  562. uniqueKeyColumns := NewColumnList([]string{"age", "position", "id", "name"})
  563. query, sharedArgs, uniqueKeyArgs, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  564. test.S(t).ExpectNil(err)
  565. expected := `
  566. update /* gh-ost mydb.tbl */
  567. mydb.tbl
  568. set id=?, name=?, position=?, age=?
  569. where
  570. ((age = ?) and (position = ?) and (id = ?) and (name = ?))
  571. `
  572. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  573. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", 17, 23}))
  574. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{56, 17, 3, "testname"}))
  575. }
  576. {
  577. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  578. uniqueKeyColumns := NewColumnList([]string{"age", "surprise"})
  579. _, _, _, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  580. test.S(t).ExpectNotNil(err)
  581. }
  582. {
  583. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  584. uniqueKeyColumns := NewColumnList([]string{})
  585. _, _, _, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  586. test.S(t).ExpectNotNil(err)
  587. }
  588. {
  589. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  590. mappedColumns := NewColumnList([]string{"id", "name", "role", "age"})
  591. uniqueKeyColumns := NewColumnList([]string{"id"})
  592. query, sharedArgs, uniqueKeyArgs, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, mappedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  593. test.S(t).ExpectNil(err)
  594. expected := `
  595. update /* gh-ost mydb.tbl */
  596. mydb.tbl
  597. set id=?, name=?, role=?, age=?
  598. where
  599. ((id = ?))
  600. `
  601. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  602. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", 17, 23}))
  603. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{3}))
  604. }
  605. }
  606. func TestBuildDMLUpdateQuerySignedUnsigned(t *testing.T) {
  607. databaseName := "mydb"
  608. tableName := "tbl"
  609. tableColumns := NewColumnList([]string{"id", "name", "rank", "position", "age"})
  610. valueArgs := []interface{}{3, "testname", "newval", int8(-17), int8(-2)}
  611. whereArgs := []interface{}{3, "testname", "findme", int8(-3), 56}
  612. sharedColumns := NewColumnList([]string{"id", "name", "position", "age"})
  613. uniqueKeyColumns := NewColumnList([]string{"position"})
  614. {
  615. // test signed
  616. query, sharedArgs, uniqueKeyArgs, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  617. test.S(t).ExpectNil(err)
  618. expected := `
  619. update /* gh-ost mydb.tbl */
  620. mydb.tbl
  621. set id=?, name=?, position=?, age=?
  622. where
  623. ((position = ?))
  624. `
  625. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  626. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", int8(-17), int8(-2)}))
  627. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{int8(-3)}))
  628. }
  629. {
  630. // test unsigned
  631. sharedColumns.SetUnsigned("age")
  632. uniqueKeyColumns.SetUnsigned("position")
  633. query, sharedArgs, uniqueKeyArgs, err := BuildDMLUpdateQuery(databaseName, tableName, tableColumns, sharedColumns, sharedColumns, uniqueKeyColumns, valueArgs, whereArgs)
  634. test.S(t).ExpectNil(err)
  635. expected := `
  636. update /* gh-ost mydb.tbl */
  637. mydb.tbl
  638. set id=?, name=?, position=?, age=?
  639. where
  640. ((position = ?))
  641. `
  642. test.S(t).ExpectEquals(normalizeQuery(query), normalizeQuery(expected))
  643. test.S(t).ExpectTrue(reflect.DeepEqual(sharedArgs, []interface{}{3, "testname", int8(-17), uint8(254)}))
  644. test.S(t).ExpectTrue(reflect.DeepEqual(uniqueKeyArgs, []interface{}{uint8(253)}))
  645. }
  646. }