FMDBMoreTests.swift 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. import XCTest
  2. import SQLite3
  3. @testable import FMDB
  4. final class FMDBMoreTests: FMDBTempDBTests {
  5. let tempPath = "/tmp/FMDBMoreTests.db"
  6. override func setUp() {
  7. }
  8. func testFunkyTableNames() throws {
  9. do {
  10. let db = emptyDatabase(path: tempPath)
  11. XCTAssert(try db.open())
  12. try db.executeUpdate("create table '234 fds' (foo text)")
  13. XCTAssertFalse(db.hadError(), "table creation should have succeeded")
  14. let rs = try db.getTableSchema("234 fds")
  15. XCTAssertTrue(try rs.next(), "Schema should have succeded");
  16. rs.close()
  17. XCTAssertFalse(db.hadError(), "There shouldn't be any errors")
  18. }
  19. catch {
  20. print(error)
  21. XCTAssert(false)
  22. }
  23. }
  24. func testBoolForQuery() throws {
  25. do {
  26. let db = emptyDatabase(path: tempPath)
  27. XCTAssert(try db.open())
  28. var result = try db.boolForQuery("SELECT ? not null", "")
  29. XCTAssertTrue(result, "Empty strings should be considered true");
  30. result = try db.boolForQuery("SELECT ? not null", NSMutableData())
  31. XCTAssertTrue(result, "Empty mutable data should be considered true");
  32. result = try db.boolForQuery("SELECT ? not null", NSData())
  33. XCTAssertTrue(result, "Empty data should be considered true");
  34. }
  35. catch {
  36. print(error)
  37. XCTAssert(false)
  38. }
  39. }
  40. func testIntForQuery() throws {
  41. do {
  42. let db = emptyDatabase(path: tempPath)
  43. XCTAssert(try db.open())
  44. try db.executeUpdate("create table t1 (a integer)")
  45. try db.executeUpdate("insert into t1 values (?)", 5)
  46. XCTAssertEqual(db.changes(), 1, "There should only be one change")
  47. let ia = try db.intForQuery("select a from t1 where a = ?", 5)
  48. XCTAssertEqual(ia, 5, "foo");
  49. }
  50. catch {
  51. print(error)
  52. XCTAssert(false)
  53. }
  54. }
  55. func testDateForQuery() throws {
  56. do {
  57. let db = emptyDatabase(path: tempPath)
  58. XCTAssert(try db.open())
  59. let date = NSDate()
  60. try db.executeUpdate("create table datetest (a double, b double, c double)")
  61. try db.executeUpdate("insert into datetest (a, b, c) values (?, ?, 0)", NSNull(), date)
  62. XCTAssertEqual(db.changes(), 1, "There should only be one change")
  63. let foo = try db.dateForQuery("select b from datetest where c = 0")
  64. let interval = foo!.timeIntervalSince(date as Date)
  65. XCTAssertEqual(interval, 0.0, accuracy: 1.0, "Dates should be the same to within a second");
  66. }
  67. catch {
  68. print(error)
  69. XCTAssert(false)
  70. }
  71. }
  72. func testValidate() throws {
  73. // This is just ported over from the other tests. It's kind of dumb, but whatever.
  74. do {
  75. let db = emptyDatabase(path: tempPath)
  76. XCTAssert(try db.open())
  77. try db.validateSQL("create table datetest (a double, b double, c double)")
  78. XCTAssertFalse(db.hadError())
  79. // XCTAssertNil(error, @"There should be no error object");
  80. }
  81. catch {
  82. print(error)
  83. XCTAssert(false)
  84. }
  85. }
  86. func testFailValidate() throws {
  87. var hadErr = false
  88. // This is just ported over from the other tests. It's kind of dumb, but whatever.
  89. do {
  90. let db = emptyDatabase(path: tempPath)
  91. XCTAssert(try db.open())
  92. try db.validateSQL("blah blah blah")
  93. }
  94. catch {
  95. print(error)
  96. hadErr = true
  97. }
  98. XCTAssertTrue(hadErr)
  99. }
  100. func testTableExists() throws {
  101. let db = emptyDatabase(path: tempPath)
  102. do {
  103. XCTAssert(try db.open())
  104. try db.executeUpdate("create table t4 (a text, b text)")
  105. XCTAssertTrue(db.tableExists("t4"));
  106. XCTAssertFalse(db.tableExists("thisdoesntexist"));
  107. let x = Optional("table")
  108. XCTAssertTrue(x == "table")
  109. let rs = db.getSchema()
  110. if let rs = rs {
  111. while (try rs.next()) {
  112. print("\(String(describing: rs.string("type")))")
  113. XCTAssertTrue(rs.string("type") == "table");
  114. }
  115. }
  116. }
  117. catch {
  118. print(error)
  119. print("\(String(describing: db.lastErrorMessage()))")
  120. XCTAssertTrue(false)
  121. }
  122. }
  123. func testColumnExists() throws {
  124. let db = emptyDatabase(path: tempPath)
  125. do {
  126. XCTAssert(try db.open())
  127. try db.executeUpdate("create table nulltest (a text, b text)")
  128. XCTAssertTrue(db.columnExists("a", inTable: "nulltest"))
  129. XCTAssertTrue(db.columnExists("b", inTable: "nulltest"))
  130. XCTAssertFalse(db.columnExists("c", inTable: "nulltest"))
  131. }
  132. catch {
  133. print(error)
  134. print("\(String(describing: db.lastErrorMessage()))")
  135. XCTAssertTrue(false)
  136. }
  137. }
  138. func testUserVersion() throws {
  139. let db = emptyDatabase(path: tempPath)
  140. XCTAssert(try db.open())
  141. db.setUserVersion(10)
  142. XCTAssertTrue(db.userVersion() == 10);
  143. }
  144. func fourCharCode(from string : String) -> FourCharCode
  145. {
  146. return string.utf16.reduce(0, {$0 << 8 + FourCharCode($1)})
  147. }
  148. func testApplicationID() throws {
  149. let appID = NSHFSTypeCodeFromFileType(NSFileTypeForHFSTypeCode(fourCharCode(from: "fmdb")))
  150. let db = emptyDatabase(path: tempPath)
  151. XCTAssert(try db.open())
  152. db.setApplicationID(appID)
  153. let rAppID = db.applicationID()
  154. XCTAssertEqual(rAppID, appID);
  155. db.setApplicationIDString("acrn")
  156. let s = db.applicationIDString()
  157. XCTAssertEqual(s, "acrn")
  158. }
  159. func testFailOnUnopenedDatabase() throws {
  160. let db = emptyDatabase(path: tempPath)
  161. XCTAssert(try db.open())
  162. db.close()
  163. var hadError = false
  164. do {
  165. let rs = try db.executeQuery("select * from table")
  166. XCTAssertNil(rs, "Shouldn't get results from an empty table")
  167. }
  168. catch {
  169. hadError = true
  170. }
  171. XCTAssertTrue(hadError)
  172. XCTAssertTrue(db.hadError())
  173. }
  174. func testFailOnBadStatement() throws {
  175. let db = emptyDatabase(path: tempPath)
  176. XCTAssert(try db.open())
  177. var hadError = false
  178. do {
  179. let rs = try db.executeQuery("blah blah blah")
  180. XCTAssertNil(rs, "Shouldn't get results from an empty table")
  181. }
  182. catch {
  183. hadError = true
  184. }
  185. XCTAssertTrue(hadError)
  186. XCTAssertTrue(db.hadError())
  187. }
  188. func testSelectULL() throws {
  189. let db = emptyDatabase(path: tempPath)
  190. XCTAssert(try db.open())
  191. do {
  192. try db.executeUpdate("create table ull (a integer)")
  193. try db.executeUpdate("insert into ull (a) values (?)", CUnsignedLongLong.max);
  194. let rs = try db.executeQuery("select a from ull")
  195. while (try rs.next()) {
  196. XCTAssertEqual(rs.unsignedLongLongInt(0), UInt64.max, "Result should be \(CUnsignedLongLong.max)")
  197. XCTAssertEqual(rs.unsignedLongLongInt("a"), UInt64.max, "Result should be \(CUnsignedLongLong.max)")
  198. }
  199. }
  200. catch {
  201. print(error)
  202. XCTAssertTrue(false)
  203. }
  204. }
  205. func testSelectByColumnName() throws {
  206. let db = populatedOpenDatabase(path: tempPath)
  207. do {
  208. let rs = try db.executeQuery("select rowid,* from test where a = ?", "hi")
  209. XCTAssertNotNil(rs, "Should have a non-nil result set");
  210. while (try rs.next()) {
  211. XCTAssertTrue(rs.int("c") > 0)
  212. XCTAssertNotNil(rs.string("b"), "Should have non-nil string for 'b'");
  213. XCTAssertNotNil(rs["b"], "Should have non-nil string for 'b' subscript");
  214. XCTAssertNotNil(rs.string("a"), "Should have non-nil string for 'a'");
  215. XCTAssertNotNil(rs.string("rowid"), "Should have non-nil string for 'rowid'");
  216. XCTAssertNotNil(rs.string("d"), "Should have non-nil date for 'd'");
  217. XCTAssertTrue(rs.double("d") > 0)
  218. XCTAssertTrue(rs.double("e") > 0)
  219. XCTAssertTrue(type(of: rs["b"]) == type(of: ""))
  220. XCTAssertTrue(type(of: rs["e"]) == type(of: 2.2))
  221. XCTAssertTrue(rs.columnNameForIndex(0) == "rowid", "Wrong column name for result set column number")
  222. XCTAssertTrue(rs.columnNameForIndex(1) == "a", "Wrong column name for result set column number")
  223. }
  224. XCTAssertFalse(db.hasOpenResultSets())
  225. XCTAssertFalse(db.hadError())
  226. }
  227. catch {
  228. print(error)
  229. XCTAssertTrue(false)
  230. }
  231. }
  232. func testInvalidColumnNames() throws {
  233. let db = populatedOpenDatabase(path: tempPath)
  234. do {
  235. let rs = try db.executeQuery("select rowid, a, b, c from test")
  236. XCTAssertNotNil(rs, "Should have a non-nil result set");
  237. let invalidColumnName = "foobar"
  238. while (try rs.next()) {
  239. XCTAssertNil(rs[invalidColumnName], "Invalid column name should return nil")
  240. XCTAssertNil(rs.string(invalidColumnName), "Invalid column name should return nil")
  241. XCTAssertEqual(rs.UTF8String(invalidColumnName), nil, "Invalid column name should return nil")
  242. XCTAssertNil(rs.date(invalidColumnName), "Invalid column name should return nil")
  243. XCTAssertNil(rs.data(invalidColumnName), "Invalid column name should return nil")
  244. XCTAssertNil(rs.dataNoCopy(invalidColumnName), "Invalid column name should return nil")
  245. }
  246. XCTAssertFalse(db.hasOpenResultSets())
  247. XCTAssertFalse(db.hadError())
  248. }
  249. catch {
  250. print(error)
  251. XCTAssertTrue(false)
  252. }
  253. }
  254. func testInvalidColumnIndexes() throws {
  255. let db = populatedOpenDatabase(path: tempPath)
  256. do {
  257. let rs = try db.executeQuery("select rowid, a, b, c from test")
  258. XCTAssertNotNil(rs, "Should have a non-nil result set");
  259. let invalidColumnIndex = Int32(999)
  260. while (try rs.next()) {
  261. XCTAssertNil(rs[invalidColumnIndex], "Invalid column name should return nil")
  262. XCTAssertNil(rs.string(invalidColumnIndex), "Invalid column name should return nil")
  263. XCTAssertEqual(rs.UTF8String(invalidColumnIndex), nil, "Invalid column name should return nil")
  264. XCTAssertNil(rs.date(invalidColumnIndex), "Invalid column name should return nil")
  265. XCTAssertNil(rs.data(invalidColumnIndex), "Invalid column name should return nil")
  266. XCTAssertNil(rs.dataNoCopy(invalidColumnIndex), "Invalid column name should return nil")
  267. }
  268. XCTAssertFalse(db.hasOpenResultSets())
  269. XCTAssertFalse(db.hadError())
  270. }
  271. catch {
  272. print(error)
  273. XCTAssertTrue(false)
  274. }
  275. }
  276. func testBusyRetryTimeout() throws {
  277. let db = populatedOpenDatabase(path: tempPath)
  278. do {
  279. try db.executeUpdate("create table t1 (a integer)")
  280. try db.executeUpdate("insert into t1 values (?)", 5)
  281. db.setMaxBusyRetryTimeInterval(2)
  282. let newDB = FMDatabase.database(with: tempPath)
  283. try newDB.open()
  284. let rs = try newDB.executeQuery("select rowid,* from test where a = ?", "hi'")
  285. try rs.next() // just grab one... which will keep the db locked
  286. XCTAssertFalse(try db.executeUpdate("insert into t1 values (5)"), "Insert should fail because the db is locked by a read")
  287. XCTAssertEqual(db.lastErrorCode(), SQLITE_BUSY, "SQLITE_BUSY should be the last error");
  288. rs.close()
  289. newDB.close()
  290. XCTAssertTrue(try db.executeUpdate("insert into t1 values (5)"), "The database shouldn't be locked at this point")
  291. XCTAssertFalse(db.hasOpenResultSets())
  292. XCTAssertFalse(db.hadError())
  293. }
  294. catch {
  295. print(error)
  296. XCTAssertTrue(false)
  297. }
  298. }
  299. func testCaseSensitiveResultDictionary() throws {
  300. let db = populatedOpenDatabase(path: tempPath)
  301. do {
  302. // case sensitive result dictionary test
  303. try db.executeUpdate("create table cs (aRowName integer, bRowName text)")
  304. try db.executeUpdate("insert into cs (aRowName, bRowName) values (?, ?)", 1, "hello")
  305. XCTAssertFalse(db.hadError(), "Shouldn't have any errors")
  306. let rs = try db.executeQuery("select * from cs")
  307. while (try rs.next()) {
  308. let d = rs.resultDictionary()
  309. print("dict is: \(d)")
  310. let t = type(of:d["aRowName"])
  311. print("the type is : \(t)")
  312. XCTAssertNotNil(d["aRowName"], "aRowName should be non-nil");
  313. XCTAssertNil(d["arowname"], "arowname should be nil");
  314. XCTAssertNotNil(d["bRowName"], "bRowName should be non-nil");
  315. XCTAssertNil(d["browname"], "browname should be nil");
  316. }
  317. XCTAssertFalse(db.hasOpenResultSets())
  318. XCTAssertFalse(db.hadError())
  319. }
  320. catch {
  321. print(error)
  322. XCTAssertTrue(false)
  323. }
  324. }
  325. func testBoolInsert() throws {
  326. let db = populatedOpenDatabase(path: tempPath)
  327. do {
  328. // case sensitive result dictionary test
  329. try db.executeUpdate("create table btest (aRowName integer)")
  330. try db.executeUpdate("insert into btest (aRowName) values (?)", true)
  331. XCTAssertFalse(db.hadError(), "Shouldn't have any errors")
  332. let rs = try db.executeQuery("select * from btest")
  333. while (try rs.next()) {
  334. XCTAssertTrue(rs.bool(0), "first column should be true.");
  335. XCTAssertTrue(rs.int(0) == 1, "first column should be equal to 1 - it was \(rs.int(0)).");
  336. }
  337. XCTAssertFalse(db.hasOpenResultSets())
  338. XCTAssertFalse(db.hadError())
  339. }
  340. catch {
  341. print(error)
  342. XCTAssertTrue(false)
  343. }
  344. }
  345. func testNamedParametersCount() throws {
  346. let db = populatedOpenDatabase(path: tempPath)
  347. do {
  348. XCTAssertTrue(try db.executeUpdate("create table namedparamcounttest (a text, b text, c integer, d double)"))
  349. var dictionaryArgs = [String: Any]()
  350. dictionaryArgs["a"] = "Text1"
  351. dictionaryArgs["b"] = "Text2"
  352. dictionaryArgs["c"] = 1
  353. dictionaryArgs["d"] = 2.0
  354. XCTAssertTrue(try db.executeUpdate("insert into namedparamcounttest values (:a, :b, :c, :d)", withParameterDictionary: dictionaryArgs))
  355. var rs = try db.executeQuery("select * from namedparamcounttest")
  356. XCTAssertNotNil(rs);
  357. XCTAssertTrue(try rs.next())
  358. XCTAssertTrue(rs.string("a") == "Text1")
  359. XCTAssertTrue(rs.string("b") == "Text2")
  360. XCTAssertTrue(rs.int("c") == 1)
  361. XCTAssertTrue(rs.double("d") == 2.0)
  362. rs.close()
  363. // note that at this point, dictionaryArgs has way more values than we need, but the query should still work since
  364. // a is in there, and that's all we need.
  365. rs = try db.executeQuery("select * from namedparamcounttest where a = :a", withParameterDictionary:dictionaryArgs)
  366. XCTAssertNotNil(rs);
  367. XCTAssertTrue(try rs.next())
  368. rs.close()
  369. // ***** Please note the following codes *****
  370. dictionaryArgs = [String: Any]()
  371. dictionaryArgs["a"] = "NewText1"
  372. dictionaryArgs["b"] = "NewText2"
  373. dictionaryArgs["OneMore"] = "OneMoreText"
  374. XCTAssertTrue(try db.executeUpdate("update namedparamcounttest set a = :a, b = :b where b = 'Text2'", withParameterDictionary:dictionaryArgs))
  375. }
  376. catch {
  377. print(error)
  378. XCTAssertTrue(false)
  379. }
  380. }
  381. func testBlobs() throws {
  382. let db = populatedOpenDatabase(path: tempPath)
  383. do {
  384. try db.executeUpdate("create table blobTable (a text, b blob)")
  385. let binSHBinary = try Data(contentsOf: URL(fileURLWithPath: "/bin/sh"))
  386. try db.executeUpdate("insert into blobTable (a, b) values (?, ?)", "bin/sh", binSHBinary)
  387. let rs = try db.executeQuery("select b from blobTable where a = ?", "bin/sh")
  388. XCTAssertTrue(try rs.next());
  389. let readData = rs.data("b")
  390. XCTAssertTrue(readData == binSHBinary)
  391. let readDataNoCopy = rs.dataNoCopy("b");
  392. XCTAssertTrue(readDataNoCopy == binSHBinary)
  393. rs.close()
  394. XCTAssertFalse(db.hasOpenResultSets())
  395. XCTAssertFalse(db.hadError())
  396. }
  397. catch {
  398. print(error)
  399. XCTAssertTrue(false)
  400. }
  401. }
  402. func testNullValues() throws {
  403. let db = populatedOpenDatabase(path: tempPath)
  404. do {
  405. try db.executeUpdate("create table t2 (a integer, b integer)")
  406. let rc = try db.executeUpdate("insert into t2 values (?, ?)", NSNull(), 5)
  407. XCTAssertTrue(rc, "Failed to insert a nil value");
  408. let rs = try db.executeQuery("select * from t2")
  409. while (try rs.next()) {
  410. XCTAssertNil(rs.string(0), "Wasn't able to retrieve a null string");
  411. XCTAssert(rs.string(1) == "5")
  412. }
  413. XCTAssertFalse(db.hasOpenResultSets())
  414. XCTAssertFalse(db.hadError())
  415. }
  416. catch {
  417. print(error)
  418. XCTAssertTrue(false)
  419. }
  420. }
  421. func testNestedResultSets() throws {
  422. let db = populatedOpenDatabase(path: tempPath)
  423. do {
  424. let rs = try db.executeQuery("select * from t3")
  425. while (try rs.next()) {
  426. let foo = rs.int(0)
  427. let newValue = foo + 11
  428. try db.executeUpdate("update t3 set a = ? where a = ?", newValue, foo)
  429. let rs2 = try db.executeQuery("select a from t3 where a = ?", newValue)
  430. try rs2.next()
  431. XCTAssertTrue(rs2.int(0) == newValue)
  432. rs2.close()
  433. }
  434. XCTAssertFalse(db.hasOpenResultSets())
  435. XCTAssertFalse(db.hadError())
  436. }
  437. catch {
  438. print(error)
  439. XCTAssertTrue(false)
  440. }
  441. }
  442. func testNSNullInsertion() throws {
  443. let db = populatedOpenDatabase(path: tempPath)
  444. do {
  445. try db.executeUpdate("create table nulltest (a text, b text)")
  446. try db.executeUpdate("insert into nulltest (a, b) values (?, ?)", NSNull(), "a")
  447. try db.executeUpdate("insert into nulltest (a, b) values (?, ?)", nil, "b")
  448. let rs = try db.executeQuery("select * from nulltest")
  449. while (try rs.next()) {
  450. XCTAssertNil(rs.string(0));
  451. XCTAssertNotNil(rs.string(1));
  452. }
  453. XCTAssertFalse(db.hasOpenResultSets())
  454. XCTAssertFalse(db.hadError())
  455. }
  456. catch {
  457. print(error)
  458. XCTAssertTrue(false)
  459. }
  460. }
  461. func testNSNullDates() throws {
  462. let date = Date()
  463. let db = populatedOpenDatabase(path: tempPath)
  464. do {
  465. try db.executeUpdate("create table datetest (a double, b double, c double)")
  466. try db.executeUpdate("insert into datetest (a, b, c) values (?, ?, 0)", nil, date)
  467. let rs = try db.executeQuery("select * from datetest")
  468. while (try rs.next()) {
  469. let b = rs.date(1)
  470. let c = rs.date(2)
  471. XCTAssertNil(rs.date(0));
  472. XCTAssertNotNil(c, "zero date shouldn't be nil");
  473. XCTAssertEqual(b!.timeIntervalSince(date), 0.0, accuracy: 1.0, "Dates should be the same to within a second");
  474. XCTAssertEqual(c!.timeIntervalSince1970 , 0.0, accuracy: 1.0, "Dates should be the same to within a second");
  475. }
  476. XCTAssertFalse(db.hasOpenResultSets())
  477. XCTAssertFalse(db.hadError())
  478. }
  479. catch {
  480. print(error)
  481. XCTAssertTrue(false)
  482. }
  483. }
  484. func testLotsOfNULLs() throws {
  485. let db = populatedOpenDatabase(path: tempPath)
  486. do {
  487. let binSHBinary = try Data(contentsOf: URL(fileURLWithPath: "/bin/sh"))
  488. try db.executeUpdate("create table nulltest2 (s text, d data, i integer, f double, b integer)")
  489. try db.executeUpdate("insert into nulltest2 (s, d, i, f, b) values (?, ?, ?, ?, ?)", "hi", binSHBinary, 12, 4.4, true)
  490. try db.executeUpdate("insert into nulltest2 (s, d, i, f, b) values (?, ?, ?, ?, ?)" , nil, nil, nil, nil, NSNull());
  491. let rs = try db.executeQuery("select * from nulltest2")
  492. while (try rs.next()) {
  493. let i = rs.int(2)
  494. if (i == 12) {
  495. // it's the first row we inserted.
  496. XCTAssertFalse(rs.columnIsNull(0))
  497. XCTAssertFalse(rs.columnIsNull(1))
  498. XCTAssertFalse(rs.columnIsNull(2))
  499. XCTAssertFalse(rs.columnIsNull(3))
  500. XCTAssertFalse(rs.columnIsNull(4))
  501. XCTAssertTrue(rs.columnIsNull(5))
  502. XCTAssertTrue(rs.data("d") == binSHBinary)
  503. XCTAssertNil(rs.data("notthere"))
  504. XCTAssertNil(rs.string(-2), "Negative columns should return nil results")
  505. XCTAssertTrue(rs.bool(4))
  506. XCTAssertTrue(rs.bool("b"))
  507. XCTAssertEqual(4.4, rs.double("f"), accuracy: 0.0000001, "Saving a float and returning it as a double shouldn't change the result much");
  508. XCTAssertEqual(rs.int("i"), 12)
  509. XCTAssertEqual(rs.int(2), 12)
  510. XCTAssertEqual(rs.int(12), 0, "Non-existent columns should return zero for ints")
  511. XCTAssertEqual(rs.int("not there"), 0, "Non-existent columns should return zero for ints")
  512. XCTAssertEqual(rs.longLongInt("i"), 12)
  513. XCTAssertEqual(rs.longLongInt(2), 12)
  514. }
  515. else {
  516. XCTAssertTrue(rs.columnIsNull(0))
  517. XCTAssertTrue(rs.columnIsNull(1))
  518. XCTAssertTrue(rs.columnIsNull(2))
  519. XCTAssertTrue(rs.columnIsNull(3))
  520. XCTAssertTrue(rs.columnIsNull(4))
  521. XCTAssertTrue(rs.columnIsNull(5))
  522. XCTAssertNil(rs.data("d"))
  523. }
  524. }
  525. XCTAssertFalse(db.hasOpenResultSets())
  526. XCTAssertFalse(db.hadError())
  527. }
  528. catch {
  529. print(error)
  530. XCTAssertTrue(false)
  531. }
  532. }
  533. func testUTF8Strings() throws {
  534. let db = populatedOpenDatabase(path: tempPath)
  535. do {
  536. try db.executeUpdate("create table utest (a text)")
  537. try db.executeUpdate("insert into utest values (?)", "/übertest")
  538. let rs = try db.executeQuery("select * from utest where a = ?", "/übertest")
  539. XCTAssertTrue(try rs.next());
  540. rs.close();
  541. XCTAssertFalse(db.hasOpenResultSets())
  542. XCTAssertFalse(db.hadError())
  543. }
  544. catch {
  545. print(error)
  546. XCTAssertTrue(false)
  547. }
  548. }
  549. func testArgumentsInArray() throws {
  550. let db = emptyDatabase(path: tempPath)
  551. do {
  552. try db.open()
  553. try db.executeUpdate("create table testOneHundredTwelvePointTwo (a text, b integer)")
  554. try db.executeUpdate("insert into testOneHundredTwelvePointTwo values (?, ?)", ["one", 2])
  555. try db.executeUpdate("insert into testOneHundredTwelvePointTwo values (?, ?)", ["one", 3])
  556. let rs = try db.executeQuery("select * from testOneHundredTwelvePointTwo where b > ?", [1])
  557. XCTAssertTrue(try rs.next());
  558. XCTAssertTrue(rs.hasAnotherRow())
  559. XCTAssertFalse(db.hadError())
  560. XCTAssertTrue(rs.string(0) == "one")
  561. XCTAssertEqual(rs.int(1), 2)
  562. XCTAssertTrue(try rs.next())
  563. XCTAssertEqual(rs.int(1), 3)
  564. XCTAssertFalse(try rs.next())
  565. XCTAssertFalse(rs.hasAnotherRow())
  566. XCTAssertFalse(db.hasOpenResultSets())
  567. XCTAssertFalse(db.hadError())
  568. }
  569. catch {
  570. print(error)
  571. XCTAssertTrue(false)
  572. }
  573. }
  574. func testColumnNamesContainingPeriods() throws {
  575. let db = emptyDatabase(path: tempPath)
  576. do {
  577. try db.open()
  578. try db.executeUpdate("create table t4 (a text, b text)")
  579. try db.executeUpdate("insert into t4 (a, b) values (?, ?)", "one", "two")
  580. var rs = try db.executeQuery("select t4.a as 't4.a', t4.b from t4")
  581. XCTAssertTrue(try rs.next())
  582. XCTAssertTrue(rs.string("t4.a") == "one")
  583. XCTAssertTrue(rs.string("b") == "two")
  584. //XCTAssertEqual(strcmp((const char*)[rs UTF8StringForColumn:@"b"], "two"), 0, @"String comparison should return zero");
  585. rs.close()
  586. XCTAssertTrue(try db.executeUpdate("drop table t4", []))
  587. XCTAssertTrue(try db.executeUpdate("create table t4 (a text, b text)", []))
  588. try db.executeUpdate("insert into t4 (a, b) values (?, ?)", ["one", "two"])
  589. rs = try db.executeQuery("select t4.a as 't4.a', t4.b from t4", [])
  590. XCTAssertTrue(try rs.next())
  591. XCTAssertTrue(rs.string("t4.a") == "one")
  592. XCTAssertTrue(rs.string("b") == "two")
  593. rs.close()
  594. XCTAssertFalse(db.hasOpenResultSets())
  595. XCTAssertFalse(db.hadError())
  596. }
  597. catch {
  598. print(error)
  599. XCTAssertTrue(false)
  600. }
  601. }
  602. }