Skip to content

Commit

Permalink
Almost complete native date and datetime support for sqlite. What
Browse files Browse the repository at this point in the history
is missing is a cached data dictionary to determine date vs. datetime
on updates (see the FIXME in the changeset).

I'm striving here for database compatibility between a rails migration
generated database and activerecord.  This way I can prototype my
schema with a rails scaffold and populate my sqlite database with
test data from a rails app during iPhone development.

Sqlite appears to support date and datetime natively via a string.
  • Loading branch information
face committed Nov 30, 2008
1 parent 28cfe03 commit 25e1449
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 3 deletions.
4 changes: 3 additions & 1 deletion Source/Bindings/ARBaseArrayInterface.h
Expand Up @@ -33,7 +33,9 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef _ARBASE_ARRAYINTERFACE_H_
#define _ARBASE_ARRAYINTERFACE_H_
#ifndef TARGET_OS_IPHONE
#import <Cocoa/Cocoa.h>
#endif
#import <ActiveRecord/ARBase.h>

/*!
Expand Down Expand Up @@ -122,4 +124,4 @@
/*! Invokes setValue:forKey: on each of the receiver's records using the specified value and key. */
- (void)setValue:(id)value forKey:(NSString *)key;
@end
#endif _ARBASE_ARRAYINTERFACE_H_
#endif _ARBASE_ARRAYINTERFACE_H_
57 changes: 55 additions & 2 deletions Source/Connections/ARSQLiteConnection.m
Expand Up @@ -13,10 +13,15 @@

/*! @cond IGNORE */
@interface ARSQLiteConnection ()
NSDateFormatter *dateFormatter = nil;
- (sqlite3_stmt *)prepareQuerySQL:(NSString *)query;
- (void)finalizeQuery:(sqlite3_stmt *)query;
- (NSArray *)columnsForQuery:(sqlite3_stmt *)query;
- (id)valueForColumn:(unsigned int)colIndex query:(sqlite3_stmt *)query;
- (NSDate *)dateFromString:(NSString *)dateString;
- (NSDate *)dateTimeFromString:(NSString *)dateString;
- (NSString *)stringFromDate:(NSDate *)date;
- (NSString *)stringFromDateTime:(NSDate *)date;
@end
/*! @endcond */

Expand Down Expand Up @@ -87,7 +92,15 @@ - (NSArray *)executeSQL:(NSString *)sql substitutions:(NSDictionary *)substituti
sqlite3_bind_double(queryByteCode, i, [sub doubleValue]);
else if([sub isMemberOfClass:[NSNull class]])
sqlite3_bind_null(queryByteCode, i);
else
else if([sub isMemberOfClass:[NSDate class]] || [[sub className] isEqualToString:@"NSCFDate"] || [[sub className] isEqualToString:@"__NSCFDate"])
{
// FIXME: this is the wrong place to be doing expensive meta lookups.
// decltype is only for SELECT... For now just save it
// with the time till we have the data dictionary info here
NSString *str = nil;
str = [self stringFromDateTime:sub];
sqlite3_bind_text(queryByteCode, i, [str UTF8String], [str length], SQLITE_TRANSIENT);
} else
[NSException raise:@"Unrecognized object type" format:@"Active record doesn't know how to handle this type of object: %@ class: %@", sub, [sub className]];
}

Expand Down Expand Up @@ -191,6 +204,7 @@ - (void)finalizeQuery:(sqlite3_stmt *)query
- (id)valueForColumn:(unsigned int)colIndex query:(sqlite3_stmt *)query
{
int columnType = sqlite3_column_type(query, colIndex);
const char *decltype = nil;
switch(columnType)
{
case SQLITE_INTEGER:
Expand All @@ -207,7 +221,13 @@ - (id)valueForColumn:(unsigned int)colIndex query:(sqlite3_stmt *)query
return [NSNull null];
break;
case SQLITE_TEXT:
return [NSString stringWithUTF8String:(const char *)sqlite3_column_text(query, colIndex)];
decltype = sqlite3_column_decltype(query, colIndex);
if ( !strcmp(decltype, "date") )
return [self dateFromString:[NSString stringWithUTF8String:(const char *)sqlite3_column_text(query, colIndex)]];
else if ( !strcmp(decltype, "datetime") )
return [self dateTimeFromString:[NSString stringWithUTF8String:(const char *)sqlite3_column_text(query, colIndex)]];
else
return [NSString stringWithUTF8String:(const char *)sqlite3_column_text(query, colIndex)];
break;
default:
// It really shouldn't ever come to this.
Expand Down Expand Up @@ -243,6 +263,38 @@ - (BOOL)endTransaction
return YES;
}

- (NSDate *)dateFromString:(NSString *)dateString
{
if ( dateFormatter == nil )
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd"];
return ([dateFormatter dateFromString:dateString]);
}

- (NSString *)stringFromDate:(NSDate *)date
{
if ( dateFormatter == nil )
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd"];
return ([dateFormatter stringFromDate:date]);
}

- (NSDate *)dateTimeFromString:(NSString *)dateString
{
if ( dateFormatter == nil )
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSSS"];
return ([dateFormatter dateFromString:dateString]);
}

- (NSString *)stringFromDateTime:(NSDate *)date
{
if ( dateFormatter == nil )
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSSS"];
return ([dateFormatter stringFromDate:date]);
}

#pragma mark -
#pragma mark Cleanup
- (void)finalize
Expand All @@ -253,6 +305,7 @@ - (void)finalize
- (void)dealloc
{
[self closeConnection];
[dateFormatter release];
[super dealloc];
}
@end
Expand Down

0 comments on commit 25e1449

Please sign in to comment.