4 Copyright (C) 2004 SKYRIX Software AG and Helge Hess
6 Author: Helge Hess (helge.hess@opengroupware.org)
8 This file is part of the PostgreSQL72 Adaptor Library
10 This library is free software; you can redistribute it and/or
11 modify it under the terms of the GNU Library General Public
12 License as published by the Free Software Foundation; either
13 version 2 of the License, or (at your option) any later version.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Library General Public
21 License along with this library; see the file COPYING.LIB.
22 If not, write to the Free Software Foundation,
23 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 // $Id: PGConnection.m 1 2004-08-20 10:38:46Z znek $
27 #include "PGConnection.h"
31 #if PG_MAJOR_VERSION >= 6 && PG_MINOR_VERSION > 3
32 # define NG_HAS_NOTICE_PROCESSOR 1
33 # define NG_HAS_BINARY_TUPLES 1
34 # define NG_HAS_FMOD 1
37 #if PG_MAJOR_VERSION >= 7 && PG_MINOR_VERSION > 3
38 # define NG_SET_CLIENT_ENCODING 1
41 @implementation PGConnection
43 static BOOL debugOn = NO;
45 - (id)initWithHostName:(NSString *)_host port:(NSString *)_port
46 options:(NSString *)_options tty:(NSString *)_tty
47 database:(NSString *)_dbname
48 login:(NSString *)_login password:(NSString *)_pwd
50 if ((self = [self init])) {
53 error = [self connectWithHostName:_host port:_port options:_options
54 tty:_tty database:_dbname login:_login password:_pwd];
57 NSLog(@"%s: could not connect: %@", __PRETTY_FUNCTION__, error);
72 - (const char *)_cstrFromString:(NSString *)_s {
73 // TODO: fix API, check what the API string encoding is
76 - (NSString *)_stringFromCString:(const char *)_cstr {
77 return [NSString stringWithCString:_cstr];
83 return self->_connection != NULL ? YES : NO;
88 - (NSException *)_makeConnectException:(const char *)_func {
89 return [NSException exceptionWithName:@"PGConnectFailed"
90 reason:[NSString stringWithCString:_func]
94 /* connect operations */
97 if (self->_connection != NULL)
101 - (NSException *)startConnectWithInfo:(NSString *)_conninfo {
104 self->_connection = PQconnectStart([self _cstrFromString:_conninfo]);
105 if (self->_connection == NULL)
106 return [self _makeConnectException:__PRETTY_FUNCTION__];
109 // TODO: add method for polling connect status
111 - (NSException *)connectWithInfo:(NSString *)_conninfo {
114 self->_connection = PQconnectdb([self _cstrFromString:_conninfo]);
115 if (self->_connection == NULL)
116 return [self _makeConnectException:__PRETTY_FUNCTION__];
120 - (NSException *)connectWithHostName:(NSString *)_host port:(NSString *)_port
121 options:(NSString *)_options tty:(NSString *)_tty
122 database:(NSString *)_dbname
123 login:(NSString *)_login password:(NSString *)_pwd
127 self->_connection = PQsetdbLogin([self _cstrFromString:_host],
128 [self _cstrFromString:_port],
129 [self _cstrFromString:_options],
130 [self _cstrFromString:_tty],
131 [self _cstrFromString:_dbname],
132 [self _cstrFromString:_login],
133 [self _cstrFromString:_pwd]);
134 if (self->_connection == NULL)
135 return [self _makeConnectException:__PRETTY_FUNCTION__];
140 if (self->_connection != NULL) {
141 PQfinish(self->_connection);
142 self->_connection = NULL;
146 - (BOOL)isConnectionOK {
149 return PQstatus(self->_connection) == CONNECTION_OK ? YES : NO;
152 /* message callbacks */
154 - (BOOL)setNoticeProcessor:(void *)_callback context:(void *)_ctx {
155 #if NG_HAS_NOTICE_PROCESSOR
156 PQsetNoticeProcessor(self->_connection, _callback, _ctx);
157 return YES; // TODO: improve error handling
165 - (BOOL)setClientEncoding:(NSString *)_encoding {
166 return PQsetClientEncoding(self->_connection,
167 [self _cstrFromString:_encoding]) == 0 ? YES : NO;
172 - (NSString *)errorMessage {
176 return [self _stringFromCString:PQerrorMessage(self->_connection)];
181 - (void *)rawExecute:(NSString *)_sql {
182 return PQexec(self->_connection, [self _cstrFromString:_sql]);
184 - (void)clearRawResults:(void *)_ptr {
185 if (_ptr == NULL) return;
189 - (PGResultSet *)execute:(NSString *)_sql {
192 if ((handle = [self rawExecute:_sql]) == NULL)
195 return [[[PGResultSet alloc] initWithConnection:self handle:handle]
201 - (BOOL)isDebuggingEnabled {
207 - (NSString *)description {
210 ms = [NSMutableString stringWithCapacity:128];
211 [ms appendFormat:@"<0x%08X[%@]: ", self, NSStringFromClass([self class])];
213 [ms appendFormat:@" connection=0x%08X", self->_connection];
215 [ms appendString:@" not-connected"];
216 [ms appendString:@">"];
220 @end /* PGConnection */
222 @implementation PGResultSet
226 - (id)initWithConnection:(PGConnection *)_con handle:(void *)_handle {
227 if (_handle == NULL) {
231 if ((self = [super init])) {
232 self->connection = [_con retain];
233 self->results = _handle;
240 [self->connection release];
247 return self->results != NULL ? YES : NO;
250 - (BOOL)containsBinaryTuples {
251 #if NG_HAS_BINARY_TUPLES
252 if (self->results == NULL) return NO;
253 return PQbinaryTuples(self->results) ? YES : NO;
259 - (NSString *)commandStatus {
262 if (self->results == NULL)
264 if ((cstr = PQcmdStatus(self->results)) == NULL)
266 return [NSString stringWithCString:cstr];
269 - (NSString *)commandTuples {
272 if (self->results == NULL)
274 if ((cstr = PQcmdTuples(self->results)) == NULL)
276 return [NSString stringWithCString:cstr];
281 - (unsigned)fieldCount {
282 return self->results != NULL ? PQnfields(self->results) : 0;
285 - (NSString *)fieldNameAtIndex:(unsigned int)_idx {
287 if (self->results == NULL) return nil;
288 return [NSString stringWithCString:PQfname(self->results, _idx)];
291 - (int)indexOfFieldNamed:(NSString *)_name {
292 return PQfnumber(self->results, [_name cString]);
295 - (int)fieldSizeAtIndex:(unsigned int)_idx {
296 if (self->results == NULL) return 0;
297 return PQfsize(self->results, _idx);
300 - (int)modifierAtIndex:(unsigned int)_idx {
301 if (self->results == NULL) return 0;
303 return PQfmod(self->results, _idx);
311 - (unsigned int)tupleCount {
312 if (self->results == NULL) return 0;
313 return PQntuples(self->results);
316 - (BOOL)isNullTuple:(int)_tuple atIndex:(unsigned int)_idx {
317 if (self->results == NULL) return NO;
318 return PQgetisnull(self->results, _tuple, _idx) ? YES : NO;
321 - (void *)rawValueOfTuple:(int)_tuple atIndex:(unsigned int)_idx {
322 if (self->results == NULL) return NULL;
323 return PQgetvalue(self->results, _tuple, _idx);
326 - (int)lengthOfTuple:(int)_tuple atIndex:(unsigned int)_idx {
327 if (self->results == NULL) return 0;
328 return PQgetlength(self->results, _tuple, _idx);
334 if (self->results == NULL) return;
335 PQclear(self->results);
336 self->results = NULL;
339 @end /* PGResultSet */