Tuukka Norri avatar Tuukka Norri committed 8a3094d

Default column values
- Changed parameter length arguments from int to size_t, since that is also used in libpq.
- Changed -PGTSExpressionOfType: to -PGTSExpressionOfType:connection: and made it work with all supported parameter types.

Comments (0)

Files changed (12)

Sources/BXDatabaseObjectModelStorage.m

 
 
 @implementation BXDatabaseObjectModelStorage
-__strong static id gSharedInstance = nil;
+__strong static volatile id gSharedInstance = nil;
 
 + (void) initialize
 {
 
 + (id) defaultStorage
 {
+	// No synchronization needed because this gets called from +initialize.
 	if (! gSharedInstance)
 	{
 		gSharedInstance = [[self alloc] init];

Sources/BXPGEntityConverter.m

         if (error)
             [errors addObject: error];
 		
-		[retval addObject: [currentEntity BXPGCreateStatementWithIDColumn: YES inSchema: schemaName errors: errors]];
+		[retval addObject: [currentEntity BXPGCreateStatementWithIDColumn: YES inSchema: schemaName connection: connection errors: errors]];
 		[retval addObject: [currentEntity BXPGPrimaryKeyConstraintInSchema: schemaName]];
 		[enabledRelations addObject: [currentEntity name]];
 		

Sources/NSAttributeDescription+BXPGAdditions.h

 
 @interface NSAttributeDescription (BXPGAdditions)
 - (BOOL) BXCanAddAttribute: (NSError **) outError;
-- (NSString *) BXPGAttributeDefinition;
+- (NSString *) BXPGAttributeDefinition: (PGTSConnection *) connection;
 - (NSArray *) BXPGAttributeConstraintsInSchema: (NSString *) schemaName;
 - (NSArray *) BXPGConstraintsForValidationPredicatesInSchema: (NSString *) schemaName
 												  connection: (PGTSConnection *) connection;

Sources/NSAttributeDescription+BXPGAdditions.m

 }
 
 
-- (NSString *) BXPGAttributeDefinition
+- (NSString *) BXPGAttributeDefinition: (PGTSConnection *) connection
 {
 	NSString* typeDefinition = [self BXPGValueType];
 	NSString* addition = @"";
 	id defaultValue = [self defaultValue];
 	if (defaultValue)
 	{
-		NSString* defaultExp = [defaultValue PGTSExpressionOfType: [self attributeType]];
-		addition = [NSString stringWithFormat: @"DEFAULT %@", defaultExp];
+		NSString* defaultExp = [defaultValue PGTSExpressionOfType: [self attributeType] connection: connection];
+		if (defaultExp)
+			addition = [NSString stringWithFormat: @"DEFAULT %@", defaultExp];
 	}
 	return [NSString stringWithFormat: @"\"%@\" %@ %@", [self name], typeDefinition, addition];
 }

Sources/NSEntityDescription+BXPGAdditions.h

 #import <Foundation/Foundation.h>
 #import <CoreData/CoreData.h>
 
+@class PGTSConnection;
+
 
 @interface NSEntityDescription (BXPGAdditions)
 - (NSString *) BXPGCreateStatementWithIDColumn: (BOOL) addSerialIDColumn 
 									  inSchema: (NSString *) schemaName
+									connection: (PGTSConnection *) connection
 										errors: (NSMutableArray *) errors;
 - (NSString *) BXPGPrimaryKeyConstraintInSchema: (NSString *) schemaName;
 @end

Sources/NSEntityDescription+BXPGAdditions.m

 @implementation NSEntityDescription (BXPGAdditions)
 - (NSString *) BXPGCreateStatementWithIDColumn: (BOOL) addSerialIDColumn 
 									  inSchema: (NSString *) schemaName
+									connection: (PGTSConnection *) connection
 										errors: (NSMutableArray *) errors
 {
 	Expect (schemaName);
 			[errors addObject: attrError];
 		else
 		{
-			NSString* attrDef = [currentProperty BXPGAttributeDefinition];
+			NSString* attrDef = [currentProperty BXPGAttributeDefinition: connection];
 			[attributeDefs addObject: attrDef];
 		}
 	}

Sources/NSString+PGTSAdditions.h

 
 @class PGTSConnection;
 
-PGTS_EXPORT
-NSString* PGTSReformatErrorMessage (NSString* message);
+PGTS_EXPORT char *PGTSCopyEscapedString (PGTSConnection *, const char *);
+PGTS_EXPORT NSString *PGTSReformatErrorMessage (NSString* message);
 
 @interface NSString (PGTSAdditions)
 - (NSString *) escapeForPGTSConnection: (PGTSConnection *) connection;

Sources/NSString+PGTSAdditions.m

 #import "PGTSConnection.h"
 
 
-PGTS_EXPORT
-NSString* PGTSReformatErrorMessage (NSString* message)
+char *
+PGTSCopyEscapedString (PGTSConnection *conn, const char *from)
+{
+	size_t length = strlen (from);
+    char* to = (char *) calloc (1 + 2 * length, sizeof (char));
+    PQescapeStringConn ([conn pgConnection], to, from, length, NULL);
+	return to;
+}
+
+
+NSString* 
+PGTSReformatErrorMessage (NSString* message)
 {
 	NSMutableString* result = [NSMutableString string];
 	NSCharacterSet* skipSet = [NSCharacterSet characterSetWithCharactersInString: @"\t"];
  */
 - (NSString *) escapeForPGTSConnection: (PGTSConnection *) connection
 {
-    const char* from = [self UTF8String];
-    size_t length = strlen (from);
-    char* to = (char *) calloc (1 + 2 * length, sizeof (char));
-    PQescapeStringConn ([connection pgConnection], to, from, length, NULL);
+    const char *from = [self UTF8String];
+	char *to = PGTSCopyEscapedString (connection, from);
     NSString* retval = [NSString stringWithUTF8String: to];
     free (to);
     return retval;

Sources/PGTSAdditions.m

 - (NSString *) PGTSEscapedObjectParameter: (PGTSConnection *) connection
 {
 	NSString* retval = nil;
-	int length = 0;
+	size_t length = 0;
 	const char* charParameter = [[self PGTSParameter: connection] PGTSParameterLength: &length connection: connection];
 	if (charParameter)
 	{

Sources/PGTSFoundationObjects.h

 @class PGTSConnection;
 @class PGTSTypeDescription;
 
+
 @interface NSObject (PGTSFoundationObjects)
 + (id) copyForPGTSResultSet: (PGTSResultSet *) set withCharacters: (const char *) value type: (PGTSTypeDescription *) type;
 + (id) copyForPGTSResultSet: (PGTSResultSet *) set withCharacters: (const char *) value type: (PGTSTypeDescription *) type columnIndex: (int) columnIndex;
 - (id) PGTSParameter: (PGTSConnection *) connection;
-- (const char *) PGTSParameterLength: (int *) length connection: (PGTSConnection *) connection;
+- (const char *) PGTSParameterLength: (size_t *) length connection: (PGTSConnection *) connection;
+- (id) PGTSExpressionOfType: (NSAttributeType) attrType connection: (PGTSConnection *) connection;
 - (BOOL) PGTSIsBinaryParameter;
 - (BOOL) PGTSIsCollection;
-- (id) PGTSExpressionOfType: (NSAttributeType) attrType;
 @end

Sources/PGTSFoundationObjects.m

 #import "PGTSColumnDescription.h"
 #import "PGTSDatabaseDescription.h"
 #import "PGTSResultSet.h"
+#import "NSString+PGTSAdditions.h"
 #import "BXLogger.h"
 #import "BXEnumerate.h"
 
 
+
 @implementation NSObject (PGTSFoundationObjects)
 + (id) copyForPGTSResultSet: (PGTSResultSet *) set withCharacters: (const char *) value type: (PGTSTypeDescription *) type columnIndex: (int) columnIndex
 {
 	return self;
 }
 
-- (const char *) PGTSParameterLength: (int *) length connection: (PGTSConnection *) connection
+- (const char *) PGTSParameterLength: (size_t *) length connection: (PGTSConnection *) connection
 {
     BXLogWarning (@"Returning NULL from NSObject's implementation for %@.", [self class]);
 	if (length)
 	return NO;
 }
 
-- (id) PGTSExpressionOfType: (NSAttributeType) attrType
+- (id) PGTSExpressionOfType: (NSAttributeType) attrType connection: (PGTSConnection *) connection
 {
-	return nil;
+	NSString *retval = nil;
+	size_t length = 0;
+	id param = [self PGTSParameter: connection];
+	
+	if ([param PGTSIsBinaryParameter])
+	{
+		size_t resultLength = 0;
+		unsigned char *escapedValue = NULL;
+		const unsigned char *value = (const unsigned char *) [param PGTSParameterLength: &length connection: connection];
+		escapedValue = PQescapeByteaConn ([connection pgConnection], value, length, &resultLength);
+		retval = [NSString stringWithFormat: @"'%s'", escapedValue];
+		PQfreemem (escapedValue);
+	}
+	else
+	{
+		char *escapedValue = NULL;
+		const char *value = [param PGTSParameterLength: &length connection: connection];
+		escapedValue = PGTSCopyEscapedString (connection, value);
+		retval = [NSString stringWithFormat: @"'%s'", escapedValue];
+		free (escapedValue);
+	}
+	
+	[param self]; // For GC.
+	return retval;
 }
 @end
 
     return [[[[NSString alloc] initWithUTF8String: value] decomposedStringWithCanonicalMapping] retain];
 }
 
-- (const char *) PGTSParameterLength: (int *) length connection: (PGTSConnection *) connection
+- (const char *) PGTSParameterLength: (size_t *) length connection: (PGTSConnection *) connection
 {
     if (connection)
     {
         *length = strlen (retval);
     return retval;
 }
-
-- (id) PGTSExpressionOfType: (NSAttributeType) attrType
-{
-	NSMutableString* retval = [NSMutableString stringWithString: self];
-	[retval replaceOccurrencesOfString: @"'" withString: @"\\'" options: 0 range: NSMakeRange (0, [retval length])];
-	[retval insertString: @"'" atIndex: 0];
-	[retval appendString: @"'"];
-	return retval;
-}
 @end
 
 
 	return retval;
 }
 
-- (const char *) PGTSParameterLength: (int *) length connection: (PGTSConnection *) connection
+- (const char *) PGTSParameterLength: (size_t *) length connection: (PGTSConnection *) connection
 {
     const char* retval = [self bytes];
     if (NULL != length)
 			}
             else
             {
-                int length = -1;
+                size_t length = SIZE_T_MAX;
                 const char* value = [[currentObject PGTSParameter: connection] 
 									 PGTSParameterLength: &length connection: connection];
                 
                 {
                     //If the length isn't known, wait for a NUL byte.
                     AppendBytes (impl, contents, "\"", 1);
-                    if ([currentObject PGTSIsBinaryParameter] && -1 != length)
+                    if ([currentObject PGTSIsBinaryParameter] && SIZE_T_MAX != length)
                     {
                         const char* end = value + length;
                         while (value < end)
     return [[NSNumber alloc] initWithLongLong: strtoll (value, NULL, 10)];
 }
 
-- (id) PGTSExpressionOfType: (NSAttributeType) attrType
+- (id) PGTSExpressionOfType: (NSAttributeType) attrType connection: (PGTSConnection *) connection
 {
-	id retval = self;
+	id retval = nil;
 	if (NSBooleanAttributeType == attrType)
 		retval = ([self boolValue] ? @"true" : @"false");
+	else
+		retval = [super PGTSExpressionOfType: attrType connection: connection];
 	return retval;
 }
 @end
 	return nil;
 }
 
-- (const char *) PGTSParameterLength: (int *) length connection: (PGTSConnection *) connection
+- (const char *) PGTSParameterLength: (size_t *) length connection: (PGTSConnection *) connection
 {
 	[self doesNotRecognizeSelector: _cmd];
 	return NULL;
 
 
 @implementation NSNull (PGTSFoundationObjects)
-- (const char *) PGTSParameterLength: (int *) length connection: (PGTSConnection *) connection
+- (const char *) PGTSParameterLength: (size_t *) length connection: (PGTSConnection *) connection
 {
 	if (length)
 		*length = 0;

Sources/PGTSQuery.m

 		{
 			BOOL isBinary = [[mParameters objectAtIndex: i] PGTSIsBinaryParameter];
 			id parameter = [parameterObjects objectAtIndex: i];
-			int length = 0;
+			size_t length = 0;
 			const char* value = [parameter PGTSParameterLength: &length connection: connection];
 			
 			paramTypes   [i] = InvalidOid;
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.