/* fetch values */
row = [channel fetchAttributes:attrs withZone:NULL];
+ self->defFlags.isNew = (row != nil) ? 0 : 1;
[channel cancelFetch];
/* remember values */
[self->values release]; self->values = nil;
- if (row != nil)
- self->values = [row mutableCopy];
- else
- self->values = [[NSMutableDictionary alloc] initWithCapacity:8];
+ self->values = (row != nil)
+ ? [row mutableCopy]
+ : [[NSMutableDictionary alloc] initWithCapacity:8];
[self->values removeObjectForKey:uidColumnName];
ASSIGN(self->lastFetch, [NSCalendarDate date]);
return YES;
}
+- (NSString *)formatValue:(id)_value forAttribute:(EOAttribute *)_attribute {
+ NSString *s;
+
+ if (![_value isNotNull])
+ return @"NULL";
+
+ if ([[_attribute externalType] hasPrefix:@"int"])
+ return [_value stringValue];
+
+ s = [_value stringValue];
+ s = [s stringByReplacingString:@"'" withString:@"''"];
+ s = [[@"'" stringByAppendingString:s] stringByAppendingString:@"'"];
+ return s;
+}
+
+- (NSString *)generateSQLForInsert {
+ NSMutableString *sql;
+ unsigned i, count;
+
+ if ([self->values count] == 0)
+ return nil;
+
+ sql = [NSMutableString stringWithCapacity:2048];
+
+ [sql appendString:@"INSERT INTO "];
+ [sql appendString:[[self tableURL] gcsTableName]];
+ [sql appendString:@" ( uid"];
+
+ for (i = 0, count = [self->fieldNames count]; i < count; i++) {
+ EOAttribute *attr;
+
+ attr = [self->attributes objectForKey:[self->fieldNames objectAtIndex:i]];
+ [sql appendString:@", "];
+ [sql appendString:[attr columnName]];
+ }
+
+ [sql appendString:@") VALUES ("];
+
+ [sql appendString:@"'"];
+ [sql appendString:[self uid]]; // TODO: escaping necessary?
+ [sql appendString:@"'"];
+
+ for (i = 0, count = [self->fieldNames count]; i < count; i++) {
+ EOAttribute *attr;
+ id value;
+
+ attr = [self->attributes objectForKey:[self->fieldNames objectAtIndex:i]];
+ value = [self->values objectForKey:[self->fieldNames objectAtIndex:i]];
+
+ [sql appendString:@", "];
+ [sql appendString:[self formatValue:value forAttribute:attr]];
+ }
+
+ [sql appendString:@")"];
+ return sql;
+}
+
- (NSString *)generateSQLForUpdate {
NSMutableString *sql;
unsigned i, count;
if (i != 0) [sql appendString:@", "];
[sql appendString:[attr columnName]];
-
- if ([value isNotNull]) {
- /* a rather limited set of supported value types */
-
- if ([[attr externalType] hasPrefix:@"int"])
- [sql appendFormat:@" = %i", [value intValue]];
- else {
- // TODO: any other escaping?! move to adaptor?
- value = [value stringValue];
- value = [value stringByReplacingString:@"'" withString:@"''"];
- [sql appendString:@" = '"];
- [sql appendString:value];
- [sql appendString:@"'"];
- }
- }
- else
- [sql appendString:@" = NULL"];
+ [sql appendString:@" = "];
+ [sql appendString:[self formatValue:value forAttribute:attr]];
}
[sql appendString:@" WHERE "];
/* run SQL */
- sql = [self generateSQLForUpdate];
+ sql = self->defFlags.isNew
+ ? [self generateSQLForInsert]
+ : [self generateSQLForUpdate];
if ((ex = [channel evaluateExpressionX:sql]) != nil) {
[self errorWithFormat:@"could not run SQL '%@': %@", sql, ex];
[cm releaseChannel:channel];
}
self->defFlags.modified = 0;
+ self->defFlags.isNew = 0;
return YES;
}
[self->attributes release]; self->attributes = nil;
[self->lastFetch release]; self->lastFetch = nil;
self->defFlags.modified = 0;
+ self->defFlags.isNew = 0;
}
/* typed accessors */