Skip to content

Commit

Permalink
Added support for Data
Browse files Browse the repository at this point in the history
  • Loading branch information
noursandid committed May 15, 2024
1 parent ba2015c commit f2da733
Show file tree
Hide file tree
Showing 13 changed files with 210 additions and 51 deletions.
54 changes: 54 additions & 0 deletions Library/ClassHandler/Map/SundeedQLiteMap+Normal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,42 @@ public func <~> (left: inout [Float?]?, right: SundeedQLiteMap) {
right.addColumn(attribute: left, withColumnName: right.key!)
}
}
public func <~> (left: inout [Data], right: SundeedQLiteMap) {
if !right.fetchingColumns {
if let value = right.currentValue as? [Data] {
left = value.compactMap({$0})
}
} else {
right.addColumn(attribute: left, withColumnName: right.key!)
}
}
public func <~> (left: inout [Data?], right: SundeedQLiteMap) {
if !right.fetchingColumns {
if let value = right.currentValue as? [Data] {
left = value.map({$0})
}
} else {
right.addColumn(attribute: left, withColumnName: right.key!)
}
}
public func <~> (left: inout [Data]?, right: SundeedQLiteMap) {
if !right.fetchingColumns {
if let value = right.currentValue as? [Data] {
left = value.compactMap({$0})
}
} else {
right.addColumn(attribute: left, withColumnName: right.key!)
}
}
public func <~> (left: inout [Data?]?, right: SundeedQLiteMap) {
if !right.fetchingColumns {
if let value = right.currentValue as? [Data] {
left = value.map({$0})
}
} else {
right.addColumn(attribute: left, withColumnName: right.key!)
}
}
public func <~> (left: inout [UIImage], right: SundeedQLiteMap) {
if !right.fetchingColumns {
if let value = right.currentValue as? [String] {
Expand Down Expand Up @@ -626,6 +662,24 @@ public func <~> (left: inout Float, right: SundeedQLiteMap) {
right.addColumn(attribute: left, withColumnName: right.key!)
}
}
public func <~> (left: inout Data?, right: SundeedQLiteMap) {
if !right.fetchingColumns {
if let rightValue = right.currentValue as? Data {
left = rightValue
}
} else {
right.addColumn(attribute: left, withColumnName: right.key!)
}
}
public func <~> (left: inout Data, right: SundeedQLiteMap) {
if !right.fetchingColumns {
if let value = right.currentValue as? Data {
left = value
}
} else {
right.addColumn(attribute: left, withColumnName: right.key!)
}
}
public func <~> (left: inout UIImage?, right: SundeedQLiteMap) {
if !right.fetchingColumns {
if let rightValue = right.currentValue as? String {
Expand Down
19 changes: 12 additions & 7 deletions Library/Main/Processor/Processors/CreateTableProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,25 @@ class CreateTableProcessor {
if let firstAttribute = attribute.first {
try createTableIfNeeded(for: firstAttribute)
}
} else
if attribute is [Any] {
} else if attribute is [Any] {
createTableForPrimitiveDataTypes(withTableName: columnName)
}
createTableStatement.addColumn(with: columnName)

if attribute is Data {
createTableStatement.addColumn(with: columnName, type: .blob)
} else {
createTableStatement.addColumn(with: columnName, type: .text)
}
if columnName == "index" {
throw SundeedQLiteError.cantUseNameIndex(tableName: object.tableName)
}
}
if objects[Sundeed.shared.primaryKey] != nil {
createTableStatement.withPrimaryKey()
}
let query: String? = createTableStatement.build()
SundeedQLiteConnection.pool.execute(query: query)
let statement: String? = createTableStatement.build()
SundeedQLiteConnection.pool.execute(query: statement,
parameters: nil)
Sundeed.shared.tables.append(object.tableName)
}
}
Expand All @@ -46,9 +51,9 @@ class CreateTableProcessor {
if !Sundeed.shared.tables.contains(tableName) {
let createTableStatement = StatementBuilder()
.createTableStatement(tableName: tableName)
.addColumn(with: Sundeed.shared.valueColumnName)
.addColumn(with: Sundeed.shared.valueColumnName, type: .text)
.build()
SundeedQLiteConnection.pool.execute(query: createTableStatement)
SundeedQLiteConnection.pool.execute(query: createTableStatement, parameters: nil)
Sundeed.shared.tables.append(tableName)
}
}
Expand Down
31 changes: 18 additions & 13 deletions Library/Main/Processor/Processors/RetrieveProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,22 @@ class RetrieveProcessor {
}

func fetchStatementResult(statement: OpaquePointer?,
columns: [Int : String],
columns: [(columnName: String, columnType: ParameterType)],
objectWrapper: ObjectWrapper,
subObjectHandler: (_ objectType: String) -> ObjectWrapper?) -> [[String: Any]] {
var array: [[String: Any]] = []
while sqlite3_step(statement) == SQLITE_ROW {
var dictionary: [String: Any] = [:]
var primaryValue: String?
for column in columns {
if let databaseValue = sqlite3_column_text(statement, Int32(column.key)) {
for (index, column) in columns.enumerated() {
if case .blob = column.columnType,
let databaseValue = sqlite3_column_blob(statement, Int32(index)) {
let size = Int(sqlite3_column_bytes(statement, Int32(index)))
let value: Data = Data(bytes: databaseValue, count: size)
dictionary[column.columnName] = value
} else if let databaseValue = sqlite3_column_text(statement, Int32(index)) {
let value: String = normalizeColumnValue(databaseValue)
let columnName = column.value
let columnName = column.columnName
if value != Sundeed.shared.databaseNull {
dictionary[columnName] = value
}
Expand Down Expand Up @@ -119,9 +124,9 @@ class RetrieveProcessor {
if sqlite3_prepare_v2(database, selectStatement, -1, &statement, nil) == SQLITE_OK {
let columns = getDatabaseColumns(forTable: table)
var array: [String] = []
for column in columns where column.value == Sundeed.shared.valueColumnName {
for (index, column) in columns.enumerated() where column.columnName == Sundeed.shared.valueColumnName {
while sqlite3_step(statement) == SQLITE_ROW {
if let columnValue = sqlite3_column_text(statement, Int32(column.key)) {
if let columnValue = sqlite3_column_text(statement, Int32(index)) {
let value: String = String(cString: columnValue)
if value != Sundeed.shared.databaseNull {
array.append(value.replacingOccurrences(of: "\\\"", with: "\""))
Expand All @@ -135,23 +140,23 @@ class RetrieveProcessor {
SundeedQLiteConnection.pool.closeConnection(database: database)
return nil
}
func getDatabaseColumns(forTable table: String) -> [Int: String] {
func getDatabaseColumns(forTable table: String) -> [(columnName: String, columnType: ParameterType)] {
let database = try? SundeedQLiteConnection.pool.getConnection(toWrite: false)
var columnsStatement: OpaquePointer?
var array: [String] = []
var dictionary: [Int: String] = [:]
var array: [(columnName: String, columnType: ParameterType)] = []
sqlite3_prepare_v2(database,
"PRAGMA table_info(\(table));",-1,
&columnsStatement, nil)
while sqlite3_step(columnsStatement) == SQLITE_ROW {
if let columnName = sqlite3_column_text(columnsStatement, 1) {
array.append(String(cString: columnName))
if let columnName = sqlite3_column_text(columnsStatement, 1),
let columnType = sqlite3_column_text(columnsStatement, 2) {
array.append((columnName: String(cString: columnName),
columnType: ParameterType(typeString: String(cString: columnType))))
}
}
array.enumerated().forEach({dictionary[$0] = $1})
columnsStatement = nil
SundeedQLiteConnection.pool.closeConnection(database: database)
return dictionary
return array
}
func normalizeColumnValue(_ columnValue: UnsafePointer<UInt8>) -> String {
String(cString: columnValue).replacingOccurrences(of: "\\\"", with: "\"")
Expand Down
16 changes: 13 additions & 3 deletions Library/Main/Processor/Processors/SaveProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ class SaveProcessor {
completion?()
throw SundeedQLiteError.primaryKeyError(tableName: object.tableName)
}
} else if let attribute = attribute as? Data {
if objects[Sundeed.shared.primaryKey] as? String != nil {
insertStatement.add(key: columnName,
value: attribute)
} else {
completion?()
throw SundeedQLiteError.primaryKeyError(tableName: object.tableName)
}
} else if let attribute = attribute as? [UIImage?] {
let compactAttribute = attribute.compactMap({$0})
if compactAttribute.count > 0,
Expand Down Expand Up @@ -162,8 +170,9 @@ class SaveProcessor {
insertStatement.add(key: columnName, value: String(describing: attribute))
}
}
let query = insertStatement.build()
SundeedQLiteConnection.pool.execute(query: query, completion:
let statement = insertStatement.build()
SundeedQLiteConnection.pool.execute(query: statement?.query,
parameters: statement?.parameters, completion:
{
depth = self.completionIfNeeded(depth: depth, completion: completion)
})
Expand All @@ -189,7 +198,8 @@ class SaveProcessor {
.add(key: Sundeed.shared.foreignKey, value: foreignKey)
.add(key: Sundeed.shared.valueColumnName, value: String(describing: string))
.build()
SundeedQLiteConnection.pool.execute(query: insertStatement, completion: {
SundeedQLiteConnection.pool.execute(query: insertStatement?.query,
parameters: insertStatement?.parameters, completion: {
depth = self.completionIfNeeded(depth: depth) {
completion?()
}
Expand Down
5 changes: 3 additions & 2 deletions Library/Main/Processor/Processors/UpdateProcessor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,9 @@ class UpdateProcessor {
}
}
updateStatement.withFilters(filters)
let query: String? = updateStatement.build()
SundeedQLiteConnection.pool.execute(query: query, completion:
let statement = updateStatement.build()
SundeedQLiteConnection.pool.execute(query: statement?.query,
parameters: statement?.parameters, completion:
{
depth = self.completionIfNeeded(depth: depth, completion: completion)
})
Expand Down
14 changes: 9 additions & 5 deletions Library/Main/Statements/CreateTableStatement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,19 @@
import Foundation

class CreateTableStatement {
enum ColumnType: String {
case text = "TEXT"
case blob = "BLOB"
}
private var tableName: String
private var hasPrimaryKey: Bool = false
private var columnNames: [String] = []
private var columns: [(name: String, type: String)] = []
init(with tableName: String) {
self.tableName = tableName
}
@discardableResult
func addColumn(with columnName: String) -> Self {
columnNames.append(columnName)
func addColumn(with columnName: String, type: ColumnType) -> Self {
columns.append((name: columnName, type: type.rawValue))
return self
}
@discardableResult
Expand All @@ -27,8 +31,8 @@ class CreateTableStatement {
}
func build() -> String? {
var statement = "CREATE TABLE IF NOT EXISTS \(tableName) (\(Sundeed.shared.offlineID) INTEGER PRIMARY KEY, \(Sundeed.shared.foreignKey) TEXT, \(Sundeed.shared.fieldNameLink) TEXT"
for columnName in columnNames {
statement.append(",\(columnName) TEXT")
for column in columns {
statement.append(",\(column.name) \(column.type)")
}
if hasPrimaryKey {
statement.append(",CONSTRAINT unq\(tableName) UNIQUE (\(Sundeed.shared.foreignKey),\(Sundeed.shared.primaryKey),\(Sundeed.shared.fieldNameLink))")
Expand Down
13 changes: 7 additions & 6 deletions Library/Main/Statements/InsertStatement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,29 @@ import Foundation

class InsertStatement: Statement {
private var tableName: String
private var keyValues: [(String, String?)] = []
private var keyValues: [(String, Any?)] = []
private var values: [ParameterType] = []
init(with tableName: String) {
self.tableName = tableName
}
@discardableResult
func add(key: String, value: String?) -> Self {
func add(key: String, value: Any?) -> Self {
keyValues.append((key, value))
return self
}
func build() -> String? {
func build() -> (query: String, parameters: [ParameterType])? {
guard !keyValues.isEmpty else { return nil }
var statement: String = "REPLACE INTO \(tableName) ("
addKeysAndValues(toStatement: &statement)
return statement
return (query: statement, parameters: values)
}
private func addKeysAndValues(toStatement statement: inout String) {
var valuesStatement: String = ") VALUES ("
for (index, (key, value)) in keyValues.enumerated() {
let value = value ?? ""
let quotation = getQuotation(forValue: value)
statement.append(key)
valuesStatement.append("\(quotation)\(value)\(quotation)")
valuesStatement.append("?")
values.append(getParameter(value))
let needed = isLastIndex(index: index, in: keyValues)
addSeparatorIfNeeded(separator: ", ",
forStatement: &statement,
Expand Down
7 changes: 7 additions & 0 deletions Library/Main/Statements/Statement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,11 @@ class Statement {
final func isLastIndex<T>(index: Int, in array: [T]) -> Bool {
index != array.count - 1
}
final func getParameter(_ value: Any) -> ParameterType {
if let value = value as? Data {
return .blob(value)
} else {
return .text("\(value)")
}
}
}
15 changes: 8 additions & 7 deletions Library/Main/Statements/UpdateStatement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import Foundation

class UpdateStatement: Statement {
private var tableName: String
private var keyValues: [(String, String)] = []
private var keyValues: [(String, Any?)] = []
private var values: [ParameterType] = []
private var filters: [SundeedExpression<Bool>] = []
init(with tableName: String) {
self.tableName = tableName
}
@discardableResult
func add(key: String, value: String) -> Self {
func add(key: String, value: Any?) -> Self {
keyValues.append((key, value))
return self
}
Expand All @@ -25,18 +26,18 @@ class UpdateStatement: Statement {
self.filters = filters.compactMap({$0})
return self
}
func build() -> String? {
func build() -> (query: String, parameters: [ParameterType])? {
guard !keyValues.isEmpty else { return nil }
var statement = "UPDATE \(tableName) SET "
addKeyValues(toStatement: &statement)
addFilters(toStatement: &statement)
return statement
return (query: statement, parameters: values)
}
private func addKeyValues(toStatement statement: inout String) {
for (index, (key, value)) in keyValues.enumerated() {
let value = value
let quotation = getQuotation(forValue: value)
statement.append("\(key) = \(quotation)\(value)\(quotation)")
let value = value ?? ""
statement.append("\(key) = ?")
values.append(getParameter(value))
addSeparatorIfNeeded(separator: ", ",
forStatement: &statement,
needed: isLastIndex(index: index, in: keyValues))
Expand Down
Loading

0 comments on commit f2da733

Please sign in to comment.