SwifterSQLiteDatabaseProxy.swift 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. //
  2. // SQLiteProxy.swift
  3. // Swifter
  4. // Copyright (c) 2014 Damian Kołakowski. All rights reserved.
  5. //
  6. import Foundation
  7. class SQLiteSequenceElement {
  8. let statementPointer: COpaquePointer
  9. init(pointer: COpaquePointer) {
  10. self.statementPointer = pointer
  11. }
  12. func string(column: Int32) -> String {
  13. if let value = String.fromCString(UnsafePointer<CChar>(sqlite3_column_text(statementPointer, column))) {
  14. return value
  15. }
  16. /// Should never happend :)
  17. /// From 'String.fromCString' documentation:
  18. /// Returns `nil` if the `CString` is `NULL` or if it contains ill-formed
  19. /// UTF-8 code unit sequences.
  20. return "????"
  21. }
  22. func integer(column: Int32) -> Int32 {
  23. return sqlite3_column_int(statementPointer, column)
  24. }
  25. func double(column: Int32) -> Double {
  26. return sqlite3_column_double(statementPointer, column)
  27. }
  28. }
  29. class SQLiteSequenceGenarator: GeneratorType {
  30. let statementPointer: COpaquePointer
  31. init(pointer: COpaquePointer) {
  32. self.statementPointer = pointer
  33. }
  34. func next() -> SQLiteSequenceElement? {
  35. if ( sqlite3_step(statementPointer) == SQLITE_ROW ) {
  36. return SQLiteSequenceElement(pointer: statementPointer)
  37. }
  38. sqlite3_finalize(statementPointer)
  39. return nil
  40. }
  41. }
  42. class SQLiteSequence: SequenceType {
  43. var statementPointer = COpaquePointer()
  44. init?(database: COpaquePointer, statement: String, error: NSErrorPointer? = nil) {
  45. let result = statement.withCString { sqlite3_prepare(database, $0, Int32(strlen($0)), &self.statementPointer, nil) };
  46. if result != SQLITE_OK {
  47. if let error = error { error.memory = err("Can't prepare statement: \(statement), Error: \(result)") }
  48. return nil
  49. }
  50. }
  51. func err(reason: String) -> NSError {
  52. return NSError(domain: "SQLiteSequence", code: 0, userInfo: [NSLocalizedDescriptionKey : reason])
  53. }
  54. func generate() -> SQLiteSequenceGenarator {
  55. return SQLiteSequenceGenarator(pointer: statementPointer)
  56. }
  57. }
  58. class SQLiteStatement: StringLiteralConvertible {
  59. typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
  60. typealias UnicodeScalarLiteralType = UnicodeScalarType
  61. let sqlStatement: String
  62. init(value: String) {
  63. self.sqlStatement = value
  64. }
  65. required init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
  66. self.sqlStatement = value
  67. }
  68. required init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
  69. self.sqlStatement = value
  70. }
  71. required init(stringLiteral value: StringLiteralType) {
  72. self.sqlStatement = value
  73. }
  74. func execute(databse: COpaquePointer, error: NSErrorPointer? = nil) -> SQLiteSequence? {
  75. return SQLiteSequence(database: databse, statement: sqlStatement, error: error)
  76. }
  77. }
  78. class SwifterSQLiteDatabaseProxy: SwifterDatabseProxy {
  79. let databaseName: String
  80. let typesMap = [ "TEXT": SwifterDatabseProxyType.String, "INT": .Integer, "REAL": .Float]
  81. init(name: String) {
  82. databaseName = name
  83. }
  84. func err(reason: String) -> NSError {
  85. return NSError(domain: "SwifterSQLiteDatabaseProxy", code: 0, userInfo: [NSLocalizedDescriptionKey : reason])
  86. }
  87. func scheme(error: NSErrorPointer?) -> [String: [(String, SwifterDatabseProxyType)]]? {
  88. var database = COpaquePointer()
  89. if ( SQLITE_OK != databaseName.withCString { sqlite3_open($0, &database) } ) {
  90. if let e = error { e.memory = err("Cant' open databse: \(databaseName)") }
  91. return nil
  92. }
  93. var scheme = [String: [(String, SwifterDatabseProxyType)]]()
  94. let tablesQuery: SQLiteStatement = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;";
  95. if let tables = tablesQuery.execute(database, error: error) {
  96. for table in map(tables, { $0.string(0) }) {
  97. if let columns = SQLiteStatement(value: "PRAGMA table_info('\(table)');").execute(database, error: error) {
  98. scheme[table] = map(columns) {
  99. if let swifterType = self.typesMap[$0.string(2)] { return ($0.string(1), swifterType) }
  100. return ($0.string(1), SwifterDatabseProxyType.Unknown)
  101. }
  102. }
  103. }
  104. sqlite3_close(database)
  105. return scheme
  106. } else {
  107. sqlite3_close(database)
  108. if let e = error { e.memory = err("Cant' query tables databse: \(tablesQuery)") }
  109. return nil
  110. }
  111. }
  112. func createTable(name: String, columns: [String: SwifterDatabseProxyType], error: NSErrorPointer?) -> Bool {
  113. return false
  114. }
  115. func deleteTable(name: String, error: NSErrorPointer?) -> Bool {
  116. return false
  117. }
  118. func insertColumn(table: String, column: String, error: NSErrorPointer?) -> Bool {
  119. return false
  120. }
  121. func deleteColumn(table: String, column: String, error: NSErrorPointer?) -> Bool {
  122. return false
  123. }
  124. func copyColumn(table: String, from: String, to: String, error: NSErrorPointer?) -> Bool {
  125. return false
  126. }
  127. func insertRow(table: String, value: [String: String], error: NSErrorPointer?) -> Int {
  128. return 0
  129. }
  130. func deleteRow(table: String, id: Int, error: NSErrorPointer?) -> Bool {
  131. return false
  132. }
  133. }