Index: Doxyfile ================================================================== --- Doxyfile +++ Doxyfile @@ -11,7 +11,7 @@ PREDEFINED = OF_DESIGNATED_INITIALIZER= \ OF_GENERIC(...)= \ OF_SENTINEL MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES -IGNORE_PREFIX = PG +IGNORE_PREFIX = PGSQL EXTRACT_STATIC = yes Index: src/ObjPgSQL.h ================================================================== --- src/ObjPgSQL.h +++ src/ObjPgSQL.h @@ -14,12 +14,12 @@ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -#import "PGResult.h" -#import "PGResultRow.h" -#import "PGConnection.h" +#import "PGSQLResult.h" +#import "PGSQLResultRow.h" +#import "PGSQLConnection.h" -#import "PGException.h" -#import "PGCommandFailedException.h" -#import "PGConnectionFailedException.h" +#import "PGSQLException.h" +#import "PGSQLExecuteCommandFailedException.h" +#import "PGSQLConnectionFailedException.h" DELETED src/PGConnection+Private.h Index: src/PGConnection+Private.h ================================================================== --- src/PGConnection+Private.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGConnection.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface PGConnection () -@property (readonly, nonatomic) PGconn *pg_connection; -@end - -OF_ASSUME_NONNULL_END DELETED src/PGConnection.h Index: src/PGConnection.h ================================================================== --- src/PGConnection.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#import - -#import "PGResult.h" - -OF_ASSUME_NONNULL_BEGIN - -/** @file */ - -/** - * @brief A result row. - */ -typedef OFDictionary OF_GENERIC(OFString *, id) *PGRow; - -/** - * @class PGConnection PGConnection.h ObjPgSQL/ObjPgSQL.h - * - * @brief A connection to a database. - */ -@interface PGConnection: OFObject -{ - PGconn *_connection; - OFDictionary OF_GENERIC(OFString *, OFString *) *_parameters; -} - -/** - * @brief The parameters for the database connection. See `PQconnectdb` in the - * PostgreSQL documentation. - */ -@property (nonatomic, copy) - OFDictionary OF_GENERIC(OFString *, OFString *) *parameters; - -/** - * @brief Connects to the database. - * - * @throw PGConnectionFailedException The connection failed - */ -- (void)connect; - -/** - * @brief Resets the connection to the database. - */ -- (void)reset; - -/** - * @brief Closes the connection to the database. - */ -- (void)close; - -/** - * @brief Executes the specified command. - * - * @param command The command to execute - * @return The result of the command, if any - * @throw PGCommandFailedException Executing the command failed. - */ -- (nullable PGResult *)executeCommand: (OFConstantString *)command; - -/** - * @brief Executes the specified command. - * - * @param command The command to execute - * @param firstParameter First parameter for the command - * @return The result of the command, if any - * @throw PGCommandFailedException Executing the command failed. - */ -- (nullable PGResult *)executeCommand: (OFConstantString *)command - parameters: (id)firstParameter, ... OF_SENTINEL; -@end - -OF_ASSUME_NONNULL_END DELETED src/PGConnection.m Index: src/PGConnection.m ================================================================== --- src/PGConnection.m +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGConnection.h" -#import "PGConnection+Private.h" -#import "PGResult.h" -#import "PGResult+Private.h" - -#import "PGConnectionFailedException.h" -#import "PGExecuteCommandFailedException.h" - -@implementation PGConnection -@synthesize pg_connection = _connection, parameters = _parameters; - -- (instancetype)init -{ - self = [super init]; - - @try { - _parameters = [[OFDictionary alloc] init]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_parameters release]; - - [self close]; - - [super dealloc]; -} - -- (void)connect -{ - void *pool = objc_autoreleasePoolPush(); - OFEnumerator OF_GENERIC(OFString *) *keyEnumerator = - [_parameters keyEnumerator]; - OFEnumerator OF_GENERIC(OFString *) *objectEnumerator = - [_parameters objectEnumerator]; - OFMutableString *connectionInfo = nil; - OFString *key, *object; - - while ((key = [keyEnumerator nextObject]) != nil && - (object = [objectEnumerator nextObject]) != nil) { - if (connectionInfo != nil) - [connectionInfo appendFormat: @" %@=%@", key, object]; - else - connectionInfo = [OFMutableString stringWithFormat: - @"%@=%@", key, object]; - } - - if ((_connection = PQconnectdb(connectionInfo.UTF8String)) == NULL) - @throw [OFOutOfMemoryException exception]; - - if (PQstatus(_connection) == CONNECTION_BAD) - @throw [PGConnectionFailedException - exceptionWithConnection: self]; - - objc_autoreleasePoolPop(pool); -} - -- (void)reset -{ - PQreset(_connection); -} - -- (void)close -{ - if (_connection != NULL) - PQfinish(_connection); - - _connection = NULL; -} - -- (PGResult *)executeCommand: (OFConstantString *)command -{ - PGresult *result = PQexec(_connection, command.UTF8String); - - if (PQresultStatus(result) == PGRES_FATAL_ERROR) { - PQclear(result); - @throw [PGExecuteCommandFailedException - exceptionWithConnection: self - command: command]; - } - - switch (PQresultStatus(result)) { - case PGRES_TUPLES_OK: - return [PGResult pg_resultWithResult: result]; - case PGRES_COMMAND_OK: - PQclear(result); - return nil; - default: - PQclear(result); - @throw [PGExecuteCommandFailedException - exceptionWithConnection: self - command: command]; - } -} - -- (PGResult *)executeCommand: (OFConstantString *)command - parameters: (id)parameter, ... -{ - void *pool = objc_autoreleasePoolPush(); - PGresult *result; - const char **values; - va_list args, args2; - int argsCount; - - va_start(args, parameter); - va_copy(args2, args); - - for (argsCount = 1; va_arg(args2, id) != nil; argsCount++); - - values = OFAllocMemory(argsCount, sizeof(*values)); - @try { - size_t i = 0; - - do { - if ([parameter isKindOfClass: [OFString class]]) - values[i++] = [parameter UTF8String]; - else if ([parameter isKindOfClass: [OFNumber class]]) { - OFNumber *number = parameter; - - if (strcmp(number.objCType, - @encode(bool)) == 0) { - if (number.boolValue) - values[i++] = "t"; - else - values[i++] = "f"; - } else - values[i++] = - number.description.UTF8String; - } else if ([parameter isKindOfClass: [OFNull class]]) - values[i++] = NULL; - else - values[i++] = - [parameter description].UTF8String; - } while ((parameter = va_arg(args, id)) != nil); - - result = PQexecParams(_connection, command.UTF8String, - argsCount, NULL, values, NULL, NULL, 0); - } @finally { - OFFreeMemory(values); - } - - objc_autoreleasePoolPop(pool); - - switch (PQresultStatus(result)) { - case PGRES_TUPLES_OK: - return [PGResult pg_resultWithResult: result]; - case PGRES_COMMAND_OK: - PQclear(result); - return nil; - default: - PQclear(result); - @throw [PGExecuteCommandFailedException - exceptionWithConnection: self - command: command]; - } -} -@end DELETED src/PGResult+Private.h Index: src/PGResult+Private.h ================================================================== --- src/PGResult+Private.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGResult.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface PGResult () -@property (readonly, nonatomic) PGresult *pg_result; - -+ (instancetype)pg_resultWithResult: (PGresult *)result; -- (instancetype)pg_initWithResult: (PGresult *)result; -@end - -OF_ASSUME_NONNULL_END DELETED src/PGResult.h Index: src/PGResult.h ================================================================== --- src/PGResult.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#import - -OF_ASSUME_NONNULL_BEGIN - -@class PGResultRow; - -/** - * @class PGResult PGResult.h ObjPgSQL/ObjPgSQL.h - * - * @brief A PostgreSQL result. - * - * This is a regular OFArray, where each entry in the array represents a result - * row. - */ -@interface PGResult: OFArray OF_GENERIC(PGResultRow *) -{ - PGresult *_result; -} -@end - -OF_ASSUME_NONNULL_END DELETED src/PGResult.m Index: src/PGResult.m ================================================================== --- src/PGResult.m +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGResult.h" -#import "PGResult+Private.h" -#import "PGResultRow.h" -#import "PGResultRow+Private.h" - -@implementation PGResult -@synthesize pg_result = _result; - -+ (instancetype)pg_resultWithResult: (PGresult *)result -{ - return [[[self alloc] pg_initWithResult: result] autorelease]; -} - -- (instancetype)pg_initWithResult: (PGresult *)result -{ - self = [super init]; - - _result = result; - - return self; -} - -- (void)dealloc -{ - if (_result != NULL) - PQclear(_result); - - [super dealloc]; -} - -- (size_t)count -{ - return PQntuples(_result); -} - -- (id)objectAtIndex: (size_t)index -{ - if (index > LONG_MAX || (long)index > PQntuples(_result)) - @throw [OFOutOfRangeException exception]; - - return [PGResultRow pg_rowWithResult: self row: (int)index]; -} -@end DELETED src/PGResultRow+Private.h Index: src/PGResultRow+Private.h ================================================================== --- src/PGResultRow+Private.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGResultRow.h" - -OF_ASSUME_NONNULL_BEGIN - -@interface PGResultRow () -+ (instancetype)pg_rowWithResult: (PGResult *)result row: (int)row; -- (instancetype)pg_initWithResult: (PGResult *)result row: (int)row; -@end - -OF_ASSUME_NONNULL_END DELETED src/PGResultRow.h Index: src/PGResultRow.h ================================================================== --- src/PGResultRow.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#import - -#import "PGResult.h" - -OF_ASSUME_NONNULL_BEGIN - -/** - * @class PGResult PGResult.h ObjPgSQL/ObjPgSQL.h - * - * @brief A PostgreSQL result row. - * - * This is a regular OFDictionary, where each entry in the dictionary - * represents a column of the result row. - */ -@interface PGResultRow: OFDictionary OF_GENERIC(OFString *, id) -{ - PGResult *_result; - PGresult *_res; - int _row; -} -@end - -OF_ASSUME_NONNULL_END DELETED src/PGResultRow.m Index: src/PGResultRow.m ================================================================== --- src/PGResultRow.m +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGResultRow.h" -#import "PGResult+Private.h" - -static id -convertType(PGresult *res, int column, OFString *string) -{ - switch (PQftype(res, column)) { - case 16: /* BOOLOID */ - if ([string isEqual: @"t"]) - return [OFNumber numberWithBool: YES]; - else - return [OFNumber numberWithBool: NO]; - case 21: /* INT2OID */ - return [OFNumber numberWithShort: - (short)[string longLongValueWithBase: 10]]; - case 23: /* INT4OID */ - return [OFNumber numberWithLong: - (long)[string longLongValueWithBase: 10]]; - case 20: /* INT8OID */ - return [OFNumber numberWithLongLong: - [string longLongValueWithBase: 10]]; - case 700: /* FLOAT4OID */ - return [OFNumber numberWithFloat: string.floatValue]; - case 701: /* FLOAT8OID */ - return [OFNumber numberWithDouble: string.doubleValue]; - } - - return string; -} - -@interface PGResultRowEnumerator: OFEnumerator -{ - PGResult *_result; - PGresult *_res; - int _row, _pos, _count; -} - -- (instancetype)initWithResult: (PGResult*)result row: (int)row; -@end - -@interface PGResultRowKeyEnumerator: PGResultRowEnumerator -@end - -@interface PGResultRowObjectEnumerator: PGResultRowEnumerator -@end - -@implementation PGResultRow -+ (instancetype)pg_rowWithResult: (PGResult *)result row: (int)row -{ - return [[[self alloc] pg_initWithResult: result row: row] autorelease]; -} - -- (instancetype)pg_initWithResult: (PGResult *)result row: (int)row -{ - self = [super init]; - - _result = [result retain]; - _res = result.pg_result; - _row = row; - - return self; -} - -- (void)dealloc -{ - [_result release]; - - [super dealloc]; -} - -- (size_t)count -{ - int i, count, fields = PQnfields(_res); - - for (i = count = 0; i < fields; i++) - if (!PQgetisnull(_res, _row, i)) - count++; - - return count; -} - -- (id)objectForKey: (id)key -{ - int column; - - if ([key isKindOfClass: [OFNumber class]]) - column = [key intValue]; - else - column = PQfnumber(_res, [key UTF8String]); - - if (PQgetisnull(_res, _row, column)) - return nil; - - return convertType(_res, column, - [OFString stringWithUTF8String: PQgetvalue(_res, _row, column)]); -} - -- (OFEnumerator *)keyEnumerator -{ - return [[[PGResultRowKeyEnumerator alloc] - initWithResult: _result - row: _row] autorelease]; -} - -- (OFEnumerator *)objectEnumerator -{ - return [[[PGResultRowObjectEnumerator alloc] - initWithResult: _result - row: _row] autorelease]; -} - -- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state - objects: (id *)objects - count: (int)count -{ - int i, j; - - if (state->extra[0] == 0) { - state->extra[0] = 1; - state->extra[1] = PQnfields(_res); - } - - if (count < 0 || (unsigned long)count > SIZE_MAX - state->state) - @throw [OFOutOfRangeException exception]; - - if (state->state + count > state->extra[1]) - count = state->extra[1] - state->state; - - for (i = j = 0; i < count; i++) { - if (PQgetisnull(_res, _row, state->state + i)) - continue; - - objects[j++] = [OFString stringWithUTF8String: - PQfname(_res, state->state + i)]; - } - - state->state += count; - state->itemsPtr = objects; - state->mutationsPtr = (unsigned long *)self; - - return j; -} -@end - -@implementation PGResultRowEnumerator -- (instancetype)initWithResult: (PGResult *)result row: (int)row -{ - self = [super init]; - - _result = [result retain]; - _res = result.pg_result; - _row = row; - _count = PQnfields(_res); - - return self; -} - -- (void)dealloc -{ - [_result release]; - - [super dealloc]; -} - -- (void)reset -{ - _pos = 0; -} -@end - -@implementation PGResultRowKeyEnumerator -- (id)nextObject -{ - if (_pos >= _count) - return nil; - - while (_pos < _count && PQgetisnull(_res, _row, _pos)) - _pos++; - - if (_pos >= _count) - return nil; - - return [OFString stringWithUTF8String: PQfname(_res, _pos++)]; -} -@end - -@implementation PGResultRowObjectEnumerator -- (id)nextObject -{ - id object; - - if (_pos >= _count) - return nil; - - while (_pos < _count && PQgetisnull(_res, _row, _pos)) - _pos++; - - if (_pos >= _count) - return nil; - - object = convertType(_res, _pos, - [OFString stringWithUTF8String: PQgetvalue(_res, _row, _pos)]); - _pos++; - - return object; -} -@end ADDED src/PGSQLConnection+Private.h Index: src/PGSQLConnection+Private.h ================================================================== --- /dev/null +++ src/PGSQLConnection+Private.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLConnection.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface PGSQLConnection () +@property (readonly, nonatomic) PGconn *pg_connection; +@end + +OF_ASSUME_NONNULL_END ADDED src/PGSQLConnection.h Index: src/PGSQLConnection.h ================================================================== --- /dev/null +++ src/PGSQLConnection.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#import + +#import "PGSQLResult.h" + +OF_ASSUME_NONNULL_BEGIN + +/** @file */ + +/** + * @brief A result row. + */ +typedef OFDictionary OF_GENERIC(OFString *, id) *PGSQLRow; + +/** + * @class PGSQLConnection PGSQLConnection.h ObjPgSQL/ObjPgSQL.h + * + * @brief A connection to a database. + */ +@interface PGSQLConnection: OFObject +{ + PGconn *_connection; + OFDictionary OF_GENERIC(OFString *, OFString *) *_parameters; +} + +/** + * @brief The parameters for the database connection. See `PQconnectdb` in the + * PostgreSQL documentation. + */ +@property (nonatomic, copy) + OFDictionary OF_GENERIC(OFString *, OFString *) *parameters; + +/** + * @brief Connects to the database. + * + * @throw PGSQLConnectionFailedException The connection failed + */ +- (void)connect; + +/** + * @brief Resets the connection to the database. + */ +- (void)reset; + +/** + * @brief Closes the connection to the database. + */ +- (void)close; + +/** + * @brief Executes the specified command. + * + * @param command The command to execute + * @return The result of the command, if any + * @throw PGSQLCommandFailedException Executing the command failed. + */ +- (nullable PGSQLResult *)executeCommand: (OFConstantString *)command; + +/** + * @brief Executes the specified command. + * + * @param command The command to execute + * @param firstParameter First parameter for the command + * @return The result of the command, if any + * @throw PGSQLCommandFailedException Executing the command failed. + */ +- (nullable PGSQLResult *)executeCommand: (OFConstantString *)command + parameters: (id)firstParameter, ... OF_SENTINEL; +@end + +OF_ASSUME_NONNULL_END ADDED src/PGSQLConnection.m Index: src/PGSQLConnection.m ================================================================== --- /dev/null +++ src/PGSQLConnection.m @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLConnection.h" +#import "PGSQLConnection+Private.h" +#import "PGSQLResult.h" +#import "PGSQLResult+Private.h" + +#import "PGSQLConnectionFailedException.h" +#import "PGSQLExecuteCommandFailedException.h" + +@implementation PGSQLConnection +@synthesize pg_connection = _connection, parameters = _parameters; + +- (instancetype)init +{ + self = [super init]; + + @try { + _parameters = [[OFDictionary alloc] init]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_parameters release]; + + [self close]; + + [super dealloc]; +} + +- (void)connect +{ + void *pool = objc_autoreleasePoolPush(); + OFEnumerator OF_GENERIC(OFString *) *keyEnumerator = + [_parameters keyEnumerator]; + OFEnumerator OF_GENERIC(OFString *) *objectEnumerator = + [_parameters objectEnumerator]; + OFMutableString *connectionInfo = nil; + OFString *key, *object; + + while ((key = [keyEnumerator nextObject]) != nil && + (object = [objectEnumerator nextObject]) != nil) { + if (connectionInfo != nil) + [connectionInfo appendFormat: @" %@=%@", key, object]; + else + connectionInfo = [OFMutableString stringWithFormat: + @"%@=%@", key, object]; + } + + if ((_connection = PQconnectdb(connectionInfo.UTF8String)) == NULL) + @throw [OFOutOfMemoryException exception]; + + if (PQstatus(_connection) == CONNECTION_BAD) + @throw [PGSQLConnectionFailedException + exceptionWithConnection: self]; + + objc_autoreleasePoolPop(pool); +} + +- (void)reset +{ + PQreset(_connection); +} + +- (void)close +{ + if (_connection != NULL) + PQfinish(_connection); + + _connection = NULL; +} + +- (PGSQLResult *)executeCommand: (OFConstantString *)command +{ + PGresult *result = PQexec(_connection, command.UTF8String); + + if (PQresultStatus(result) == PGRES_FATAL_ERROR) { + PQclear(result); + @throw [PGSQLExecuteCommandFailedException + exceptionWithConnection: self + command: command]; + } + + switch (PQresultStatus(result)) { + case PGRES_TUPLES_OK: + return [PGSQLResult pg_resultWithResult: result]; + case PGRES_COMMAND_OK: + PQclear(result); + return nil; + default: + PQclear(result); + @throw [PGSQLExecuteCommandFailedException + exceptionWithConnection: self + command: command]; + } +} + +- (PGSQLResult *)executeCommand: (OFConstantString *)command + parameters: (id)parameter, ... +{ + void *pool = objc_autoreleasePoolPush(); + PGresult *result; + const char **values; + va_list args, args2; + int argsCount; + + va_start(args, parameter); + va_copy(args2, args); + + for (argsCount = 1; va_arg(args2, id) != nil; argsCount++); + + values = OFAllocMemory(argsCount, sizeof(*values)); + @try { + size_t i = 0; + + do { + if ([parameter isKindOfClass: [OFString class]]) + values[i++] = [parameter UTF8String]; + else if ([parameter isKindOfClass: [OFNumber class]]) { + OFNumber *number = parameter; + + if (strcmp(number.objCType, + @encode(bool)) == 0) { + if (number.boolValue) + values[i++] = "t"; + else + values[i++] = "f"; + } else + values[i++] = + number.description.UTF8String; + } else if ([parameter isKindOfClass: [OFNull class]]) + values[i++] = NULL; + else + values[i++] = + [parameter description].UTF8String; + } while ((parameter = va_arg(args, id)) != nil); + + result = PQexecParams(_connection, command.UTF8String, + argsCount, NULL, values, NULL, NULL, 0); + } @finally { + OFFreeMemory(values); + } + + objc_autoreleasePoolPop(pool); + + switch (PQresultStatus(result)) { + case PGRES_TUPLES_OK: + return [PGSQLResult pg_resultWithResult: result]; + case PGRES_COMMAND_OK: + PQclear(result); + return nil; + default: + PQclear(result); + @throw [PGSQLExecuteCommandFailedException + exceptionWithConnection: self + command: command]; + } +} +@end ADDED src/PGSQLResult+Private.h Index: src/PGSQLResult+Private.h ================================================================== --- /dev/null +++ src/PGSQLResult+Private.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLResult.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface PGSQLResult () +@property (readonly, nonatomic) PGresult *pg_result; + ++ (instancetype)pg_resultWithResult: (PGresult *)result; +- (instancetype)pg_initWithResult: (PGresult *)result; +@end + +OF_ASSUME_NONNULL_END ADDED src/PGSQLResult.h Index: src/PGSQLResult.h ================================================================== --- /dev/null +++ src/PGSQLResult.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#import + +OF_ASSUME_NONNULL_BEGIN + +@class PGSQLResultRow; + +/** + * @class PGSQLResult PGSQLResult.h ObjPgSQL/ObjPgSQL.h + * + * @brief A PostgreSQL result. + * + * This is a regular OFArray, where each entry in the array represents a result + * row. + */ +@interface PGSQLResult: OFArray OF_GENERIC(PGSQLResultRow *) +{ + PGresult *_result; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/PGSQLResult.m Index: src/PGSQLResult.m ================================================================== --- /dev/null +++ src/PGSQLResult.m @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLResult.h" +#import "PGSQLResult+Private.h" +#import "PGSQLResultRow.h" +#import "PGSQLResultRow+Private.h" + +@implementation PGSQLResult +@synthesize pg_result = _result; + ++ (instancetype)pg_resultWithResult: (PGresult *)result +{ + return [[[self alloc] pg_initWithResult: result] autorelease]; +} + +- (instancetype)pg_initWithResult: (PGresult *)result +{ + self = [super init]; + + _result = result; + + return self; +} + +- (void)dealloc +{ + if (_result != NULL) + PQclear(_result); + + [super dealloc]; +} + +- (size_t)count +{ + return PQntuples(_result); +} + +- (id)objectAtIndex: (size_t)index +{ + if (index > LONG_MAX || (long)index > PQntuples(_result)) + @throw [OFOutOfRangeException exception]; + + return [PGSQLResultRow pg_rowWithResult: self row: (int)index]; +} +@end ADDED src/PGSQLResultRow+Private.h Index: src/PGSQLResultRow+Private.h ================================================================== --- /dev/null +++ src/PGSQLResultRow+Private.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLResultRow.h" + +OF_ASSUME_NONNULL_BEGIN + +@interface PGSQLResultRow () ++ (instancetype)pg_rowWithResult: (PGSQLResult *)result row: (int)row; +- (instancetype)pg_initWithResult: (PGSQLResult *)result row: (int)row; +@end + +OF_ASSUME_NONNULL_END ADDED src/PGSQLResultRow.h Index: src/PGSQLResultRow.h ================================================================== --- /dev/null +++ src/PGSQLResultRow.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#import + +#import "PGSQLResult.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class PGSQLResult PGSQLResult.h ObjPgSQL/ObjPgSQL.h + * + * @brief A PostgreSQL result row. + * + * This is a regular OFDictionary, where each entry in the dictionary + * represents a column of the result row. + */ +@interface PGSQLResultRow: OFDictionary OF_GENERIC(OFString *, id) +{ + PGSQLResult *_result; + PGresult *_res; + int _row; +} +@end + +OF_ASSUME_NONNULL_END ADDED src/PGSQLResultRow.m Index: src/PGSQLResultRow.m ================================================================== --- /dev/null +++ src/PGSQLResultRow.m @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLResultRow.h" +#import "PGSQLResult+Private.h" + +static id +convertType(PGresult *res, int column, OFString *string) +{ + switch (PQftype(res, column)) { + case 16: /* BOOLOID */ + if ([string isEqual: @"t"]) + return [OFNumber numberWithBool: YES]; + else + return [OFNumber numberWithBool: NO]; + case 21: /* INT2OID */ + return [OFNumber numberWithShort: + (short)[string longLongValueWithBase: 10]]; + case 23: /* INT4OID */ + return [OFNumber numberWithLong: + (long)[string longLongValueWithBase: 10]]; + case 20: /* INT8OID */ + return [OFNumber numberWithLongLong: + [string longLongValueWithBase: 10]]; + case 700: /* FLOAT4OID */ + return [OFNumber numberWithFloat: string.floatValue]; + case 701: /* FLOAT8OID */ + return [OFNumber numberWithDouble: string.doubleValue]; + } + + return string; +} + +@interface PGSQLResultRowEnumerator: OFEnumerator +{ + PGSQLResult *_result; + PGresult *_res; + int _row, _pos, _count; +} + +- (instancetype)initWithResult: (PGSQLResult*)result row: (int)row; +@end + +@interface PGSQLResultRowKeyEnumerator: PGSQLResultRowEnumerator +@end + +@interface PGSQLResultRowObjectEnumerator: PGSQLResultRowEnumerator +@end + +@implementation PGSQLResultRow ++ (instancetype)pg_rowWithResult: (PGSQLResult *)result row: (int)row +{ + return [[[self alloc] pg_initWithResult: result row: row] autorelease]; +} + +- (instancetype)pg_initWithResult: (PGSQLResult *)result row: (int)row +{ + self = [super init]; + + _result = [result retain]; + _res = result.pg_result; + _row = row; + + return self; +} + +- (void)dealloc +{ + [_result release]; + + [super dealloc]; +} + +- (size_t)count +{ + int i, count, fields = PQnfields(_res); + + for (i = count = 0; i < fields; i++) + if (!PQgetisnull(_res, _row, i)) + count++; + + return count; +} + +- (id)objectForKey: (id)key +{ + int column; + + if ([key isKindOfClass: [OFNumber class]]) + column = [key intValue]; + else + column = PQfnumber(_res, [key UTF8String]); + + if (PQgetisnull(_res, _row, column)) + return nil; + + return convertType(_res, column, + [OFString stringWithUTF8String: PQgetvalue(_res, _row, column)]); +} + +- (OFEnumerator *)keyEnumerator +{ + return [[[PGSQLResultRowKeyEnumerator alloc] + initWithResult: _result + row: _row] autorelease]; +} + +- (OFEnumerator *)objectEnumerator +{ + return [[[PGSQLResultRowObjectEnumerator alloc] + initWithResult: _result + row: _row] autorelease]; +} + +- (int)countByEnumeratingWithState: (OFFastEnumerationState *)state + objects: (id *)objects + count: (int)count +{ + int i, j; + + if (state->extra[0] == 0) { + state->extra[0] = 1; + state->extra[1] = PQnfields(_res); + } + + if (count < 0 || (unsigned long)count > SIZE_MAX - state->state) + @throw [OFOutOfRangeException exception]; + + if (state->state + count > state->extra[1]) + count = state->extra[1] - state->state; + + for (i = j = 0; i < count; i++) { + if (PQgetisnull(_res, _row, state->state + i)) + continue; + + objects[j++] = [OFString stringWithUTF8String: + PQfname(_res, state->state + i)]; + } + + state->state += count; + state->itemsPtr = objects; + state->mutationsPtr = (unsigned long *)self; + + return j; +} +@end + +@implementation PGSQLResultRowEnumerator +- (instancetype)initWithResult: (PGSQLResult *)result row: (int)row +{ + self = [super init]; + + _result = [result retain]; + _res = result.pg_result; + _row = row; + _count = PQnfields(_res); + + return self; +} + +- (void)dealloc +{ + [_result release]; + + [super dealloc]; +} + +- (void)reset +{ + _pos = 0; +} +@end + +@implementation PGSQLResultRowKeyEnumerator +- (id)nextObject +{ + if (_pos >= _count) + return nil; + + while (_pos < _count && PQgetisnull(_res, _row, _pos)) + _pos++; + + if (_pos >= _count) + return nil; + + return [OFString stringWithUTF8String: PQfname(_res, _pos++)]; +} +@end + +@implementation PGSQLResultRowObjectEnumerator +- (id)nextObject +{ + id object; + + if (_pos >= _count) + return nil; + + while (_pos < _count && PQgetisnull(_res, _row, _pos)) + _pos++; + + if (_pos >= _count) + return nil; + + object = convertType(_res, _pos, + [OFString stringWithUTF8String: PQgetvalue(_res, _row, _pos)]); + _pos++; + + return object; +} +@end DELETED src/exceptions/PGConnectionFailedException.h Index: src/exceptions/PGConnectionFailedException.h ================================================================== --- src/exceptions/PGConnectionFailedException.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGException.h" - -OF_ASSUME_NONNULL_BEGIN - -/** - * @class PGConnectionFailedException PGConnectionFailedException.h - * PgSQL/PgSQL.h - * - * @brief An exception indicating that connecting to the database failed. - */ -@interface PGConnectionFailedException: PGException -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/PGConnectionFailedException.m Index: src/exceptions/PGConnectionFailedException.m ================================================================== --- src/exceptions/PGConnectionFailedException.m +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGConnectionFailedException.h" - -@implementation PGConnectionFailedException -- (OFString *)description -{ - return [OFString stringWithFormat: - @"Establishing a PostgreSQL connection failed:\n%@\n" - "Parameters: %@", _errorMessage, [_connection parameters]]; -} -@end DELETED src/exceptions/PGException.h Index: src/exceptions/PGException.h ================================================================== --- src/exceptions/PGException.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import - -#import "PGConnection.h" - -OF_ASSUME_NONNULL_BEGIN - -/** - * @class PGException PGException.h ObjPgSQL/ObjPgSQL.h - * - * @brief A PostgreSQL exception. - */ -@interface PGException: OFException -{ - PGConnection *_connection; - OFString *_errorMessage; -} - -/** - * @brief The connection for which the exception occurred. - */ -@property (readonly, nonatomic) PGConnection *connection; - -/** - * @brief An error message for the exception. - */ -@property (readonly, nonatomic) OFString *errorMessage; - -+ (instancetype)exception OF_UNAVAILABLE; - -/** - * @brief Creates a new PostgreSQL exception. - * - * @param connection The connection for which the exception occurred - * @return A new, autoreleased PostgreSQL exception - */ -+ (instancetype)exceptionWithConnection: (PGConnection *)connection; - -- (instancetype)init OF_UNAVAILABLE; - -/** - * @brief Initializes an already allocated PostgreSQL exception. - * - * @param connection The connection for which the exception occurred - * @return An initialized PostgreSQL exception - */ -- (instancetype)initWithConnection: (PGConnection *)connection - OF_DESIGNATED_INITIALIZER; -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/PGException.m Index: src/exceptions/PGException.m ================================================================== --- src/exceptions/PGException.m +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGException.h" -#import "PGConnection+Private.h" - -@implementation PGException -@synthesize connection = _connection, errorMessage = _errorMessage; - -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - -+ (instancetype)exceptionWithConnection: (PGConnection *)connection -{ - return [[[self alloc] initWithConnection: connection] autorelease]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithConnection: (PGConnection *)connection -{ - self = [super init]; - - @try { - _connection = [connection retain]; - _errorMessage = [[OFString alloc] - initWithCString: PQerrorMessage([_connection pg_connection]) - encoding: [OFLocale encoding]]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_connection release]; - [_errorMessage release]; - - [super dealloc]; -} - -- (OFString *)description -{ - return [OFString stringWithFormat: @"A PostgreSQL operation failed: %@", - _errorMessage]; -} -@end DELETED src/exceptions/PGExecuteCommandFailedException.h Index: src/exceptions/PGExecuteCommandFailedException.h ================================================================== --- src/exceptions/PGExecuteCommandFailedException.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGException.h" - -OF_ASSUME_NONNULL_BEGIN - -/** - * @class PGExecuteCommandFailedException PGExecuteCommandFailedException.h - * ObjPgSQL/ObjPgSQL.h - * - * @brief An exception indicating that executing a command failed. - */ -@interface PGExecuteCommandFailedException: PGException -{ - OFConstantString *_command; -} - -/** - * @brief The command that could not be executed. - */ -@property (readonly, nonatomic) OFConstantString *command; - -+ (instancetype)exceptionWithConnection: (PGConnection *)connection - OF_UNAVAILABLE; - -/** - * @brief Creates a new execte command failed exception. - * - * @param connection The connection for which the command could not be executed - * @param command The command which could not be executed - * @return A new, autoreleased execute command failed exception - */ -+ (instancetype)exceptionWithConnection: (PGConnection *)connection - command: (OFConstantString *)command; - -- (instancetype)initWithConnection: (PGConnection *)connection OF_UNAVAILABLE; - -/** - * @brief Initializes an already allocated execte command failed exception. - * - * @param connection The connection for which the command could not be executed - * @param command The command which could not be executed - * @return An initialized execute command failed exception - */ -- (instancetype)initWithConnection: (PGConnection *)connection - command: (OFConstantString *)command - OF_DESIGNATED_INITIALIZER; -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/PGExecuteCommandFailedException.m Index: src/exceptions/PGExecuteCommandFailedException.m ================================================================== --- src/exceptions/PGExecuteCommandFailedException.m +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer - * - * https://fl.nil.im/objpgsql - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH - * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, - * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM - * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE - * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -#import "PGExecuteCommandFailedException.h" - -@implementation PGExecuteCommandFailedException -@synthesize command = _command; - -+ (instancetype)exceptionWithConnection: (PGConnection *)connection -{ - OF_UNRECOGNIZED_SELECTOR -} - -+ (instancetype)exceptionWithConnection: (PGConnection *)connection - command: (OFConstantString *)command -{ - return [[[self alloc] initWithConnection: connection - command: command] autorelease]; -} - -- (instancetype)initWithConnection: (PGConnection *)connection -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithConnection: (PGConnection *)connection - command: (OFConstantString *)command -{ - self = [super initWithConnection: connection]; - - @try { - _command = [command copy]; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_command release]; - - [super dealloc]; -} - -- (OFString *)description -{ - return [OFString stringWithFormat: @"A PostgreSQL command failed: %@\n" - @"Command: %@", - _errorMessage, _command]; -} -@end ADDED src/exceptions/PGSQLConnectionFailedException.h Index: src/exceptions/PGSQLConnectionFailedException.h ================================================================== --- /dev/null +++ src/exceptions/PGSQLConnectionFailedException.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLException.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class PGSQLConnectionFailedException PGSQLConnectionFailedException.h + * PgSQL/PgSQL.h + * + * @brief An exception indicating that connecting to the database failed. + */ +@interface PGSQLConnectionFailedException: PGSQLException +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/PGSQLConnectionFailedException.m Index: src/exceptions/PGSQLConnectionFailedException.m ================================================================== --- /dev/null +++ src/exceptions/PGSQLConnectionFailedException.m @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLConnectionFailedException.h" + +@implementation PGSQLConnectionFailedException +- (OFString *)description +{ + return [OFString stringWithFormat: + @"Establishing a PostgreSQL connection failed:\n%@\n" + "Parameters: %@", _errorMessage, [_connection parameters]]; +} +@end ADDED src/exceptions/PGSQLException.h Index: src/exceptions/PGSQLException.h ================================================================== --- /dev/null +++ src/exceptions/PGSQLException.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import + +#import "PGSQLConnection.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class PGSQLException PGSQLException.h ObjPgSQL/ObjPgSQL.h + * + * @brief A PostgreSQL exception. + */ +@interface PGSQLException: OFException +{ + PGSQLConnection *_connection; + OFString *_errorMessage; +} + +/** + * @brief The connection for which the exception occurred. + */ +@property (readonly, nonatomic) PGSQLConnection *connection; + +/** + * @brief An error message for the exception. + */ +@property (readonly, nonatomic) OFString *errorMessage; + ++ (instancetype)exception OF_UNAVAILABLE; + +/** + * @brief Creates a new PostgreSQL exception. + * + * @param connection The connection for which the exception occurred + * @return A new, autoreleased PostgreSQL exception + */ ++ (instancetype)exceptionWithConnection: (PGSQLConnection *)connection; + +- (instancetype)init OF_UNAVAILABLE; + +/** + * @brief Initializes an already allocated PostgreSQL exception. + * + * @param connection The connection for which the exception occurred + * @return An initialized PostgreSQL exception + */ +- (instancetype)initWithConnection: (PGSQLConnection *)connection + OF_DESIGNATED_INITIALIZER; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/PGSQLException.m Index: src/exceptions/PGSQLException.m ================================================================== --- /dev/null +++ src/exceptions/PGSQLException.m @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLException.h" +#import "PGSQLConnection+Private.h" + +@implementation PGSQLException +@synthesize connection = _connection, errorMessage = _errorMessage; + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithConnection: (PGSQLConnection *)connection +{ + return [[[self alloc] initWithConnection: connection] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithConnection: (PGSQLConnection *)connection +{ + self = [super init]; + + @try { + _connection = [connection retain]; + _errorMessage = [[OFString alloc] + initWithCString: PQerrorMessage([_connection pg_connection]) + encoding: [OFLocale encoding]]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_connection release]; + [_errorMessage release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: @"A PostgreSQL operation failed: %@", + _errorMessage]; +} +@end ADDED src/exceptions/PGSQLExecuteCommandFailedException.h Index: src/exceptions/PGSQLExecuteCommandFailedException.h ================================================================== --- /dev/null +++ src/exceptions/PGSQLExecuteCommandFailedException.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLException.h" + +OF_ASSUME_NONNULL_BEGIN + +/** + * @class PGSQLExecuteCommandFailedException + * PGSQLExecuteCommandFailedException.h + * ObjPgSQL/ObjPgSQL.h + * + * @brief An exception indicating that executing a command failed. + */ +@interface PGSQLExecuteCommandFailedException: PGSQLException +{ + OFConstantString *_command; +} + +/** + * @brief The command that could not be executed. + */ +@property (readonly, nonatomic) OFConstantString *command; + ++ (instancetype)exceptionWithConnection: (PGSQLConnection *)connection + OF_UNAVAILABLE; + +/** + * @brief Creates a new execte command failed exception. + * + * @param connection The connection for which the command could not be executed + * @param command The command which could not be executed + * @return A new, autoreleased execute command failed exception + */ ++ (instancetype)exceptionWithConnection: (PGSQLConnection *)connection + command: (OFConstantString *)command; + +- (instancetype)initWithConnection: (PGSQLConnection *)connection + OF_UNAVAILABLE; + +/** + * @brief Initializes an already allocated execte command failed exception. + * + * @param connection The connection for which the command could not be executed + * @param command The command which could not be executed + * @return An initialized execute command failed exception + */ +- (instancetype)initWithConnection: (PGSQLConnection *)connection + command: (OFConstantString *)command + OF_DESIGNATED_INITIALIZER; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/PGSQLExecuteCommandFailedException.m Index: src/exceptions/PGSQLExecuteCommandFailedException.m ================================================================== --- /dev/null +++ src/exceptions/PGSQLExecuteCommandFailedException.m @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2012 - 2019, 2021, 2024 Jonathan Schleifer + * + * https://fl.nil.im/objpgsql + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#import "PGSQLExecuteCommandFailedException.h" + +@implementation PGSQLExecuteCommandFailedException +@synthesize command = _command; + ++ (instancetype)exceptionWithConnection: (PGSQLConnection *)connection +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithConnection: (PGSQLConnection *)connection + command: (OFConstantString *)command +{ + return [[[self alloc] initWithConnection: connection + command: command] autorelease]; +} + +- (instancetype)initWithConnection: (PGSQLConnection *)connection +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithConnection: (PGSQLConnection *)connection + command: (OFConstantString *)command +{ + self = [super initWithConnection: connection]; + + @try { + _command = [command copy]; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_command release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: @"A PostgreSQL command failed: %@\n" + @"Command: %@", + _errorMessage, _command]; +} +@end Index: src/exceptions/meson.build ================================================================== --- src/exceptions/meson.build +++ src/exceptions/meson.build @@ -1,5 +1,5 @@ exceptions_sources = files( - 'PGConnectionFailedException.m', - 'PGException.m', - 'PGExecuteCommandFailedException.m', + 'PGSQLConnectionFailedException.m', + 'PGSQLException.m', + 'PGSQLExecuteCommandFailedException.m', ) Index: src/meson.build ================================================================== --- src/meson.build +++ src/meson.build @@ -1,13 +1,13 @@ fs = import('fs') subdir('exceptions') sources = files( - 'PGConnection.m', - 'PGResult.m', - 'PGResultRow.m', + 'PGSQLConnection.m', + 'PGSQLResult.m', + 'PGSQLResultRow.m', ) objpgsql = library('objpgsql', sources + exceptions_sources, include_directories: incdir, Index: tests/Tests.m ================================================================== --- tests/Tests.m +++ tests/Tests.m @@ -16,16 +16,15 @@ * PERFORMANCE OF THIS SOFTWARE. */ #import -#import "PGConnection.h" -#import "PGConnectionFailedException.h" +#import "ObjPgSQL.h" @interface Test: OFObject { - PGConnection *_connection; + PGSQLConnection *_connection; } @end OF_APPLICATION_DELEGATE(Test) @@ -32,13 +31,13 @@ @implementation Test - (void)applicationDidFinishLaunching: (OFNotification *)notification { OFString *username = [[OFApplication environment] objectForKey: @"USER"]; - PGResult *result; + PGSQLResult *result; - _connection = [[PGConnection alloc] init]; + _connection = [[PGSQLConnection alloc] init]; [_connection setParameters: [OFDictionary dictionaryWithKeysAndObjects: @"user", username, @"dbname", username, nil]]; [_connection connect];