sqlite3_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. package sqlite3
  2. import (
  3. "database/sql"
  4. "fmt"
  5. "testing"
  6. "time"
  7. "github.com/doug-martin/goqu/v9"
  8. "github.com/doug-martin/goqu/v9/dialect/mysql"
  9. _ "github.com/mattn/go-sqlite3"
  10. "github.com/stretchr/testify/suite"
  11. )
  12. const (
  13. dropTable = "DROP TABLE IF EXISTS `entry`;"
  14. createTable = "CREATE TABLE `entry` (" +
  15. "`id` INTEGER PRIMARY KEY," +
  16. "`int` INT NOT NULL ," +
  17. "`float` FLOAT NOT NULL ," +
  18. "`string` VARCHAR(255) NOT NULL ," +
  19. "`time` DATETIME NOT NULL ," +
  20. "`bool` TINYINT NOT NULL ," +
  21. "`bytes` BLOB NOT NULL" +
  22. ");"
  23. insertDefaultReords = "INSERT INTO `entry` (`int`, `float`, `string`, `time`, `bool`, `bytes`) VALUES" +
  24. "(0, 0.000000, '0.000000', '2015-02-22 18:19:55', 1, '0.000000')," +
  25. "(1, 0.100000, '0.100000', '2015-02-22 19:19:55', 0, '0.100000')," +
  26. "(2, 0.200000, '0.200000', '2015-02-22 20:19:55', 1, '0.200000')," +
  27. "(3, 0.300000, '0.300000', '2015-02-22 21:19:55', 0, '0.300000')," +
  28. "(4, 0.400000, '0.400000', '2015-02-22 22:19:55', 1, '0.400000')," +
  29. "(5, 0.500000, '0.500000', '2015-02-22 23:19:55', 0, '0.500000')," +
  30. "(6, 0.600000, '0.600000', '2015-02-23 00:19:55', 1, '0.600000')," +
  31. "(7, 0.700000, '0.700000', '2015-02-23 01:19:55', 0, '0.700000')," +
  32. "(8, 0.800000, '0.800000', '2015-02-23 02:19:55', 1, '0.800000')," +
  33. "(9, 0.900000, '0.900000', '2015-02-23 03:19:55', 0, '0.900000');"
  34. )
  35. var dbURI = ":memory:"
  36. type (
  37. sqlite3Suite struct {
  38. suite.Suite
  39. db *goqu.Database
  40. }
  41. entry struct {
  42. ID uint32 `db:"id" goqu:"skipinsert,skipupdate"`
  43. Int int `db:"int"`
  44. Float float64 `db:"float"`
  45. String string `db:"string"`
  46. Time time.Time `db:"time"`
  47. Bool bool `db:"bool"`
  48. Bytes []byte `db:"bytes"`
  49. }
  50. )
  51. func (st *sqlite3Suite) SetupSuite() {
  52. fmt.Println(dbURI)
  53. db, err := sql.Open("sqlite3", dbURI)
  54. if err != nil {
  55. panic(err.Error())
  56. }
  57. st.db = goqu.New("sqlite3", db)
  58. }
  59. func (st *sqlite3Suite) SetupTest() {
  60. if _, err := st.db.Exec(dropTable); err != nil {
  61. panic(err)
  62. }
  63. if _, err := st.db.Exec(createTable); err != nil {
  64. panic(err)
  65. }
  66. if _, err := st.db.Exec(insertDefaultReords); err != nil {
  67. panic(err)
  68. }
  69. }
  70. func (st *sqlite3Suite) TestSelectSQL() {
  71. ds := st.db.From("entry")
  72. s, _, err := ds.Select("id", "float", "string", "time", "bool").ToSQL()
  73. st.NoError(err)
  74. st.Equal("SELECT `id`, `float`, `string`, `time`, `bool` FROM `entry`", s)
  75. s, _, err = ds.Where(goqu.C("int").Eq(10)).ToSQL()
  76. st.NoError(err)
  77. st.Equal("SELECT * FROM `entry` WHERE (`int` = 10)", s)
  78. s, args, err := ds.Prepared(true).Where(goqu.L("? = ?", goqu.C("int"), 10)).ToSQL()
  79. st.NoError(err)
  80. st.Equal([]interface{}{int64(10)}, args)
  81. st.Equal("SELECT * FROM `entry` WHERE `int` = ?", s)
  82. }
  83. func (st *sqlite3Suite) TestCompoundQueries() {
  84. ds1 := st.db.From("entry").Select("int").Where(goqu.C("int").Gt(0))
  85. ds2 := st.db.From("entry").Select("int").Where(goqu.C("int").Gt(5))
  86. var ids []int64
  87. err := ds1.Union(ds2).ScanVals(&ids)
  88. st.NoError(err)
  89. st.Equal([]int64{1, 2, 3, 4, 5, 6, 7, 8, 9}, ids)
  90. ids = ids[0:0]
  91. err = ds1.UnionAll(ds2).ScanVals(&ids)
  92. st.NoError(err)
  93. st.Equal([]int64{1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 7, 8, 9}, ids)
  94. ids = ids[0:0]
  95. err = ds1.Intersect(ds2).ScanVals(&ids)
  96. st.NoError(err)
  97. st.Equal([]int64{6, 7, 8, 9}, ids)
  98. }
  99. func (st *sqlite3Suite) TestQuery() {
  100. var entries []entry
  101. ds := st.db.From("entry")
  102. st.NoError(ds.Order(goqu.C("id").Asc()).ScanStructs(&entries))
  103. st.Len(entries, 10)
  104. floatVal := float64(0)
  105. baseDate, err := time.Parse(DialectOptions().TimeFormat, "2015-02-22 18:19:55")
  106. st.NoError(err)
  107. for i, entry := range entries {
  108. f := fmt.Sprintf("%f", floatVal)
  109. st.Equal(uint32(i+1), entry.ID)
  110. st.Equal(i, entry.Int)
  111. st.Equal(f, fmt.Sprintf("%f", entry.Float))
  112. st.Equal(f, entry.String)
  113. st.Equal([]byte(f), entry.Bytes)
  114. st.Equal(i%2 == 0, entry.Bool)
  115. st.Equal(baseDate.Add(time.Duration(i)*time.Hour), entry.Time)
  116. floatVal += float64(0.1)
  117. }
  118. entries = entries[0:0]
  119. st.NoError(ds.Where(goqu.C("bool").IsTrue()).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  120. st.Len(entries, 5)
  121. st.NoError(err)
  122. for _, entry := range entries {
  123. st.True(entry.Bool)
  124. }
  125. entries = entries[0:0]
  126. st.NoError(ds.Where(goqu.C("int").Gt(4)).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  127. st.Len(entries, 5)
  128. st.NoError(err)
  129. for _, entry := range entries {
  130. st.True(entry.Int > 4)
  131. }
  132. entries = entries[0:0]
  133. st.NoError(ds.Where(goqu.C("int").Gte(5)).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  134. st.Len(entries, 5)
  135. st.NoError(err)
  136. for _, entry := range entries {
  137. st.True(entry.Int >= 5)
  138. }
  139. entries = entries[0:0]
  140. st.NoError(ds.Where(goqu.C("int").Lt(5)).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  141. st.Len(entries, 5)
  142. st.NoError(err)
  143. for _, entry := range entries {
  144. st.True(entry.Int < 5)
  145. }
  146. entries = entries[0:0]
  147. st.NoError(ds.Where(goqu.C("int").Lte(4)).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  148. st.Len(entries, 5)
  149. st.NoError(err)
  150. for _, entry := range entries {
  151. st.True(entry.Int <= 4)
  152. }
  153. entries = entries[0:0]
  154. st.NoError(ds.Where(goqu.C("int").Between(goqu.Range(3, 6))).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  155. st.Len(entries, 4)
  156. st.NoError(err)
  157. for _, entry := range entries {
  158. st.True(entry.Int >= 3)
  159. st.True(entry.Int <= 6)
  160. }
  161. entries = entries[0:0]
  162. st.NoError(ds.Where(goqu.C("string").Eq("0.100000")).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  163. st.Len(entries, 1)
  164. st.NoError(err)
  165. for _, entry := range entries {
  166. st.Equal(entry.String, "0.100000")
  167. }
  168. entries = entries[0:0]
  169. st.NoError(ds.Where(goqu.C("string").Like("0.1%")).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  170. st.Len(entries, 1)
  171. st.NoError(err)
  172. for _, entry := range entries {
  173. st.Equal("0.100000", entry.String)
  174. }
  175. entries = entries[0:0]
  176. st.NoError(ds.Where(goqu.C("string").NotLike("0.1%")).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  177. st.Len(entries, 9)
  178. st.NoError(err)
  179. for _, entry := range entries {
  180. st.NotEqual("0.100000", entry.String)
  181. }
  182. entries = entries[0:0]
  183. st.NoError(ds.Where(goqu.C("string").IsNull()).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  184. st.Empty(entries)
  185. }
  186. func (st *sqlite3Suite) TestQuery_Prepared() {
  187. var entries []entry
  188. ds := st.db.From("entry").Prepared(true)
  189. st.NoError(ds.Order(goqu.C("id").Asc()).ScanStructs(&entries))
  190. st.Len(entries, 10)
  191. floatVal := float64(0)
  192. baseDate, err := time.Parse(DialectOptions().TimeFormat, "2015-02-22 18:19:55")
  193. st.NoError(err)
  194. for i, entry := range entries {
  195. f := fmt.Sprintf("%f", floatVal)
  196. st.Equal(uint32(i+1), entry.ID)
  197. st.Equal(i, entry.Int)
  198. st.Equal(f, fmt.Sprintf("%f", entry.Float))
  199. st.Equal(f, entry.String)
  200. st.Equal([]byte(f), entry.Bytes)
  201. st.Equal(i%2 == 0, entry.Bool)
  202. st.Equal(baseDate.Add(time.Duration(i)*time.Hour), entry.Time)
  203. floatVal += float64(0.1)
  204. }
  205. entries = entries[0:0]
  206. st.NoError(ds.Where(goqu.C("bool").IsTrue()).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  207. st.Len(entries, 5)
  208. st.NoError(err)
  209. for _, entry := range entries {
  210. st.True(entry.Bool)
  211. }
  212. entries = entries[0:0]
  213. st.NoError(ds.Where(goqu.C("int").Gt(4)).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  214. st.Len(entries, 5)
  215. st.NoError(err)
  216. for _, entry := range entries {
  217. st.True(entry.Int > 4)
  218. }
  219. entries = entries[0:0]
  220. st.NoError(ds.Where(goqu.C("int").Gte(5)).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  221. st.Len(entries, 5)
  222. st.NoError(err)
  223. for _, entry := range entries {
  224. st.True(entry.Int >= 5)
  225. }
  226. entries = entries[0:0]
  227. st.NoError(ds.Where(goqu.C("int").Lt(5)).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  228. st.Len(entries, 5)
  229. st.NoError(err)
  230. for _, entry := range entries {
  231. st.True(entry.Int < 5)
  232. }
  233. entries = entries[0:0]
  234. st.NoError(ds.Where(goqu.C("int").Lte(4)).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  235. st.Len(entries, 5)
  236. st.NoError(err)
  237. for _, entry := range entries {
  238. st.True(entry.Int <= 4)
  239. }
  240. entries = entries[0:0]
  241. st.NoError(ds.Where(goqu.C("int").Between(goqu.Range(3, 6))).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  242. st.Len(entries, 4)
  243. st.NoError(err)
  244. for _, entry := range entries {
  245. st.True(entry.Int >= 3)
  246. st.True(entry.Int <= 6)
  247. }
  248. entries = entries[0:0]
  249. st.NoError(ds.Where(goqu.C("string").Eq("0.100000")).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  250. st.Len(entries, 1)
  251. st.NoError(err)
  252. for _, entry := range entries {
  253. st.Equal(entry.String, "0.100000")
  254. }
  255. entries = entries[0:0]
  256. st.NoError(ds.Where(goqu.C("string").Like("0.1%")).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  257. st.Len(entries, 1)
  258. st.NoError(err)
  259. for _, entry := range entries {
  260. st.Equal("0.100000", entry.String)
  261. }
  262. entries = entries[0:0]
  263. st.NoError(ds.Where(goqu.C("string").NotLike("0.1%")).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  264. st.Len(entries, 9)
  265. st.NoError(err)
  266. for _, entry := range entries {
  267. st.NotEqual("0.100000", entry.String)
  268. }
  269. entries = entries[0:0]
  270. st.NoError(ds.Where(goqu.C("string").IsNull()).Order(goqu.C("id").Asc()).ScanStructs(&entries))
  271. st.Empty(entries)
  272. }
  273. func (st *sqlite3Suite) TestQuery_ValueExpressions() {
  274. type wrappedEntry struct {
  275. entry
  276. BoolValue bool `db:"bool_value"`
  277. }
  278. expectedDate, err := time.Parse("2006-01-02 15:04:05", "2015-02-22 19:19:55")
  279. st.NoError(err)
  280. ds := st.db.From("entry").Select(goqu.Star(), goqu.V(true).As("bool_value")).Where(goqu.Ex{"int": 1})
  281. var we wrappedEntry
  282. found, err := ds.ScanStruct(&we)
  283. st.NoError(err)
  284. st.True(found)
  285. st.Equal(we, wrappedEntry{
  286. entry{2, 1, 0.100000, "0.100000", expectedDate, false, []byte("0.100000")},
  287. true,
  288. })
  289. }
  290. func (st *sqlite3Suite) TestCount() {
  291. ds := st.db.From("entry")
  292. count, err := ds.Count()
  293. st.NoError(err)
  294. st.Equal(int64(10), count)
  295. count, err = ds.Where(goqu.C("int").Gt(4)).Count()
  296. st.NoError(err)
  297. st.Equal(int64(5), count)
  298. count, err = ds.Where(goqu.C("int").Gte(4)).Count()
  299. st.NoError(err)
  300. st.Equal(int64(6), count)
  301. count, err = ds.Where(goqu.C("string").Like("0.1%")).Count()
  302. st.NoError(err)
  303. st.Equal(int64(1), count)
  304. count, err = ds.Where(goqu.C("string").IsNull()).Count()
  305. st.NoError(err)
  306. st.Equal(int64(0), count)
  307. }
  308. func (st *sqlite3Suite) TestInsert() {
  309. ds := st.db.From("entry")
  310. now := time.Now()
  311. e := entry{Int: 10, Float: 1.000000, String: "1.000000", Time: now, Bool: true, Bytes: []byte("1.000000")}
  312. _, err := ds.Insert().Rows(e).Executor().Exec()
  313. st.NoError(err)
  314. var insertedEntry entry
  315. found, err := ds.Where(goqu.C("int").Eq(10)).ScanStruct(&insertedEntry)
  316. st.NoError(err)
  317. st.True(found)
  318. st.True(insertedEntry.ID > 0)
  319. entries := []entry{
  320. {Int: 11, Float: 1.100000, String: "1.100000", Time: now, Bool: false, Bytes: []byte("1.100000")},
  321. {Int: 12, Float: 1.200000, String: "1.200000", Time: now, Bool: true, Bytes: []byte("1.200000")},
  322. {Int: 13, Float: 1.300000, String: "1.300000", Time: now, Bool: false, Bytes: []byte("1.300000")},
  323. {Int: 14, Float: 1.400000, String: "1.400000", Time: now, Bool: true, Bytes: []byte("1.400000")},
  324. {Int: 14, Float: 1.400000, String: `abc'd"e"f\\gh\n\ri\x00`, Time: now, Bool: true, Bytes: []byte("1.400000")},
  325. }
  326. _, err = ds.Insert().Rows(entries).Executor().Exec()
  327. st.NoError(err)
  328. var newEntries []entry
  329. st.NoError(ds.Where(goqu.C("int").In([]uint32{11, 12, 13, 14})).ScanStructs(&newEntries))
  330. for i, e := range newEntries {
  331. st.Equal(entries[i].Int, e.Int)
  332. st.Equal(entries[i].Float, e.Float)
  333. st.Equal(entries[i].String, e.String)
  334. st.Equal(entries[i].Time.UTC().Format(mysql.DialectOptions().TimeFormat), e.Time.Format(mysql.DialectOptions().TimeFormat))
  335. st.Equal(entries[i].Bool, e.Bool)
  336. st.Equal(entries[i].Bytes, e.Bytes)
  337. }
  338. _, err = ds.Insert().Rows(
  339. entry{Int: 15, Float: 1.500000, String: "1.500000", Time: now, Bool: false, Bytes: []byte("1.500000")},
  340. entry{Int: 16, Float: 1.600000, String: "1.600000", Time: now, Bool: true, Bytes: []byte("1.600000")},
  341. entry{Int: 17, Float: 1.700000, String: "1.700000", Time: now, Bool: false, Bytes: []byte("1.700000")},
  342. entry{Int: 18, Float: 1.800000, String: "1.800000", Time: now, Bool: true, Bytes: []byte("1.800000")},
  343. entry{Int: 18, Float: 1.800000, String: `abc'd"e"f\\gh\n\ri\x00`, Time: now, Bool: true, Bytes: []byte("1.800000")},
  344. ).Executor().Exec()
  345. st.NoError(err)
  346. newEntries = newEntries[0:0]
  347. st.NoError(ds.Where(goqu.C("int").In([]uint32{15, 16, 17, 18})).ScanStructs(&newEntries))
  348. st.Len(newEntries, 5)
  349. }
  350. func (st *sqlite3Suite) TestInsert_returning() {
  351. ds := st.db.From("entry")
  352. now := time.Now()
  353. e := entry{Int: 10, Float: 1.000000, String: "1.000000", Time: now, Bool: true, Bytes: []byte("1.000000")}
  354. _, err := ds.Insert().Rows(e).Returning(goqu.Star()).Executor().ScanStruct(&e)
  355. st.Error(err)
  356. }
  357. func (st *sqlite3Suite) TestUpdate() {
  358. ds := st.db.From("entry")
  359. var e entry
  360. found, err := ds.Where(goqu.C("int").Eq(9)).Select("id").ScanStruct(&e)
  361. st.NoError(err)
  362. st.True(found)
  363. e.Int = 11
  364. _, err = ds.Where(goqu.C("id").Eq(e.ID)).Update().Set(e).Executor().Exec()
  365. st.NoError(err)
  366. count, err := ds.Where(goqu.C("int").Eq(11)).Count()
  367. st.NoError(err)
  368. st.Equal(int64(1), count)
  369. }
  370. func (st *sqlite3Suite) TestUpdateReturning() {
  371. ds := st.db.From("entry")
  372. var id uint32
  373. _, err := ds.
  374. Where(goqu.C("int").Eq(11)).
  375. Update().
  376. Set(map[string]interface{}{"int": 9}).
  377. Returning("id").
  378. Executor().ScanVal(&id)
  379. st.Error(err)
  380. st.EqualError(err, "goqu: dialect does not support RETURNING clause [dialect=sqlite3]")
  381. }
  382. func (st *sqlite3Suite) TestDelete() {
  383. ds := st.db.From("entry")
  384. var e entry
  385. found, err := ds.Where(goqu.C("int").Eq(9)).Select("id").ScanStruct(&e)
  386. st.NoError(err)
  387. st.True(found)
  388. _, err = ds.Where(goqu.C("id").Eq(e.ID)).Delete().Executor().Exec()
  389. st.NoError(err)
  390. count, err := ds.Count()
  391. st.NoError(err)
  392. st.Equal(int64(9), count)
  393. var id uint32
  394. found, err = ds.Where(goqu.C("id").Eq(e.ID)).ScanVal(&id)
  395. st.NoError(err)
  396. st.False(found)
  397. e = entry{}
  398. found, err = ds.Where(goqu.C("int").Eq(8)).Select("id").ScanStruct(&e)
  399. st.NoError(err)
  400. st.True(found)
  401. st.NotEqual(int64(0), e.ID)
  402. id = 0
  403. _, err = ds.Where(goqu.C("id").Eq(e.ID)).Delete().Returning("id").Executor().ScanVal(&id)
  404. st.EqualError(err, "goqu: dialect does not support RETURNING clause [dialect=sqlite3]")
  405. }
  406. func TestSqlite3Suite(t *testing.T) {
  407. suite.Run(t, new(sqlite3Suite))
  408. }