Skip to content

Commit

Permalink
Added String extension to handle substring operations, Completed code…
Browse files Browse the repository at this point in the history
… to determine column data type
  • Loading branch information
FahimF committed Jun 13, 2014
1 parent 646809f commit 26fa4fe
Showing 1 changed file with 73 additions and 105 deletions.
178 changes: 73 additions & 105 deletions SQLiteDB.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,31 @@
import Foundation
import UIKit

extension String {
func positionOf(sub:String)->Int {
var pos = -1
let range = self.rangeOfString(sub)
pos = distance(self.startIndex, range.startIndex)
return pos
}

func subStringFrom(pos:Int)->String {
var substr = ""
let start = advance(self.startIndex, pos)
let range = start...self.endIndex
substr = self[range]
return substr
}

func subStringTo(pos:Int)->String {
var substr = ""
let end = advance(self.startIndex, pos-1)
let range = self.startIndex...end
substr = self[range]
return substr
}
}

class SQLiteDB {
let DB_NAME:CString = "data.db"
var db:COpaquePointer = nil
Expand Down Expand Up @@ -146,7 +171,7 @@ class SQLiteDB {
var fetchColumnInfo = true
var columnCount:CInt = 0
var columnNames = String[]()
var columnTypes = String[]()
var columnTypes = CInt[]()
result = sqlite3_step(stmt)
while result == SQLITE_ROW {
// Should we get column info?
Expand Down Expand Up @@ -179,8 +204,7 @@ class SQLiteDB {
// SQL escape string
func esc(str: String)->String {
var cstr:CString = str.bridgeToObjectiveC().cString()
// var ptr:CMutablePointer<CString> = &cstr
// cstr = sqlite3_vmprintf("%Q", CVaListPointer(fromUnsafePointer: ptr))
// cstr = sqlite3_vmprintf("%Q", CVaListPointer(fromUnsafePointer: &cstr))
return ""
}

Expand Down Expand Up @@ -210,9 +234,51 @@ class SQLiteDB {
}

// Get column type
func getColumnType(index:CInt, stmt:COpaquePointer)->String {
var type = ""

func getColumnType(index:CInt, stmt:COpaquePointer)->CInt {
var type:CInt = 0
// Column types - http://www.sqlite.org/datatype3.html (section 2.2 table column 1)
let blobTypes = ["BINARY", "BLOB", "VARBINARY"]
let charTypes = ["CHAR", "CHARACTER", "CLOB", "NATIONAL VARYING CHARACTER", "NATIVE CHARACTER", "NCHAR", "NVARCHAR", "TEXT", "VARCHAR", "VARIANT", "VARYING CHARACTER"]
let dateTypes = ["DATE", "DATETIME", "TIME", "TIMESTAMP"]
let intTypes = ["BIGINT", "BIT", "BOOL", "BOOLEAN", "INT", "INT2", "INT8", "INTEGER", "MEDIUMINT", "SMALLINT", "TINYINT"]
let nullTypes = ["NULL"]
let realTypes = ["DECIMAL", "DOUBLE", "DOUBLE PRECISION", "FLOAT", "NUMERIC", "REAL"]
// Determine type of column - http://www.sqlite.org/c3ref/c_blob.html
let buf:CString? = sqlite3_column_decltype(stmt, index)
println("SQLiteDB - Got column type: \(buf)")
if (buf) {
var tmp = String.fromCString(buf!).uppercaseString
// Remove brackets
let pos = tmp.positionOf("(")
if pos > 0 {
tmp = tmp.subStringTo(pos)
}
// Remove unsigned?
// Remove spaces
// Is the data type in any of the pre-set values?
println("SQLiteDB - Cleaned up column type: \(tmp)")
if contains(intTypes, tmp) {
return SQLITE_INTEGER
}
if contains(realTypes, tmp) {
return SQLITE_FLOAT
}
if contains(charTypes, tmp) {
return SQLITE_TEXT
}
if contains(blobTypes, tmp) {
return SQLITE_BLOB
}
if contains(nullTypes, tmp) {
return SQLITE_NULL
}
if contains(dateTypes, tmp) {
return SQLITE_NULL + 1
}
return SQLITE_TEXT
} else {
type = sqlite3_column_type(stmt, index)
}
return type
}

Expand All @@ -224,102 +290,4 @@ class SQLiteDB {
value = String.fromCString(cstr)
return value
}
}

/*
-(id)columnValueAtIndex:(int)column withColumnType:(int)columnType inStatement:(sqlite3_stmt *)statement {
if (columnType == SQLITE_INTEGER) {
return @(sqlite3_column_int(statement, column));
}
if (columnType == SQLITE_FLOAT) {
return [[NSDecimalNumber alloc] initWithDouble:sqlite3_column_double(statement, column)];
}
if (columnType == SQLITE_TEXT) {
const char *text = (const char *)sqlite3_column_text(statement, column);
if (text != NULL) {
return @(text);
}
}
if (columnType == SQLITE_BLOB) {
return [NSData dataWithBytes:sqlite3_column_blob(statement, column) length:sqlite3_column_bytes(statement, column)];
}
if (columnType == SQLITE_DATE) {
const char *text = (const char *)sqlite3_column_text(statement, column);
if (text != NULL) {
NSString *buf = @(text);
NSCharacterSet *set = [NSCharacterSet characterSetWithCharactersInString:@"-:"];
if ([buf rangeOfCharacterFromSet:set].location != NSNotFound) {
time_t t;
struct tm tm;
strptime([buf cStringUsingEncoding:NSUTF8StringEncoding], "%Y-%m-%d %H:%M:%S", &tm);
tm.tm_isdst = -1;
t = mktime(&tm);
return [NSDate dateWithTimeIntervalSince1970:t + [[NSTimeZone localTimeZone] secondsFromGMT]];
}
}
return [[NSDecimalNumber alloc] initWithDouble:sqlite3_column_double(statement, column)];
}
return [NSNull null];
}


-(NSString *)esc:(NSString *)str {
if (!str || [str length] == 0) {
return @"";
}
return @(sqlite3_mprintf("%Q", [str cStringUsingEncoding:NSUTF8StringEncoding]));
}

-(NSArray *)query:(NSString *)sql {
return [self query:sql asObject:[NSMutableDictionary class]];
}


-(SEL)selectorForSettingColumnName:(NSString *)column {
return NSSelectorFromString([NSString stringWithFormat:@"set%@:", [NSString capitalizeFirstCharacterInString:column]]);
}

-(int)columnTypeAtIndex:(int)column inStatement:(sqlite3_stmt *)statement {
// Declared data types - http://www.sqlite.org/datatype3.html (section 2.2 table column 1)
const NSSet *blobTypes = [NSSet setWithObjects:@"BINARY", @"BLOB", @"VARBINARY", nil];
const NSSet *charTypes = [NSSet setWithObjects:@"CHAR", @"CHARACTER", @"CLOB", @"NATIONAL VARYING CHARACTER", @"NATIVE CHARACTER", @"NCHAR", @"NVARCHAR", @"TEXT", @"VARCHAR", @"VARIANT", @"VARYING CHARACTER", nil];
const NSSet *dateTypes = [NSSet setWithObjects:@"DATE", @"DATETIME", @"TIME", @"TIMESTAMP", nil];
const NSSet *intTypes = [NSSet setWithObjects:@"BIGINT", @"BIT", @"BOOL", @"BOOLEAN", @"INT", @"INT2", @"INT8", @"INTEGER", @"MEDIUMINT", @"SMALLINT", @"TINYINT", nil];
const NSSet *nullTypes = [NSSet setWithObjects:@"NULL", nil];
const NSSet *realTypes = [NSSet setWithObjects:@"DECIMAL", @"DOUBLE", @"DOUBLE PRECISION", @"FLOAT", @"NUMERIC", @"REAL", nil];
// Determine data type of the column - http://www.sqlite.org/c3ref/c_blob.html
const char *columnType = (const char *)sqlite3_column_decltype(statement, column);
if (columnType != NULL) {
NSString *dataType = [@(columnType) uppercaseString];
NSRange end = [dataType rangeOfString:@"("];
if (end.location != NSNotFound) {
dataType = [dataType substringWithRange:NSMakeRange(0, end.location)];
}
if ([dataType hasPrefix:@"UNSIGNED"]) {
dataType = [dataType substringWithRange:NSMakeRange(0, 8)];
}
dataType = [dataType stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([intTypes containsObject:dataType]) {
return SQLITE_INTEGER;
}
if ([realTypes containsObject:dataType]) {
return SQLITE_FLOAT;
}
if ([charTypes containsObject:dataType]) {
return SQLITE_TEXT;
}
if ([blobTypes containsObject:dataType]) {
return SQLITE_BLOB;
}
if ([nullTypes containsObject:dataType]) {
return SQLITE_NULL;
}
if ([dateTypes containsObject:dataType]) {
return SQLITE_DATE;
}
return SQLITE_TEXT;
}
return sqlite3_column_type(statement, column);
}

*/
}

0 comments on commit 26fa4fe

Please sign in to comment.