diff options
author | stuconnolly <stuart02@gmail.com> | 2012-09-03 10:22:17 +0000 |
---|---|---|
committer | stuconnolly <stuart02@gmail.com> | 2012-09-03 10:22:17 +0000 |
commit | e124a1d0fb576c311a6ac601b1c08e6ce51bcd30 (patch) | |
tree | 5a3350fc75bcad1f5c8d07f8a66ea53b0a07805f /Frameworks | |
parent | d4e8474b3437771fd6891def8324981d82186a88 (diff) | |
download | sequelpro-e124a1d0fb576c311a6ac601b1c08e6ce51bcd30.tar.gz sequelpro-e124a1d0fb576c311a6ac601b1c08e6ce51bcd30.tar.bz2 sequelpro-e124a1d0fb576c311a6ac601b1c08e6ce51bcd30.zip |
Initial commit of PostgresKit, our new Postgres framework as a start towards adding PostgreSQL support to Sequel Pro.
Note, that the framerwork is by no means feature complete and in it's current state has quite a few limitations:
- No support for Postgres' asynchronous query API
- Only supports the very basic data types (char/text and numerics)
- No support (outide of libpq) for re-establishing dropped connections
Current feature support includes:
- Basic connection handling
- Query execution
- Prepared statement execution
- Encoding support similar to SPMySQL's
Diffstat (limited to 'Frameworks')
46 files changed, 5344 insertions, 0 deletions
diff --git a/Frameworks/PostgresKit/PostgreSQL/include/libpq-fe.h b/Frameworks/PostgresKit/PostgreSQL/include/libpq-fe.h new file mode 100644 index 00000000..d7802753 --- /dev/null +++ b/Frameworks/PostgresKit/PostgreSQL/include/libpq-fe.h @@ -0,0 +1,576 @@ +/*------------------------------------------------------------------------- + * + * libpq-fe.h + * This file contains definitions for structures and + * externs for functions used by frontend postgres applications. + * + * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/interfaces/libpq/libpq-fe.h + * + *------------------------------------------------------------------------- + */ + +#ifndef LIBPQ_FE_H +#define LIBPQ_FE_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdio.h> + +/* + * postgres_ext.h defines the backend's externally visible types, + * such as Oid. + */ +#include "postgres_ext.h" + +/* + * Option flags for PQcopyResult + */ +#define PG_COPYRES_ATTRS 0x01 +#define PG_COPYRES_TUPLES 0x02 /* Implies PG_COPYRES_ATTRS */ +#define PG_COPYRES_EVENTS 0x04 +#define PG_COPYRES_NOTICEHOOKS 0x08 + +/* Application-visible enum types */ + +typedef enum +{ + /* + * Although it is okay to add to this list, values which become unused + * should never be removed, nor should constants be redefined - that would + * break compatibility with existing code. + */ + CONNECTION_OK, + CONNECTION_BAD, + /* Non-blocking mode only below here */ + + /* + * The existence of these should never be relied upon - they should only + * be used for user feedback or similar purposes. + */ + CONNECTION_STARTED, /* Waiting for connection to be made. */ + CONNECTION_MADE, /* Connection OK; waiting to send. */ + CONNECTION_AWAITING_RESPONSE, /* Waiting for a response from the + * postmaster. */ + CONNECTION_AUTH_OK, /* Received authentication; waiting for + * backend startup. */ + CONNECTION_SETENV, /* Negotiating environment. */ + CONNECTION_SSL_STARTUP, /* Negotiating SSL. */ + CONNECTION_NEEDED /* Internal state: connect() needed */ +} ConnStatusType; + +typedef enum +{ + PGRES_POLLING_FAILED = 0, + PGRES_POLLING_READING, /* These two indicate that one may */ + PGRES_POLLING_WRITING, /* use select before polling again. */ + PGRES_POLLING_OK, + PGRES_POLLING_ACTIVE /* unused; keep for awhile for backwards + * compatibility */ +} PostgresPollingStatusType; + +typedef enum +{ + PGRES_EMPTY_QUERY = 0, /* empty query string was executed */ + PGRES_COMMAND_OK, /* a query command that doesn't return + * anything was executed properly by the + * backend */ + PGRES_TUPLES_OK, /* a query command that returns tuples was + * executed properly by the backend, PGresult + * contains the result tuples */ + PGRES_COPY_OUT, /* Copy Out data transfer in progress */ + PGRES_COPY_IN, /* Copy In data transfer in progress */ + PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the + * backend */ + PGRES_NONFATAL_ERROR, /* notice or warning message */ + PGRES_FATAL_ERROR, /* query failed */ + PGRES_COPY_BOTH /* Copy In/Out data transfer in progress */ +} ExecStatusType; + +typedef enum +{ + PQTRANS_IDLE, /* connection idle */ + PQTRANS_ACTIVE, /* command in progress */ + PQTRANS_INTRANS, /* idle, within transaction block */ + PQTRANS_INERROR, /* idle, within failed transaction */ + PQTRANS_UNKNOWN /* cannot determine status */ +} PGTransactionStatusType; + +typedef enum +{ + PQERRORS_TERSE, /* single-line error messages */ + PQERRORS_DEFAULT, /* recommended style */ + PQERRORS_VERBOSE /* all the facts, ma'am */ +} PGVerbosity; + +typedef enum +{ + PQPING_OK, /* server is accepting connections */ + PQPING_REJECT, /* server is alive but rejecting connections */ + PQPING_NO_RESPONSE, /* could not establish connection */ + PQPING_NO_ATTEMPT /* connection not attempted (bad params) */ +} PGPing; + +/* PGconn encapsulates a connection to the backend. + * The contents of this struct are not supposed to be known to applications. + */ +typedef struct pg_conn PGconn; + +/* PGresult encapsulates the result of a query (or more precisely, of a single + * SQL command --- a query string given to PQsendQuery can contain multiple + * commands and thus return multiple PGresult objects). + * The contents of this struct are not supposed to be known to applications. + */ +typedef struct pg_result PGresult; + +/* PGcancel encapsulates the information needed to cancel a running + * query on an existing connection. + * The contents of this struct are not supposed to be known to applications. + */ +typedef struct pg_cancel PGcancel; + +/* PGnotify represents the occurrence of a NOTIFY message. + * Ideally this would be an opaque typedef, but it's so simple that it's + * unlikely to change. + * NOTE: in Postgres 6.4 and later, the be_pid is the notifying backend's, + * whereas in earlier versions it was always your own backend's PID. + */ +typedef struct pgNotify +{ + char *relname; /* notification condition name */ + int be_pid; /* process ID of notifying server process */ + char *extra; /* notification parameter */ + /* Fields below here are private to libpq; apps should not use 'em */ + struct pgNotify *next; /* list link */ +} PGnotify; + +/* Function types for notice-handling callbacks */ +typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res); +typedef void (*PQnoticeProcessor) (void *arg, const char *message); + +/* Print options for PQprint() */ +typedef char pqbool; + +typedef struct _PQprintOpt +{ + pqbool header; /* print output field headings and row count */ + pqbool align; /* fill align the fields */ + pqbool standard; /* old brain dead format */ + pqbool html3; /* output html tables */ + pqbool expanded; /* expand tables */ + pqbool pager; /* use pager for output if needed */ + char *fieldSep; /* field separator */ + char *tableOpt; /* insert to HTML <table ...> */ + char *caption; /* HTML <caption> */ + char **fieldName; /* null terminated array of replacement field + * names */ +} PQprintOpt; + +/* ---------------- + * Structure for the conninfo parameter definitions returned by PQconndefaults + * or PQconninfoParse. + * + * All fields except "val" point at static strings which must not be altered. + * "val" is either NULL or a malloc'd current-value string. PQconninfoFree() + * will release both the val strings and the PQconninfoOption array itself. + * ---------------- + */ +typedef struct _PQconninfoOption +{ + char *keyword; /* The keyword of the option */ + char *envvar; /* Fallback environment variable name */ + char *compiled; /* Fallback compiled in default value */ + char *val; /* Option's current value, or NULL */ + char *label; /* Label for field in connect dialog */ + char *dispchar; /* Indicates how to display this field in a + * connect dialog. Values are: "" Display + * entered value as is "*" Password field - + * hide value "D" Debug option - don't show + * by default */ + int dispsize; /* Field size in characters for dialog */ +} PQconninfoOption; + +/* ---------------- + * PQArgBlock -- structure for PQfn() arguments + * ---------------- + */ +typedef struct +{ + int len; + int isint; + union + { + int *ptr; /* can't use void (dec compiler barfs) */ + int integer; + } u; +} PQArgBlock; + +/* ---------------- + * PGresAttDesc -- Data about a single attribute (column) of a query result + * ---------------- + */ +typedef struct pgresAttDesc +{ + char *name; /* column name */ + Oid tableid; /* source table, if known */ + int columnid; /* source column, if known */ + int format; /* format code for value (text/binary) */ + Oid typid; /* type id */ + int typlen; /* type size */ + int atttypmod; /* type-specific modifier info */ +} PGresAttDesc; + +/* ---------------- + * Exported functions of libpq + * ---------------- + */ + +/* === in fe-connect.c === */ + +/* make a new client connection to the backend */ +/* Asynchronous (non-blocking) */ +extern PGconn *PQconnectStart(const char *conninfo); +extern PGconn *PQconnectStartParams(const char **keywords, + const char **values, int expand_dbname); +extern PostgresPollingStatusType PQconnectPoll(PGconn *conn); + +/* Synchronous (blocking) */ +extern PGconn *PQconnectdb(const char *conninfo); +extern PGconn *PQconnectdbParams(const char **keywords, + const char **values, int expand_dbname); +extern PGconn *PQsetdbLogin(const char *pghost, const char *pgport, + const char *pgoptions, const char *pgtty, + const char *dbName, + const char *login, const char *pwd); + +#define PQsetdb(M_PGHOST,M_PGPORT,M_PGOPT,M_PGTTY,M_DBNAME) \ + PQsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, NULL, NULL) + +/* close the current connection and free the PGconn data structure */ +extern void PQfinish(PGconn *conn); + +/* get info about connection options known to PQconnectdb */ +extern PQconninfoOption *PQconndefaults(void); + +/* parse connection options in same way as PQconnectdb */ +extern PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg); + +/* free the data structure returned by PQconndefaults() or PQconninfoParse() */ +extern void PQconninfoFree(PQconninfoOption *connOptions); + +/* + * close the current connection and restablish a new one with the same + * parameters + */ +/* Asynchronous (non-blocking) */ +extern int PQresetStart(PGconn *conn); +extern PostgresPollingStatusType PQresetPoll(PGconn *conn); + +/* Synchronous (blocking) */ +extern void PQreset(PGconn *conn); + +/* request a cancel structure */ +extern PGcancel *PQgetCancel(PGconn *conn); + +/* free a cancel structure */ +extern void PQfreeCancel(PGcancel *cancel); + +/* issue a cancel request */ +extern int PQcancel(PGcancel *cancel, char *errbuf, int errbufsize); + +/* backwards compatible version of PQcancel; not thread-safe */ +extern int PQrequestCancel(PGconn *conn); + +/* Accessor functions for PGconn objects */ +extern char *PQdb(const PGconn *conn); +extern char *PQuser(const PGconn *conn); +extern char *PQpass(const PGconn *conn); +extern char *PQhost(const PGconn *conn); +extern char *PQport(const PGconn *conn); +extern char *PQtty(const PGconn *conn); +extern char *PQoptions(const PGconn *conn); +extern ConnStatusType PQstatus(const PGconn *conn); +extern PGTransactionStatusType PQtransactionStatus(const PGconn *conn); +extern const char *PQparameterStatus(const PGconn *conn, + const char *paramName); +extern int PQprotocolVersion(const PGconn *conn); +extern int PQserverVersion(const PGconn *conn); +extern char *PQerrorMessage(const PGconn *conn); +extern int PQsocket(const PGconn *conn); +extern int PQbackendPID(const PGconn *conn); +extern int PQconnectionNeedsPassword(const PGconn *conn); +extern int PQconnectionUsedPassword(const PGconn *conn); +extern int PQclientEncoding(const PGconn *conn); +extern int PQsetClientEncoding(PGconn *conn, const char *encoding); + +/* Get the OpenSSL structure associated with a connection. Returns NULL for + * unencrypted connections or if any other TLS library is in use. */ +extern void *PQgetssl(PGconn *conn); + +/* Tell libpq whether it needs to initialize OpenSSL */ +extern void PQinitSSL(int do_init); + +/* More detailed way to tell libpq whether it needs to initialize OpenSSL */ +extern void PQinitOpenSSL(int do_ssl, int do_crypto); + +/* Set verbosity for PQerrorMessage and PQresultErrorMessage */ +extern PGVerbosity PQsetErrorVerbosity(PGconn *conn, PGVerbosity verbosity); + +/* Enable/disable tracing */ +extern void PQtrace(PGconn *conn, FILE *debug_port); +extern void PQuntrace(PGconn *conn); + +/* Override default notice handling routines */ +extern PQnoticeReceiver PQsetNoticeReceiver(PGconn *conn, + PQnoticeReceiver proc, + void *arg); +extern PQnoticeProcessor PQsetNoticeProcessor(PGconn *conn, + PQnoticeProcessor proc, + void *arg); + +/* + * Used to set callback that prevents concurrent access to + * non-thread safe functions that libpq needs. + * The default implementation uses a libpq internal mutex. + * Only required for multithreaded apps that use kerberos + * both within their app and for postgresql connections. + */ +typedef void (*pgthreadlock_t) (int acquire); + +extern pgthreadlock_t PQregisterThreadLock(pgthreadlock_t newhandler); + +/* === in fe-exec.c === */ + +/* Simple synchronous query */ +extern PGresult *PQexec(PGconn *conn, const char *query); +extern PGresult *PQexecParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern PGresult *PQprepare(PGconn *conn, const char *stmtName, + const char *query, int nParams, + const Oid *paramTypes); +extern PGresult *PQexecPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); + +/* Interface for multiple-result or asynchronous queries */ +extern int PQsendQuery(PGconn *conn, const char *query); +extern int PQsendQueryParams(PGconn *conn, + const char *command, + int nParams, + const Oid *paramTypes, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern int PQsendPrepare(PGconn *conn, const char *stmtName, + const char *query, int nParams, + const Oid *paramTypes); +extern int PQsendQueryPrepared(PGconn *conn, + const char *stmtName, + int nParams, + const char *const * paramValues, + const int *paramLengths, + const int *paramFormats, + int resultFormat); +extern PGresult *PQgetResult(PGconn *conn); + +/* Routines for managing an asynchronous query */ +extern int PQisBusy(PGconn *conn); +extern int PQconsumeInput(PGconn *conn); + +/* LISTEN/NOTIFY support */ +extern PGnotify *PQnotifies(PGconn *conn); + +/* Routines for copy in/out */ +extern int PQputCopyData(PGconn *conn, const char *buffer, int nbytes); +extern int PQputCopyEnd(PGconn *conn, const char *errormsg); +extern int PQgetCopyData(PGconn *conn, char **buffer, int async); + +/* Deprecated routines for copy in/out */ +extern int PQgetline(PGconn *conn, char *string, int length); +extern int PQputline(PGconn *conn, const char *string); +extern int PQgetlineAsync(PGconn *conn, char *buffer, int bufsize); +extern int PQputnbytes(PGconn *conn, const char *buffer, int nbytes); +extern int PQendcopy(PGconn *conn); + +/* Set blocking/nonblocking connection to the backend */ +extern int PQsetnonblocking(PGconn *conn, int arg); +extern int PQisnonblocking(const PGconn *conn); +extern int PQisthreadsafe(void); +extern PGPing PQping(const char *conninfo); +extern PGPing PQpingParams(const char **keywords, + const char **values, int expand_dbname); + +/* Force the write buffer to be written (or at least try) */ +extern int PQflush(PGconn *conn); + +/* + * "Fast path" interface --- not really recommended for application + * use + */ +extern PGresult *PQfn(PGconn *conn, + int fnid, + int *result_buf, + int *result_len, + int result_is_int, + const PQArgBlock *args, + int nargs); + +/* Accessor functions for PGresult objects */ +extern ExecStatusType PQresultStatus(const PGresult *res); +extern char *PQresStatus(ExecStatusType status); +extern char *PQresultErrorMessage(const PGresult *res); +extern char *PQresultErrorField(const PGresult *res, int fieldcode); +extern int PQntuples(const PGresult *res); +extern int PQnfields(const PGresult *res); +extern int PQbinaryTuples(const PGresult *res); +extern char *PQfname(const PGresult *res, int field_num); +extern int PQfnumber(const PGresult *res, const char *field_name); +extern Oid PQftable(const PGresult *res, int field_num); +extern int PQftablecol(const PGresult *res, int field_num); +extern int PQfformat(const PGresult *res, int field_num); +extern Oid PQftype(const PGresult *res, int field_num); +extern int PQfsize(const PGresult *res, int field_num); +extern int PQfmod(const PGresult *res, int field_num); +extern char *PQcmdStatus(PGresult *res); +extern char *PQoidStatus(const PGresult *res); /* old and ugly */ +extern Oid PQoidValue(const PGresult *res); /* new and improved */ +extern char *PQcmdTuples(PGresult *res); +extern char *PQgetvalue(const PGresult *res, int tup_num, int field_num); +extern int PQgetlength(const PGresult *res, int tup_num, int field_num); +extern int PQgetisnull(const PGresult *res, int tup_num, int field_num); +extern int PQnparams(const PGresult *res); +extern Oid PQparamtype(const PGresult *res, int param_num); + +/* Describe prepared statements and portals */ +extern PGresult *PQdescribePrepared(PGconn *conn, const char *stmt); +extern PGresult *PQdescribePortal(PGconn *conn, const char *portal); +extern int PQsendDescribePrepared(PGconn *conn, const char *stmt); +extern int PQsendDescribePortal(PGconn *conn, const char *portal); + +/* Delete a PGresult */ +extern void PQclear(PGresult *res); + +/* For freeing other alloc'd results, such as PGnotify structs */ +extern void PQfreemem(void *ptr); + +/* Exists for backward compatibility. bjm 2003-03-24 */ +#define PQfreeNotify(ptr) PQfreemem(ptr) + +/* Error when no password was given. */ +/* Note: depending on this is deprecated; use PQconnectionNeedsPassword(). */ +#define PQnoPasswordSupplied "fe_sendauth: no password supplied\n" + +/* Create and manipulate PGresults */ +extern PGresult *PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status); +extern PGresult *PQcopyResult(const PGresult *src, int flags); +extern int PQsetResultAttrs(PGresult *res, int numAttributes, PGresAttDesc *attDescs); +extern void *PQresultAlloc(PGresult *res, size_t nBytes); +extern int PQsetvalue(PGresult *res, int tup_num, int field_num, char *value, int len); + +/* Quoting strings before inclusion in queries. */ +extern size_t PQescapeStringConn(PGconn *conn, + char *to, const char *from, size_t length, + int *error); +extern char *PQescapeLiteral(PGconn *conn, const char *str, size_t len); +extern char *PQescapeIdentifier(PGconn *conn, const char *str, size_t len); +extern unsigned char *PQescapeByteaConn(PGconn *conn, + const unsigned char *from, size_t from_length, + size_t *to_length); +extern unsigned char *PQunescapeBytea(const unsigned char *strtext, + size_t *retbuflen); + +/* These forms are deprecated! */ +extern size_t PQescapeString(char *to, const char *from, size_t length); +extern unsigned char *PQescapeBytea(const unsigned char *from, size_t from_length, + size_t *to_length); + + + +/* === in fe-print.c === */ + +extern void +PQprint(FILE *fout, /* output stream */ + const PGresult *res, + const PQprintOpt *ps); /* option structure */ + +/* + * really old printing routines + */ +extern void +PQdisplayTuples(const PGresult *res, + FILE *fp, /* where to send the output */ + int fillAlign, /* pad the fields with spaces */ + const char *fieldSep, /* field separator */ + int printHeader, /* display headers? */ + int quiet); + +extern void +PQprintTuples(const PGresult *res, + FILE *fout, /* output stream */ + int printAttName, /* print attribute names */ + int terseOutput, /* delimiter bars */ + int width); /* width of column, if 0, use variable width */ + + +/* === in fe-lobj.c === */ + +/* Large-object access routines */ +extern int lo_open(PGconn *conn, Oid lobjId, int mode); +extern int lo_close(PGconn *conn, int fd); +extern int lo_read(PGconn *conn, int fd, char *buf, size_t len); +extern int lo_write(PGconn *conn, int fd, const char *buf, size_t len); +extern int lo_lseek(PGconn *conn, int fd, int offset, int whence); +extern Oid lo_creat(PGconn *conn, int mode); +extern Oid lo_create(PGconn *conn, Oid lobjId); +extern int lo_tell(PGconn *conn, int fd); +extern int lo_truncate(PGconn *conn, int fd, size_t len); +extern int lo_unlink(PGconn *conn, Oid lobjId); +extern Oid lo_import(PGconn *conn, const char *filename); +extern Oid lo_import_with_oid(PGconn *conn, const char *filename, Oid lobjId); +extern int lo_export(PGconn *conn, Oid lobjId, const char *filename); + +/* === in fe-misc.c === */ + +/* Get the version of the libpq library in use */ +extern int PQlibVersion(void); + +/* Determine length of multibyte encoded char at *s */ +extern int PQmblen(const char *s, int encoding); + +/* Determine display length of multibyte encoded char at *s */ +extern int PQdsplen(const char *s, int encoding); + +/* Get encoding id from environment variable PGCLIENTENCODING */ +extern int PQenv2encoding(void); + +/* === in fe-auth.c === */ + +extern char *PQencryptPassword(const char *passwd, const char *user); + +/* === in encnames.c === */ + +extern int pg_char_to_encoding(const char *name); +extern const char *pg_encoding_to_char(int encoding); +extern int pg_valid_server_encoding_id(int encoding); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBPQ_FE_H */ diff --git a/Frameworks/PostgresKit/PostgreSQL/include/postgres_ext.h b/Frameworks/PostgresKit/PostgreSQL/include/postgres_ext.h new file mode 100644 index 00000000..b6ebb7aa --- /dev/null +++ b/Frameworks/PostgresKit/PostgreSQL/include/postgres_ext.h @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------- + * + * postgres_ext.h + * + * This file contains declarations of things that are visible everywhere + * in PostgreSQL *and* are visible to clients of frontend interface libraries. + * For example, the Oid type is part of the API of libpq and other libraries. + * + * Declarations which are specific to a particular interface should + * go in the header file for that interface (such as libpq-fe.h). This + * file is only for fundamental Postgres declarations. + * + * User-written C functions don't count as "external to Postgres." + * Those function much as local modifications to the backend itself, and + * use header files that are otherwise internal to Postgres to interface + * with the backend. + * + * src/include/postgres_ext.h + * + *------------------------------------------------------------------------- + */ + +#ifndef POSTGRES_EXT_H +#define POSTGRES_EXT_H + +/* + * Object ID is a fundamental type in Postgres. + */ +typedef unsigned int Oid; + +#ifdef __cplusplus +#define InvalidOid (Oid(0)) +#else +#define InvalidOid ((Oid) 0) +#endif + +#define OID_MAX UINT_MAX +/* you will need to include <limits.h> to use the above #define */ + + +/* + * Identifiers of error message fields. Kept here to keep common + * between frontend and backend, and also to export them to libpq + * applications. + */ +#define PG_DIAG_SEVERITY 'S' +#define PG_DIAG_SQLSTATE 'C' +#define PG_DIAG_MESSAGE_PRIMARY 'M' +#define PG_DIAG_MESSAGE_DETAIL 'D' +#define PG_DIAG_MESSAGE_HINT 'H' +#define PG_DIAG_STATEMENT_POSITION 'P' +#define PG_DIAG_INTERNAL_POSITION 'p' +#define PG_DIAG_INTERNAL_QUERY 'q' +#define PG_DIAG_CONTEXT 'W' +#define PG_DIAG_SOURCE_FILE 'F' +#define PG_DIAG_SOURCE_LINE 'L' +#define PG_DIAG_SOURCE_FUNCTION 'R' + +#endif diff --git a/Frameworks/PostgresKit/PostgreSQL/lib/libpq.a b/Frameworks/PostgresKit/PostgreSQL/lib/libpq.a Binary files differnew file mode 100644 index 00000000..72502f0c --- /dev/null +++ b/Frameworks/PostgresKit/PostgreSQL/lib/libpq.a diff --git a/Frameworks/PostgresKit/PostgresKit.xcodeproj/project.pbxproj b/Frameworks/PostgresKit/PostgresKit.xcodeproj/project.pbxproj new file mode 100644 index 00000000..d4343d90 --- /dev/null +++ b/Frameworks/PostgresKit/PostgresKit.xcodeproj/project.pbxproj @@ -0,0 +1,637 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 170465CE15C2960F00DC5BE5 /* FLXPostgresTypeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 170465CC15C2960F00DC5BE5 /* FLXPostgresTypeHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 170465CF15C2960F00DC5BE5 /* FLXPostgresTypeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 170465CD15C2960F00DC5BE5 /* FLXPostgresTypeHandler.m */; }; + 1731F02B15EE09E000D973EB /* FLXPostgresConnectionParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 1731F02915EE09E000D973EB /* FLXPostgresConnectionParameters.h */; }; + 1731F02C15EE09E000D973EB /* FLXPostgresConnectionParameters.m in Sources */ = {isa = PBXBuildFile; fileRef = 1731F02A15EE09E000D973EB /* FLXPostgresConnectionParameters.m */; }; + 1731F10815F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 1731F10615F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.h */; }; + 1731F10915F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 1731F10715F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.m */; }; + 1731F52E15F48BA500D973EB /* FLXPostgresError.h in Headers */ = {isa = PBXBuildFile; fileRef = 1731F52C15F48BA500D973EB /* FLXPostgresError.h */; }; + 1731F52F15F48BA500D973EB /* FLXPostgresError.m in Sources */ = {isa = PBXBuildFile; fileRef = 1731F52D15F48BA500D973EB /* FLXPostgresError.m */; }; + 173D4E5A15BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4E5615BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4E5B15BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 173D4E5715BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.m */; }; + 173D4E5C15BAB1DD0007F267 /* FLXPostgresTypeStringHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4E5815BAB1DD0007F267 /* FLXPostgresTypeStringHandler.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4E5D15BAB1DD0007F267 /* FLXPostgresTypeStringHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 173D4E5915BAB1DD0007F267 /* FLXPostgresTypeStringHandler.m */; }; + 173D4EA115BAB2A80007F267 /* FLXPostgresConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4E9515BAB2A80007F267 /* FLXPostgresConnection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4EA215BAB2A80007F267 /* FLXPostgresConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = 173D4E9615BAB2A80007F267 /* FLXPostgresConnection.m */; }; + 173D4EA315BAB2A80007F267 /* FLXPostgresConnectionUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4E9715BAB2A80007F267 /* FLXPostgresConnectionUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4EA415BAB2A80007F267 /* FLXPostgresConnectionUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 173D4E9815BAB2A80007F267 /* FLXPostgresConnectionUtils.m */; }; + 173D4EA515BAB2A80007F267 /* FLXPostgresException.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4E9915BAB2A80007F267 /* FLXPostgresException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4EA615BAB2A80007F267 /* FLXPostgresException.m in Sources */ = {isa = PBXBuildFile; fileRef = 173D4E9A15BAB2A80007F267 /* FLXPostgresException.m */; }; + 173D4EA715BAB2A80007F267 /* FLXPostgresResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4E9B15BAB2A80007F267 /* FLXPostgresResult.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4EA815BAB2A80007F267 /* FLXPostgresResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 173D4E9C15BAB2A80007F267 /* FLXPostgresResult.m */; }; + 173D4EA915BAB2A80007F267 /* FLXPostgresStatement.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4E9D15BAB2A80007F267 /* FLXPostgresStatement.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4EAA15BAB2A80007F267 /* FLXPostgresStatement.m in Sources */ = {isa = PBXBuildFile; fileRef = 173D4E9E15BAB2A80007F267 /* FLXPostgresStatement.m */; }; + 173D4EAB15BAB2A80007F267 /* PostgresKit.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4E9F15BAB2A80007F267 /* PostgresKit.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4EE215BACA700007F267 /* libpq.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 173D4EE115BACA700007F267 /* libpq.a */; }; + 173D4EE515BACA900007F267 /* libpq-fe.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4EE315BACA900007F267 /* libpq-fe.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4EE615BACA900007F267 /* postgres_ext.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4EE415BACA900007F267 /* postgres_ext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4F4515BAD22B0007F267 /* FLXPostgresTypeHandlerProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4EA015BAB2A80007F267 /* FLXPostgresTypeHandlerProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D4F5715BAD3030007F267 /* FLXPostgresTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D4F5615BAD3030007F267 /* FLXPostgresTypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D506A15BB93470007F267 /* libssl.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 173D506915BB93470007F267 /* libssl.dylib */; }; + 173D507015BB93E40007F267 /* libcrypto.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 173D506F15BB93E40007F267 /* libcrypto.dylib */; }; + 173D508C15BBD98D0007F267 /* FLXConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D508B15BBD98D0007F267 /* FLXConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 173D508F15BBD9BF0007F267 /* FLXConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 173D508E15BBD9BF0007F267 /* FLXConstants.m */; }; + 173D513515BBE50D0007F267 /* FLXPostgresConnectionDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 173D513415BBE50D0007F267 /* FLXPostgresConnectionDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 177AC5F015C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.h in Headers */ = {isa = PBXBuildFile; fileRef = 177AC5EE15C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.h */; }; + 177AC5F115C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.m in Sources */ = {isa = PBXBuildFile; fileRef = 177AC5EF15C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.m */; }; + 177AC66915C53CB000A3658D /* FLXPostgresConnectionQueryExecution.h in Headers */ = {isa = PBXBuildFile; fileRef = 177AC66715C53CB000A3658D /* FLXPostgresConnectionQueryExecution.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 177AC66A15C53CB000A3658D /* FLXPostgresConnectionQueryExecution.m in Sources */ = {isa = PBXBuildFile; fileRef = 177AC66815C53CB000A3658D /* FLXPostgresConnectionQueryExecution.m */; }; + 177AC67F15C53FA400A3658D /* FLXPostgresConnectionPrivateAPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 177AC67D15C53FA400A3658D /* FLXPostgresConnectionPrivateAPI.h */; }; + 177AC6B015C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.h in Headers */ = {isa = PBXBuildFile; fileRef = 177AC6AE15C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 177AC6B115C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.m in Sources */ = {isa = PBXBuildFile; fileRef = 177AC6AF15C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.m */; }; + 177C9BAB15CD37E000128642 /* FLXPostgresConnectionEncoding.h in Headers */ = {isa = PBXBuildFile; fileRef = 177C9BA915CD37E000128642 /* FLXPostgresConnectionEncoding.h */; }; + 177C9BAC15CD37E000128642 /* FLXPostgresConnectionEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 177C9BAA15CD37E000128642 /* FLXPostgresConnectionEncoding.m */; }; + 17E595F214F3058F0054EE08 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 17E595F114F3058F0054EE08 /* Foundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 170465CC15C2960F00DC5BE5 /* FLXPostgresTypeHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresTypeHandler.h; sourceTree = "<group>"; }; + 170465CD15C2960F00DC5BE5 /* FLXPostgresTypeHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresTypeHandler.m; sourceTree = "<group>"; }; + 1731F02915EE09E000D973EB /* FLXPostgresConnectionParameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnectionParameters.h; sourceTree = "<group>"; }; + 1731F02A15EE09E000D973EB /* FLXPostgresConnectionParameters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresConnectionParameters.m; sourceTree = "<group>"; }; + 1731F10615F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresTypeDateTimeHandler.h; sourceTree = "<group>"; }; + 1731F10715F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresTypeDateTimeHandler.m; sourceTree = "<group>"; }; + 1731F52C15F48BA500D973EB /* FLXPostgresError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresError.h; sourceTree = "<group>"; }; + 1731F52D15F48BA500D973EB /* FLXPostgresError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresError.m; sourceTree = "<group>"; }; + 173D4E2F15BAB13C0007F267 /* PostgresKit-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "PostgresKit-Prefix.pch"; path = "Source/PostgresKit-Prefix.pch"; sourceTree = "<group>"; }; + 173D4E5615BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresTypeNumberHandler.h; sourceTree = "<group>"; }; + 173D4E5715BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresTypeNumberHandler.m; sourceTree = "<group>"; }; + 173D4E5815BAB1DD0007F267 /* FLXPostgresTypeStringHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresTypeStringHandler.h; sourceTree = "<group>"; }; + 173D4E5915BAB1DD0007F267 /* FLXPostgresTypeStringHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresTypeStringHandler.m; sourceTree = "<group>"; }; + 173D4E9515BAB2A80007F267 /* FLXPostgresConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnection.h; sourceTree = "<group>"; }; + 173D4E9615BAB2A80007F267 /* FLXPostgresConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresConnection.m; sourceTree = "<group>"; }; + 173D4E9715BAB2A80007F267 /* FLXPostgresConnectionUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnectionUtils.h; sourceTree = "<group>"; }; + 173D4E9815BAB2A80007F267 /* FLXPostgresConnectionUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresConnectionUtils.m; sourceTree = "<group>"; }; + 173D4E9915BAB2A80007F267 /* FLXPostgresException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresException.h; sourceTree = "<group>"; }; + 173D4E9A15BAB2A80007F267 /* FLXPostgresException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresException.m; sourceTree = "<group>"; }; + 173D4E9B15BAB2A80007F267 /* FLXPostgresResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresResult.h; sourceTree = "<group>"; }; + 173D4E9C15BAB2A80007F267 /* FLXPostgresResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresResult.m; sourceTree = "<group>"; }; + 173D4E9D15BAB2A80007F267 /* FLXPostgresStatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresStatement.h; sourceTree = "<group>"; }; + 173D4E9E15BAB2A80007F267 /* FLXPostgresStatement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresStatement.m; sourceTree = "<group>"; }; + 173D4E9F15BAB2A80007F267 /* PostgresKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PostgresKit.h; sourceTree = "<group>"; }; + 173D4EA015BAB2A80007F267 /* FLXPostgresTypeHandlerProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresTypeHandlerProtocol.h; sourceTree = "<group>"; }; + 173D4EE115BACA700007F267 /* libpq.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libpq.a; sourceTree = "<group>"; }; + 173D4EE315BACA900007F267 /* libpq-fe.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "libpq-fe.h"; sourceTree = "<group>"; }; + 173D4EE415BACA900007F267 /* postgres_ext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = postgres_ext.h; sourceTree = "<group>"; }; + 173D4F5615BAD3030007F267 /* FLXPostgresTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresTypes.h; sourceTree = "<group>"; }; + 173D506915BB93470007F267 /* libssl.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libssl.dylib; path = usr/lib/libssl.dylib; sourceTree = SDKROOT; }; + 173D506F15BB93E40007F267 /* libcrypto.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcrypto.dylib; path = usr/lib/libcrypto.dylib; sourceTree = SDKROOT; }; + 173D508B15BBD98D0007F267 /* FLXConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXConstants.h; sourceTree = "<group>"; }; + 173D508E15BBD9BF0007F267 /* FLXConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXConstants.m; sourceTree = "<group>"; }; + 173D513415BBE50D0007F267 /* FLXPostgresConnectionDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnectionDelegate.h; sourceTree = "<group>"; }; + 177AC5EE15C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnectionTypeHandling.h; sourceTree = "<group>"; }; + 177AC5EF15C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresConnectionTypeHandling.m; sourceTree = "<group>"; }; + 177AC66715C53CB000A3658D /* FLXPostgresConnectionQueryExecution.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnectionQueryExecution.h; sourceTree = "<group>"; }; + 177AC66815C53CB000A3658D /* FLXPostgresConnectionQueryExecution.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresConnectionQueryExecution.m; sourceTree = "<group>"; }; + 177AC67D15C53FA400A3658D /* FLXPostgresConnectionPrivateAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnectionPrivateAPI.h; sourceTree = "<group>"; }; + 177AC6AE15C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnectionQueryPreparation.h; sourceTree = "<group>"; }; + 177AC6AF15C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresConnectionQueryPreparation.m; sourceTree = "<group>"; }; + 177C9BA915CD37E000128642 /* FLXPostgresConnectionEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FLXPostgresConnectionEncoding.h; sourceTree = "<group>"; }; + 177C9BAA15CD37E000128642 /* FLXPostgresConnectionEncoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FLXPostgresConnectionEncoding.m; sourceTree = "<group>"; }; + 17E595F114F3058F0054EE08 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 17F5B77C15C9D092006DA689 /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; }; + 8DC2EF5A0486A6940098B216 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Resources/Info.plist; sourceTree = "<group>"; }; + 8DC2EF5B0486A6940098B216 /* PostgresKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PostgresKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 8DC2EF560486A6940098B216 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 17E595F214F3058F0054EE08 /* Foundation.framework in Frameworks */, + 173D4EE215BACA700007F267 /* libpq.a in Frameworks */, + 173D506A15BB93470007F267 /* libssl.dylib in Frameworks */, + 173D507015BB93E40007F267 /* libcrypto.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 034768DFFF38A50411DB9C8B /* Products */ = { + isa = PBXGroup; + children = ( + 8DC2EF5B0486A6940098B216 /* PostgresKit.framework */, + ); + name = Products; + sourceTree = "<group>"; + }; + 0867D691FE84028FC02AAC07 /* QueryKit */ = { + isa = PBXGroup; + children = ( + 17F5B77C15C9D092006DA689 /* README */, + 173D4E2F15BAB13C0007F267 /* PostgresKit-Prefix.pch */, + 173D4E2115BAB0FE0007F267 /* Source */, + 089C1665FE841158C02AAC07 /* Resources */, + 0867D69AFE84028FC02AAC07 /* Frameworks */, + 034768DFFF38A50411DB9C8B /* Products */, + ); + name = QueryKit; + sourceTree = "<group>"; + }; + 0867D69AFE84028FC02AAC07 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 173D506915BB93470007F267 /* libssl.dylib */, + 173D506F15BB93E40007F267 /* libcrypto.dylib */, + 17E595F114F3058F0054EE08 /* Foundation.framework */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + 089C1665FE841158C02AAC07 /* Resources */ = { + isa = PBXGroup; + children = ( + 173D4EDE15BACA090007F267 /* PostgreSQL */, + 8DC2EF5A0486A6940098B216 /* Info.plist */, + ); + name = Resources; + sourceTree = "<group>"; + }; + 1731F50415F369E400D973EB /* Query */ = { + isa = PBXGroup; + children = ( + 177AC66715C53CB000A3658D /* FLXPostgresConnectionQueryExecution.h */, + 177AC66815C53CB000A3658D /* FLXPostgresConnectionQueryExecution.m */, + 177AC6AE15C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.h */, + 177AC6AF15C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.m */, + ); + name = Query; + sourceTree = "<group>"; + }; + 1731F50515F369FE00D973EB /* Encoding */ = { + isa = PBXGroup; + children = ( + 177C9BA915CD37E000128642 /* FLXPostgresConnectionEncoding.h */, + 177C9BAA15CD37E000128642 /* FLXPostgresConnectionEncoding.m */, + ); + name = Encoding; + sourceTree = "<group>"; + }; + 1731F50615F36A3E00D973EB /* Other */ = { + isa = PBXGroup; + children = ( + 173D4E9715BAB2A80007F267 /* FLXPostgresConnectionUtils.h */, + 173D4E9815BAB2A80007F267 /* FLXPostgresConnectionUtils.m */, + 1731F02915EE09E000D973EB /* FLXPostgresConnectionParameters.h */, + 1731F02A15EE09E000D973EB /* FLXPostgresConnectionParameters.m */, + 177AC5EE15C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.h */, + 177AC5EF15C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.m */, + ); + name = Other; + sourceTree = "<group>"; + }; + 1731F52B15F48B4400D973EB /* Domain */ = { + isa = PBXGroup; + children = ( + 1731F52C15F48BA500D973EB /* FLXPostgresError.h */, + 1731F52D15F48BA500D973EB /* FLXPostgresError.m */, + 173D4E9B15BAB2A80007F267 /* FLXPostgresResult.h */, + 173D4E9C15BAB2A80007F267 /* FLXPostgresResult.m */, + 173D4E9D15BAB2A80007F267 /* FLXPostgresStatement.h */, + 173D4E9E15BAB2A80007F267 /* FLXPostgresStatement.m */, + 173D4E9915BAB2A80007F267 /* FLXPostgresException.h */, + 173D4E9A15BAB2A80007F267 /* FLXPostgresException.m */, + ); + name = Domain; + sourceTree = "<group>"; + }; + 173D4E2115BAB0FE0007F267 /* Source */ = { + isa = PBXGroup; + children = ( + 173D4E9F15BAB2A80007F267 /* PostgresKit.h */, + 1731F52B15F48B4400D973EB /* Domain */, + 173D513315BBE4230007F267 /* Connection */, + 173D508D15BBD99B0007F267 /* Constants */, + 173D4E5015BAB17A0007F267 /* Types */, + ); + path = Source; + sourceTree = "<group>"; + }; + 173D4E5015BAB17A0007F267 /* Types */ = { + isa = PBXGroup; + children = ( + 173D4F5615BAD3030007F267 /* FLXPostgresTypes.h */, + 173D4EA015BAB2A80007F267 /* FLXPostgresTypeHandlerProtocol.h */, + 17F5B62215C7D1DA006DA689 /* Handlers */, + ); + name = Types; + sourceTree = "<group>"; + }; + 173D4EDE15BACA090007F267 /* PostgreSQL */ = { + isa = PBXGroup; + children = ( + 173D4EDF15BACA280007F267 /* include */, + 173D4EE015BACA3F0007F267 /* lib */, + ); + name = PostgreSQL; + sourceTree = "<group>"; + }; + 173D4EDF15BACA280007F267 /* include */ = { + isa = PBXGroup; + children = ( + 173D4EE315BACA900007F267 /* libpq-fe.h */, + 173D4EE415BACA900007F267 /* postgres_ext.h */, + ); + name = include; + path = PostgreSQL/include; + sourceTree = "<group>"; + }; + 173D4EE015BACA3F0007F267 /* lib */ = { + isa = PBXGroup; + children = ( + 173D4EE115BACA700007F267 /* libpq.a */, + ); + name = lib; + path = PostgreSQL/lib; + sourceTree = "<group>"; + }; + 173D508D15BBD99B0007F267 /* Constants */ = { + isa = PBXGroup; + children = ( + 173D508B15BBD98D0007F267 /* FLXConstants.h */, + 173D508E15BBD9BF0007F267 /* FLXConstants.m */, + ); + name = Constants; + sourceTree = "<group>"; + }; + 173D513315BBE4230007F267 /* Connection */ = { + isa = PBXGroup; + children = ( + 173D4E9515BAB2A80007F267 /* FLXPostgresConnection.h */, + 173D4E9615BAB2A80007F267 /* FLXPostgresConnection.m */, + 173D513415BBE50D0007F267 /* FLXPostgresConnectionDelegate.h */, + 177AC67D15C53FA400A3658D /* FLXPostgresConnectionPrivateAPI.h */, + 1731F50515F369FE00D973EB /* Encoding */, + 1731F50415F369E400D973EB /* Query */, + 1731F50615F36A3E00D973EB /* Other */, + ); + name = Connection; + sourceTree = "<group>"; + }; + 17F5B62215C7D1DA006DA689 /* Handlers */ = { + isa = PBXGroup; + children = ( + 170465CC15C2960F00DC5BE5 /* FLXPostgresTypeHandler.h */, + 170465CD15C2960F00DC5BE5 /* FLXPostgresTypeHandler.m */, + 173D4E5815BAB1DD0007F267 /* FLXPostgresTypeStringHandler.h */, + 173D4E5915BAB1DD0007F267 /* FLXPostgresTypeStringHandler.m */, + 173D4E5615BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.h */, + 173D4E5715BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.m */, + 1731F10615F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.h */, + 1731F10715F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.m */, + ); + name = Handlers; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 8DC2EF500486A6940098B216 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 173D4E5A15BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.h in Headers */, + 173D4E5C15BAB1DD0007F267 /* FLXPostgresTypeStringHandler.h in Headers */, + 173D4EA115BAB2A80007F267 /* FLXPostgresConnection.h in Headers */, + 173D4EA315BAB2A80007F267 /* FLXPostgresConnectionUtils.h in Headers */, + 173D4EA515BAB2A80007F267 /* FLXPostgresException.h in Headers */, + 173D4EA715BAB2A80007F267 /* FLXPostgresResult.h in Headers */, + 173D4EA915BAB2A80007F267 /* FLXPostgresStatement.h in Headers */, + 173D4EAB15BAB2A80007F267 /* PostgresKit.h in Headers */, + 173D4EE515BACA900007F267 /* libpq-fe.h in Headers */, + 173D4EE615BACA900007F267 /* postgres_ext.h in Headers */, + 173D4F4515BAD22B0007F267 /* FLXPostgresTypeHandlerProtocol.h in Headers */, + 173D4F5715BAD3030007F267 /* FLXPostgresTypes.h in Headers */, + 173D508C15BBD98D0007F267 /* FLXConstants.h in Headers */, + 173D513515BBE50D0007F267 /* FLXPostgresConnectionDelegate.h in Headers */, + 170465CE15C2960F00DC5BE5 /* FLXPostgresTypeHandler.h in Headers */, + 177AC5F015C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.h in Headers */, + 177AC66915C53CB000A3658D /* FLXPostgresConnectionQueryExecution.h in Headers */, + 177AC67F15C53FA400A3658D /* FLXPostgresConnectionPrivateAPI.h in Headers */, + 177AC6B015C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.h in Headers */, + 177C9BAB15CD37E000128642 /* FLXPostgresConnectionEncoding.h in Headers */, + 1731F02B15EE09E000D973EB /* FLXPostgresConnectionParameters.h in Headers */, + 1731F10815F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.h in Headers */, + 1731F52E15F48BA500D973EB /* FLXPostgresError.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 8DC2EF4F0486A6940098B216 /* PostgresKit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "PostgresKit" */; + buildPhases = ( + 8DC2EF540486A6940098B216 /* Sources */, + 8DC2EF560486A6940098B216 /* Frameworks */, + 8DC2EF500486A6940098B216 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PostgresKit; + productInstallPath = "$(HOME)/Library/Frameworks"; + productName = QueryKit; + productReference = 8DC2EF5B0486A6940098B216 /* PostgresKit.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 0867D690FE84028FC02AAC07 /* Project object */ = { + isa = PBXProject; + buildConfigurationList = 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "PostgresKit" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 0867D691FE84028FC02AAC07 /* QueryKit */; + productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 8DC2EF4F0486A6940098B216 /* PostgresKit */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 8DC2EF540486A6940098B216 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 173D4E5B15BAB1DD0007F267 /* FLXPostgresTypeNumberHandler.m in Sources */, + 173D4E5D15BAB1DD0007F267 /* FLXPostgresTypeStringHandler.m in Sources */, + 173D4EA215BAB2A80007F267 /* FLXPostgresConnection.m in Sources */, + 173D4EA415BAB2A80007F267 /* FLXPostgresConnectionUtils.m in Sources */, + 173D4EA615BAB2A80007F267 /* FLXPostgresException.m in Sources */, + 173D4EA815BAB2A80007F267 /* FLXPostgresResult.m in Sources */, + 173D4EAA15BAB2A80007F267 /* FLXPostgresStatement.m in Sources */, + 173D508F15BBD9BF0007F267 /* FLXConstants.m in Sources */, + 170465CF15C2960F00DC5BE5 /* FLXPostgresTypeHandler.m in Sources */, + 177AC5F115C50F6E00A3658D /* FLXPostgresConnectionTypeHandling.m in Sources */, + 177AC66A15C53CB000A3658D /* FLXPostgresConnectionQueryExecution.m in Sources */, + 177AC6B115C5460C00A3658D /* FLXPostgresConnectionQueryPreparation.m in Sources */, + 177C9BAC15CD37E000128642 /* FLXPostgresConnectionEncoding.m in Sources */, + 1731F02C15EE09E000D973EB /* FLXPostgresConnectionParameters.m in Sources */, + 1731F10915F1A52B00D973EB /* FLXPostgresTypeDateTimeHandler.m in Sources */, + 1731F52F15F48BA500D973EB /* FLXPostgresError.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 17E5952D14F302740054EE08 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + x86_64, + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Source/PostgresKit-Prefix.pch"; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Resources/Info.plist; + INFOPLIST_PREFIX_HEADER = ""; + PREBINDING = NO; + SDKROOT = macosx10.5; + VALID_ARCHS = "i386 ppc x86_64"; + }; + name = Distribution; + }; + 17E5952E14F302740054EE08 /* Distribution */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_VERSION = A; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Source/PostgresKit-Prefix.pch"; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PROTOTYPE_CONVERSION = NO; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_STRICT_SELECTOR_MATCH = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VALUE = YES; + INFOPLIST_FILE = Resources/Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/PostgreSQL/lib\"", + ); + PRODUCT_NAME = PostgresKit; + WARNING_CFLAGS = "-Wmost"; + WRAPPER_EXTENSION = framework; + }; + name = Distribution; + }; + 1DEB91AE08733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Source/PostgresKit-Prefix.pch"; + GCC_SYMBOLS_PRIVATE_EXTERN = YES; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PROTOTYPE_CONVERSION = NO; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_STRICT_SELECTOR_MATCH = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VALUE = YES; + GENERATE_PKGINFO_FILE = YES; + INFOPLIST_FILE = Resources/Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/PostgreSQL/lib\"", + ); + PRODUCT_NAME = PostgresKit; + WARNING_CFLAGS = "-Wmost"; + WRAPPER_EXTENSION = framework; + }; + name = Debug; + }; + 1DEB91AF08733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_VERSION = A; + GCC_GENERATE_DEBUGGING_SYMBOLS = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Source/PostgresKit-Prefix.pch"; + GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO = YES; + GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES; + GCC_WARN_ABOUT_MISSING_NEWLINE = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; + GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES; + GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; + GCC_WARN_MISSING_PARENTHESES = YES; + GCC_WARN_MULTIPLE_DEFINITION_TYPES_FOR_SELECTOR = YES; + GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES; + GCC_WARN_PROTOTYPE_CONVERSION = NO; + GCC_WARN_SHADOW = YES; + GCC_WARN_SIGN_COMPARE = YES; + GCC_WARN_STRICT_SELECTOR_MATCH = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNKNOWN_PRAGMAS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_LABEL = YES; + GCC_WARN_UNUSED_PARAMETER = YES; + GCC_WARN_UNUSED_VALUE = YES; + INFOPLIST_FILE = Resources/Info.plist; + INSTALL_PATH = "@executable_path/../Frameworks"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/PostgreSQL/lib\"", + ); + PRODUCT_NAME = PostgresKit; + WARNING_CFLAGS = "-Wmost"; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; + 1DEB91B208733DA50010E9CD /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + x86_64, + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Source/PostgresKit-Prefix.pch"; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Resources/Info.plist; + INFOPLIST_PREFIX_HEADER = ""; + ONLY_ACTIVE_ARCH = YES; + PREBINDING = NO; + SDKROOT = macosx10.5; + VALID_ARCHS = "i386 ppc x86_64"; + }; + name = Debug; + }; + 1DEB91B308733DA50010E9CD /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + i386, + ppc, + x86_64, + ); + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "Source/PostgresKit-Prefix.pch"; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INFOPLIST_FILE = Resources/Info.plist; + INFOPLIST_PREFIX_HEADER = ""; + PREBINDING = NO; + SDKROOT = macosx10.5; + VALID_ARCHS = "i386 ppc x86_64"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1DEB91AD08733DA50010E9CD /* Build configuration list for PBXNativeTarget "PostgresKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91AE08733DA50010E9CD /* Debug */, + 1DEB91AF08733DA50010E9CD /* Release */, + 17E5952E14F302740054EE08 /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1DEB91B108733DA50010E9CD /* Build configuration list for PBXProject "PostgresKit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1DEB91B208733DA50010E9CD /* Debug */, + 1DEB91B308733DA50010E9CD /* Release */, + 17E5952D14F302740054EE08 /* Distribution */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 0867D690FE84028FC02AAC07 /* Project object */; +} diff --git a/Frameworks/PostgresKit/README b/Frameworks/PostgresKit/README new file mode 100644 index 00000000..65842d8f --- /dev/null +++ b/Frameworks/PostgresKit/README @@ -0,0 +1,65 @@ +POSTGRESKIT README +------------------ + +PostgresKit is a fork and heavily modified version of the PostgresClientKit +code from the PostgresKit project: + + http://code.google.com/p/postgres-kit/ + +PostgresClientKit was originally written by David Thorpe and is licensed under +version 2 of the Apache License. + +This PostgresKit fork was created by Stuart Connolly on July 22, 2012 and +is to be developed as part of the Sequel Pro project: + + http://sequelpro.com/ + +Any new code added during it's development is licensed under the MIT license +and is copyrighted by the respective developer and the Sequel Pro team. + +The entire framework is dual licensed under both version 2 of the Apache +license and the MIT license. Use of it must carry both of the following +licenses to indicate this: + + +APACHE 2 LICENSE + +Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + +MIT LICENSE + +Copyright (c) 2012 Sequel Pro Team. All rights reserved. + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/Frameworks/PostgresKit/Resources/Info.plist b/Frameworks/PostgresKit/Resources/Info.plist new file mode 100644 index 00000000..63ade530 --- /dev/null +++ b/Frameworks/PostgresKit/Resources/Info.plist @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>PostgresKit</string> + <key>CFBundleIdentifier</key> + <string>com.google.code.sequel-pro.postgreskit</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>1.0</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1</string> +</dict> +</plist> diff --git a/Frameworks/PostgresKit/Scripts/build-libpq.sh b/Frameworks/PostgresKit/Scripts/build-libpq.sh new file mode 100755 index 00000000..a4f07f18 --- /dev/null +++ b/Frameworks/PostgresKit/Scripts/build-libpq.sh @@ -0,0 +1,245 @@ +#! /bin/ksh + +# +# $Id$ +# +# build- +# sequel-pro +# +# Created by Stuart Connolly (stuconnolly.com) on August 1, 2012. +# Copyright (c) 2012 Stuart Connolly. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this software and associated documentation +# files (the "Software"), to deal in the Software without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following +# conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. +# +# More info at <http://code.google.com/p/sequel-pro/> + +# Builds the PostgreSQL client library for distrubution in Sequel Pro's PostgresKit framework. +# +# Parameters: -s -- The path to the PostgreSQL source directory. +# -q -- Quiet. Don't output any compiler messages. +# -c -- Clean the source instead of building it. +# -o -- Output path. Defaults to the PostgreSQL source directory. + +QUIET='NO' +CLEAN='NO' + +MIN_OS_X_VERSION='10.5' + +# C/C++ compiler flags +export CFLAGS="-isysroot /Developer3/SDKs/MacOSX${MIN_OS_X_VERSION}.sdk -arch ppc -arch i386 -arch x86_64 -O3 -fno-omit-frame-pointer -fno-exceptions -mmacosx-version-min=${MIN_OS_X_VERSION}" +export CXXFLAGS="-isysroot /Developer3/SDKs/MacOSX${MIN_OS_X_VERSION}.sdk -arch ppc -arch i386 -arch x86_64 -O3 -fno-omit-frame-pointer -felide-constructors -fno-exceptions -fno-rtti -mmacosx-version-min=${MIN_OS_X_VERSION}" + +ESC=$(printf '\033') +CONFIGURE_OPTIONS='--enable-thread-safety --with-openssl' + +set -A INCLUDE_HEADERS 'src/interfaces/libpq/libpq-fe.h' 'src/include/postgres_ext.h' + +usage() +{ + cat <<!EOF +Usage: $(basename $0): -s <postgresql_source_path> [-q -c -d -o <output_path>] + +Where: -s -- Path to the PostgreSQL source directory. + -q -- Be quiet during the build. Suppress all compiler messages. + -c -- Clean the source directory instead of building. + -o -- Output path. Defaults to the PostgreSQL source directory. +!EOF +} + +if [ $# -eq 0 ] +then + echo "$ESC[1;31mInvalid number of arguments. I need the path to the PostgreSQL source directory.$ESC[0m" + echo '' + usage + exit 1 +fi + + +while getopts ':s:o:qcd' OPTION +do + case "$OPTION" in + s) POSTGRESQL_SOURCE_DIR="$OPTARG";; + o) OUTPUT_PATH="$OPTARG";; + q) QUIET='YES';; + c) CLEAN='YES';; + *) echo "$ESC[1;31mUnrecognised option$ESC[0m"; usage; exit 1;; + esac +done + +if [ ! -d "$POSTGRESQL_SOURCE_DIR" ] +then + echo "$ESC[1;31mPostgreSQL source directory does not exist at path '${POSTGRESQL_SOURCE_DIR}'.$ESC[0m" + echo "$ESC[1;31mExiting...$ESC[0m" + exit 1 +fi + +if [ "x${OUTPUT_PATH}" != 'x' ] +then + if [ ! -d "$OUTPUT_PATH" ] + then + echo "$ESC[1;31mOutput path does not exist at '${OUTPUT_PATH}'.$ESC[0m" + echo "$ESC[1;31mExiting...$ESC[0m" + exit 1 + fi +else + OUTPUT_PATH="$POSTGRESQL_SOURCE_DIR" +fi + +OUTPUT_PATH="${OUTPUT_PATH}/SPPostgreSQLFiles.build" + +cd "$POSTGRESQL_SOURCE_DIR" + +# Perform a clean if requested +if [ "x${CLEAN}" == 'xYES' ] +then + echo "$ESC[1mCleaning PostgreSQL source and builds...$ESC[0m" + + if [ "x${QUIET}" == 'xYES' ] + then + make clean > /dev/null + + if [ -d "$OUTPUT_PATH" ]; then rm -rf "$OUTPUT_PATH" > /dev/null; fi + else + make clean + + if [ -d "$OUTPUT_PATH" ]; then rm -rf "$OUTPUT_PATH" > /dev/null; fi + fi + + echo "$ESC[1mCleaning PostgreSQL completed.$ESC[0m" + + exit 0 +fi + +echo '' +echo "This script builds the PostgreSQL client library for distribution in Sequel Pro's PostgreSQL framework." +echo 'They are all built as 3-way binaries (32 bit PPC, 32/64 bit i386).' +echo '' +echo -n "$ESC[1mThis may take a while, are you sure you want to continue [y | n]: $ESC[0m" + +read CONTINUE + +if [ "x${CONTINUE}" == 'xn' ] +then + echo "$ESC[31mAborting...$ESC[0m" + exit 0 +fi + +echo "$ESC[1mConfiguring PostgreSQL source...$ESC[0m" + +if [ "x${QUIET}" == 'xYES' ] +then + ./configure $CONFIGURE_OPTIONS > /dev/null +else + ./configure $CONFIGURE_OPTIONS +fi + +if [ $? -eq 0 ] +then + echo "$ESC[1mConfigure successfully completed$ESC[0m" +else + echo "$ESC[1;31mConfigure failed. Exiting...$ESC[0m" + exit 1 +fi + +echo "$ESC[1mBuilding client library...$ESC[0m" + +cd "${POSTGRESQL_SOURCE_DIR}/src/interfaces/libpq" + +if [ "x${QUIET}" == 'xYES' ] +then + make > /dev/null +else + make +fi + +cd "${POSTGRESQL_SOURCE_DIR}" + +if [ $? -eq 0 ] +then + echo "$ESC[1mBuilding library successfully completed$ESC[0m" +else + echo "$ESC[1;31mBuilding library failed. Exiting...$ESC[0m" + exit 1 +fi + +echo "$ESC[1mPutting together files for distribution...$ESC[0m" + +# Create the appropriate directories +if [ ! -d "$OUTPUT_PATH" ] +then + mkdir "$OUTPUT_PATH" + + if [ ! $? -eq 0 ] + then + echo "$ESC[1;31mCould not create output directory at path '${OUTPUT_PATH}'.$ESC[0m" + exit 1 + fi +fi + +if [ ! -d "${OUTPUT_PATH}/lib" ] +then + mkdir "${OUTPUT_PATH}/lib" + + if [ ! $? -eq 0 ] + then + echo "$ESC[1;31mCould not create lib output directory at path '${OUTPUT_PATH}/lib'.$ESC[0m" + exit 1 + fi +fi + +if [ ! -d "${OUTPUT_PATH}/include" ] +then + mkdir "${OUTPUT_PATH}/include" + + if [ ! $? -eq 0 ] + then + echo "$ESC[1;31mCould not create include output directory at path '${OUTPUT_PATH}/include'.$ESC[0m" + exit 1 + fi +fi + +# Copy the library +cp 'src/interfaces/libpq/libpq.a' "${OUTPUT_PATH}/lib" + +if [ ! $? -eq 0 ] +then + echo "$ESC[1;31mCould not copy libpq.a to output directory (${OUTPUT_PATH}/lib).$ESC[0m" + exit 1 +fi + +# Copy in the required headers +for HEADER in ${INCLUDE_HEADERS[@]} +do + cp "$HEADER" "${OUTPUT_PATH}/include/" + + if [ ! $? -eq 0 ] + then + echo "$ESC[1;31mCould not copy '${HEADER}' to output directory (${OUTPUT_PATH}/include).$ESC[0m" + exit 1 + fi +done + + +echo "$ESC[1mBuilding PostgreSQL client library successfully completed.$ESC[0m" +echo "$ESC[1mSee ${OUTPUT_PATH} for the product.$ESC[0m" + +exit 0 diff --git a/Frameworks/PostgresKit/Source/FLXConstants.h b/Frameworks/PostgresKit/Source/FLXConstants.h new file mode 100644 index 00000000..95ab17f6 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXConstants.h @@ -0,0 +1,41 @@ +// +// $Id$ +// +// FLXConstants.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +// Result set row types +typedef enum +{ + FLXPostgresResultRowAsArray = 1, + FLXPostgresResultRowAsDictionary = 2 +} +FLXPostgresResultRowType; + +// Defaults +extern NSString *FLXPostgresConnectionDefaultEncoding; +extern NSString *FLXPostgresConnectionErrorDomain; +extern NSStringEncoding FLXPostgresConnectionDefaultStringEncoding; + +// Server parameters +extern NSString *FLXPostgresParameterServerEncoding; +extern NSString *FLXPostgresParameterClientEncoding; +extern NSString *FLXPostgresParameterSuperUser; +extern NSString *FLXPostgresParameterTimeZone; +extern NSString *FLXPostgresParameterIntegerDateTimes; diff --git a/Frameworks/PostgresKit/Source/FLXConstants.m b/Frameworks/PostgresKit/Source/FLXConstants.m new file mode 100644 index 00000000..3dc68ff9 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXConstants.m @@ -0,0 +1,31 @@ +// +// $Id$ +// +// FLXConstants.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +NSString *FLXPostgresConnectionDefaultEncoding = @"UNICODE"; +NSString *FLXPostgresConnectionErrorDomain = @"FLXPostgresConnectionError"; +NSStringEncoding FLXPostgresConnectionDefaultStringEncoding = NSUTF8StringEncoding; + +NSString *FLXPostgresParameterServerEncoding = @"server_encoding"; +NSString *FLXPostgresParameterClientEncoding = @"client_encoding"; +NSString *FLXPostgresParameterSuperUser = @"is_superuser"; +NSString *FLXPostgresParameterTimeZone = @"TimeZone"; +NSString *FLXPostgresParameterIntegerDateTimes = @"integer_datetimes"; diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnection.h b/Frameworks/PostgresKit/Source/FLXPostgresConnection.h new file mode 100644 index 00000000..20260818 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnection.h @@ -0,0 +1,97 @@ +// +// $Id$ +// +// FLXPostgresConnection.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresTypeHandlerProtocol.h" +#import "FLXPostgresConnectionDelegate.h" + +@class FLXPostgresResult; +@class FLXPostgresStatement; +@class FLXPostgresConnectionParameters; + +@interface FLXPostgresConnection : NSObject +{ + PGconn *_connection; + + NSString *_host; + NSString *_user; + NSString *_database; + NSString *_password; + NSString *_socketPath; + NSString *_lastErrorMessage; + NSString *_encoding; + + const char **_connectionParamNames; + const char **_connectionParamValues; + + NSStringEncoding _stringEncoding; + + NSUInteger _port; + NSUInteger _timeout; + NSUInteger _keepAliveInterval; + + BOOL _useSocket; + BOOL _useKeepAlive; + BOOL _lastQueryWasCancelled; + BOOL _delegateSupportsWillExecute; + + NSMutableDictionary *_typeMap; + + FLXPostgresConnectionParameters *_parameters; + + NSObject <FLXPostgresConnectionDelegate> *_delegate; +} + +@property (readwrite, assign) NSObject <FLXPostgresConnectionDelegate> *delegate; + +@property (readwrite, retain) NSString *host; +@property (readwrite, retain) NSString *user; +@property (readwrite, retain) NSString *database; +@property (readwrite, retain) NSString *password; +@property (readwrite, retain) NSString *socketPath; + +@property (readonly) NSString *encoding; +@property (readonly) NSString *lastErrorMessage; +@property (readonly) NSStringEncoding stringEncoding; +@property (readonly) FLXPostgresConnectionParameters *parameters; + +@property (readwrite, assign) BOOL useSocket; +@property (readwrite, assign) BOOL useKeepAlive; +@property (readwrite, assign) BOOL lastQueryWasCancelled; + +@property (readwrite, assign) NSUInteger timeout; +@property (readwrite, assign) NSUInteger port; +@property (readwrite, assign) NSUInteger keepAliveInterval; + +- (id)initWithDelegate:(NSObject <FLXPostgresConnectionDelegate> *)delegate; + +- (BOOL)connect; +- (void)disconnect; +- (BOOL)isConnected; +- (BOOL)reset; + +- (NSUInteger)clientVersion; +- (NSUInteger)serverVersion; +- (NSUInteger)serverProcessId; + +- (BOOL)cancelCurrentQuery:(NSError **)error; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnection.m b/Frameworks/PostgresKit/Source/FLXPostgresConnection.m new file mode 100644 index 00000000..3bd24bb2 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnection.m @@ -0,0 +1,460 @@ +// +// $Id$ +// +// FLXPostgresConnection.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnection.h" +#import "FLXPostgresConnectionParameters.h" +#import "FLXPostgresConnectionTypeHandling.h" +#import "FLXPostgresConnectionPrivateAPI.h" +#import "FLXPostgresTypeNumberHandler.h" +#import "FLXPostgresTypeStringHandler.h" +#import "FLXPostgresException.h" +#import "FLXPostgresStatement.h" +#import "FLXPostgresResult.h" + +#import "pthread.h" + +// Connection default constants +static NSUInteger FLXPostgresConnectionDefaultTimeout = 30; +static NSUInteger FLXPostgresConnectionDefaultServerPort = 5432; +static NSUInteger FLXPostgresConnectionDefaultKeepAlive = 60; + +// libpq connection parameters +static const char *FLXPostgresApplicationName = "PostgresKit"; +static const char *FLXPostgresApplicationParam = "application_name"; +static const char *FLXPostgresUserParam = "user"; +static const char *FLXPostgresHostParam = "host"; +static const char *FLXPostgresPasswordParam = "password"; +static const char *FLXPostgresPortParam = "port"; +static const char *FLXPostgresDatabaseParam = "dbname"; +static const char *FLXPostgresConnectionTimeoutParam = "conect_timeout"; +static const char *FLXPostgresClientEncodingParam = "client_encoding"; +static const char *FLXPostgresKeepAliveParam = "keepalives"; +static const char *FLXPostgresKeepAliveIntervalParam = "keepalives_interval"; + +@interface FLXPostgresConnection () + +- (void)_pollConnection; +- (void)_loadDatabaseParameters; +- (void)_createConnectionParameters; + +// libpq callback +static void _FLXPostgresConnectionNoticeProcessor(void *arg, const char *message); + +@end + +@implementation FLXPostgresConnection + +@synthesize port = _port; +@synthesize host = _host; +@synthesize user = _user; +@synthesize database = _database; +@synthesize password = _password; +@synthesize useSocket = _useSocket; +@synthesize socketPath = _socketPath; +@synthesize delegate = _delegate; +@synthesize timeout = _timeout; +@synthesize useKeepAlive = _useKeepAlive; +@synthesize keepAliveInterval = _keepAliveInterval; +@synthesize lastQueryWasCancelled = _lastQueryWasCancelled; +@synthesize lastErrorMessage = _lastErrorMessage; +@synthesize encoding = _encoding; +@synthesize stringEncoding = _stringEncoding; +@synthesize parameters = _parameters; + +#pragma mark - +#pragma mark Initialisation + +- (id)init +{ + return [self initWithDelegate:nil]; +} + +/** + * Initialise a new connection with the supplied delegate. + * + * @param delegate The delegate this connection should use. + * + * @return The new connection instance. + */ +- (id)initWithDelegate:(NSObject <FLXPostgresConnectionDelegate> *)delegate +{ + if ((self = [super init])) { + + _delegate = delegate; + + _port = FLXPostgresConnectionDefaultServerPort; + _timeout = FLXPostgresConnectionDefaultTimeout; + + _useKeepAlive = YES; + _keepAliveInterval = FLXPostgresConnectionDefaultKeepAlive; + + _connection = nil; + _lastErrorMessage = nil; + _lastQueryWasCancelled = NO; + + _stringEncoding = FLXPostgresConnectionDefaultStringEncoding; + _encoding = [NSString stringWithString:FLXPostgresConnectionDefaultEncoding]; + + _delegateSupportsWillExecute = [_delegate respondsToSelector:@selector(connection:willExecute:values:)]; + + _typeMap = [[NSMutableDictionary alloc] init]; + + [self registerTypeHandlers]; + } + + return self; +} + +#pragma mark - +#pragma mark Accessors + +- (PGconn *)postgresConnection +{ + return _connection; +} + +#pragma mark - +#pragma mark Connection Handling + +/** + * Does this connection have an underlying connection established with the server. + * + * @return A BOOL indicating the result of the query. + */ +- (BOOL)isConnected +{ + if (!_connection) return NO; + + return PQstatus(_connection) == CONNECTION_OK; +} + +/** + * Attempts to disconnect the underlying connection with the server. + */ +- (void)disconnect +{ + if (!_connection) return; + + [self cancelCurrentQuery:nil]; + + PQfinish(_connection); + + _connection = nil; + + if (_delegate && [_delegate respondsToSelector:@selector(connectionDisconnected:)]) { + [_delegate connectionDisconnected:self]; + } +} + +/** + * Initiates the underlying connection to the server asynchronously. + * + * Note, that if no user, host or database is set when connect is called, then libpq's defaults are used. + * For no host, this means a socket connection to /tmp is attempted. + * + * @return A BOOL indicating the success of requesting the connection. Note, that this does not indicate + * that a successful connection has been made, only that it has successfullly been requested. + */ +- (BOOL)connect +{ + if ([self isConnected]) { + [FLXPostgresException raise:FLXPostgresConnectionErrorDomain reason:@"Attempt to initiate a connection that is already active"]; + + return NO; + } + + [self _createConnectionParameters]; + + // Perform the connection + _connection = PQconnectStartParams(_connectionParamNames, _connectionParamValues, 0); + + if (!_connection || PQstatus(_connection) == CONNECTION_BAD) { + + // TODO: implement reconnection attempt + return NO; + } + + [self performSelectorInBackground:@selector(_pollConnection) withObject:nil]; + + return YES; +} + +/** + * Attempts the reset the underlying connection. + * + * @note A return value of NO means that the connection is not currently + * connected to be reset and YES means the reset request was successful, + * not that the connection re-establishment has succeeded. Use -isConnected + * to check this. + * + * @return A BOOL indicating the success of the call. + */ +- (BOOL)reset +{ + if (![self isConnected]) return NO; + + PQreset(_connection); + + return YES; +} + +/** + * Returns the PostgreSQL client library (libpq) version being used. + * + * @return The library version (e.g. version 9.1 is 90100). + */ +- (NSUInteger)clientVersion +{ + return PQlibVersion(); +} + +/** + * Returns the version of the server we're connected to. + * + * @return The server version (e.g. version 9.1 is 90100). Zero is returned if there's no connection. + */ +- (NSUInteger)serverVersion +{ + if (![self isConnected]) return 0; + + return PQserverVersion(_connection); +} + +/** + * Returns the ID of the process handling this connection on the remote host. + * + * @return The process ID or -1 if no connection is available. + */ +- (NSUInteger)serverProcessId +{ + if (![self isConnected]) return -1; + + return PQbackendPID(_connection); +} + +/** + * Attempts to cancel the query currently executing on this connection. + * + * @param error Populated if query was unabled to be cancelled. + * + * @return A BOOL indicating the success of the request + */ +- (BOOL)cancelCurrentQuery:(NSError **)error +{ + if (![self isConnected]) return NO; + + PGcancel *cancel = PQgetCancel(_connection); + + if (!cancel) return NO; + + char errorBuf[256]; + + int result = PQcancel(cancel, errorBuf, 256); + + PQfreeCancel(cancel); + + if (!result) { + if (error != NULL) { + *error = [NSError errorWithDomain:FLXPostgresConnectionErrorDomain + code:0 + userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithUTF8String:errorBuf] forKey:NSLocalizedDescriptionKey]]; + } + + return NO; + } + + _lastQueryWasCancelled = YES; + + return YES; +} + +#pragma mark - +#pragma mark Private API + +/** + * Polls the connection that was previously requested via -connect and waits for meaninful status. + * + * @note This method should be called on a background thread as it will block waiting for the connection. + */ +- (void)_pollConnection +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + BOOL failed = NO; + BOOL connected = NO; + + while (!connected && !failed) + { + switch (PQconnectPoll(_connection)) + { + case PGRES_POLLING_READING: + case PGRES_POLLING_WRITING: + case PGRES_POLLING_ACTIVE: // Obsolete so we don't really care about it + break; + case PGRES_POLLING_OK: + connected = YES; + break; + case PGRES_POLLING_FAILED: + failed = YES; + break; + } + } + + if (connected) { + PQsetNoticeProcessor(_connection, _FLXPostgresConnectionNoticeProcessor, self); + + [self _loadDatabaseParameters]; + + if (_delegate && [_delegate respondsToSelector:@selector(connectionEstablished:)]) { + [_delegate performSelectorOnMainThread:@selector(connectionEstablished:) withObject:self waitUntilDone:NO]; + } + } + + [pool release]; +} + +/** + * Loads the database parameters. + */ +- (void)_loadDatabaseParameters +{ + if (_parameters) [_parameters release]; + + _parameters = [[FLXPostgresConnectionParameters alloc] initWithConnection:self]; + + BOOL success = [_parameters loadParameters]; + + if (!success) { + NSLog(@"PostgresKit: Warning: Failed to load database parameters."); + } +} + +/** + * libpq notice processor function. Simply passes the message onto the connection delegate. + * + * @param arg The calling connection. + * @param message The message that was sent. + */ +static void _FLXPostgresConnectionNoticeProcessor(void *arg, const char *message) +{ + FLXPostgresConnection *connection = (FLXPostgresConnection *)arg; + + if ([connection isKindOfClass:[FLXPostgresConnection class]]) { + + if ([connection delegate] && [[connection delegate] respondsToSelector:@selector(connection:notice:)]) { + [[connection delegate] connection:connection notice:[NSString stringWithUTF8String:message]]; + } + } +} + +/** + * Creates the parameter arrays required to establish a connection. + */ +- (void)_createConnectionParameters +{ + BOOL hasUser = NO; + BOOL hasHost = NO; + BOOL hasPassword = NO; + BOOL hasDatabase = NO; + + if (_connectionParamNames) free(_connectionParamNames); + if (_connectionParamValues) free(_connectionParamValues); + + int paramCount = 6; + + if (_user && [_user length]) paramCount++, hasUser = YES; + if (_host && [_host length]) paramCount++, hasHost = YES; + if (_password && [_password length]) paramCount++, hasPassword = YES; + if (_database && [_database length]) paramCount++, hasDatabase = YES; + + _connectionParamNames = malloc(paramCount * sizeof(*_connectionParamNames)); + _connectionParamValues = malloc(paramCount * sizeof(*_connectionParamValues)); + + _connectionParamNames[0] = FLXPostgresApplicationParam; + _connectionParamValues[0] = FLXPostgresApplicationName; + + _connectionParamNames[1] = FLXPostgresPortParam; + _connectionParamValues[1] = [[[NSNumber numberWithUnsignedInteger:_port] stringValue] UTF8String]; + + _connectionParamNames[2] = FLXPostgresConnectionTimeoutParam; + _connectionParamValues[2] = [[[NSNumber numberWithUnsignedInteger:_timeout] stringValue] UTF8String]; + + _connectionParamNames[3] = FLXPostgresClientEncodingParam; + _connectionParamValues[3] = [_encoding UTF8String]; + + _connectionParamNames[4] = FLXPostgresKeepAliveParam; + _connectionParamValues[4] = _useKeepAlive ? "1" : "0"; + + _connectionParamNames[5] = FLXPostgresKeepAliveIntervalParam; + _connectionParamValues[5] = [[[NSNumber numberWithUnsignedInteger:_keepAliveInterval] stringValue] UTF8String]; + + NSUInteger i = 6; + + if (hasUser) { + _connectionParamNames[i] = FLXPostgresUserParam; + _connectionParamValues[i] = [_user UTF8String]; + + i++; + } + + if (hasHost) { + _connectionParamNames[i] = FLXPostgresHostParam; + _connectionParamValues[i] = [_host UTF8String]; + + i++; + } + + if (hasPassword) { + _connectionParamNames[i] = FLXPostgresPasswordParam; + _connectionParamValues[i] = [_password UTF8String]; + + i++; + } + + if (hasDatabase) { + _connectionParamNames[i] = FLXPostgresDatabaseParam; + _connectionParamValues[i] = [_database UTF8String]; + } +} + +#pragma mark - + +- (void)dealloc +{ + [_typeMap release]; + + [self disconnect]; + + [self setHost:nil]; + [self setUser:nil]; + [self setDatabase:nil]; + + if (_connectionParamNames) free(_connectionParamNames); + if (_connectionParamValues) free(_connectionParamValues); + + if (_parameters) [_parameters release], _parameters = nil; + if (_lastErrorMessage) [_lastErrorMessage release], _lastErrorMessage = nil; + + [super dealloc]; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionDelegate.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionDelegate.h new file mode 100644 index 00000000..9626d8e1 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionDelegate.h @@ -0,0 +1,58 @@ +// +// $Id$ +// +// FLXPostgresConnectionDelegate.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +@class FLXPostgresConnection; + +@protocol FLXPostgresConnectionDelegate <NSObject> + +/** + * Called whenever a connection is successfully established. + * + * @param connection The connection instance. + */ +- (void)connectionEstablished:(FLXPostgresConnection *)connection; + +/** + * Called whenever a connection is disconnected. + * + * @param connection The connection instance. + */ +- (void)connectionDisconnected:(FLXPostgresConnection *)connection; + +/** + * Called whenever a message is received from the PostgreSQL server. + * + * @param connection The connection instance. + * @param notice The notice message received. + */ +- (void)connection:(FLXPostgresConnection *)connection notice:(NSString *)notice; + +/** + * Called just before a query is about to be executed. + * + * @param connection The connection executing the query. + * @param query The query about the be executed. + * @param values The values of the query. + */ +- (void)connection:(FLXPostgresConnection *)connection willExecute:(NSObject *)query values:(NSArray *)values; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionEncoding.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionEncoding.h new file mode 100644 index 00000000..c6686465 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionEncoding.h @@ -0,0 +1,39 @@ +// $Id$ +// +// FLXPostgresConnectionEncoding.h +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on August 4, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import "FLXPostgresConnection.h" + +@interface FLXPostgresConnection (FLXPostgresConnectionEncoding) + +- (BOOL)setEncoding:(NSString *)encoding; + ++ (NSStringEncoding)stringEncodingForPostgreSQLCharset:(const char *)charset; ++ (NSString *)postgreSQLCharsetForStringEncoding:(NSStringEncoding)stringEncoding; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionEncoding.m b/Frameworks/PostgresKit/Source/FLXPostgresConnectionEncoding.m new file mode 100644 index 00000000..ddecee64 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionEncoding.m @@ -0,0 +1,197 @@ +// +// $Id$ +// +// FLXPostgresConnectionEncoding.m +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on August 4, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import "FLXPostgresConnectionEncoding.h" +#import "FLXPostgresConnectionPrivateAPI.h" + +@implementation FLXPostgresConnection (FLXPostgresConnectionEncoding) + +/** + * Set the current connection's encoding. + * + * @param encoding The name of the encoding to use. + * + * @return A BOOL indicating the success of the operation. NO means there was either no connection or the + * encoding name wasn't recognised by the server. + */ +- (BOOL)setEncoding:(NSString *)encoding +{ + if (![self isConnected]) return NO; + + if ([_encoding isEqualToString:encoding]) return YES; + + if (PQsetClientEncoding(_connection, [encoding UTF8String]) != 0) return NO; + + [_encoding release], _encoding = [[NSString alloc] initWithString:encoding]; + + _stringEncoding = [FLXPostgresConnection stringEncodingForPostgreSQLCharset:[encoding UTF8String]]; + + return YES; +} + +/** + * Translates the supplied encoding name to it's corresponding string encoding identifier. + * + * @param charset The character set as a char array. + * + * @return The string encoding identifier. + */ ++ (NSStringEncoding)stringEncodingForPostgreSQLCharset:(const char *)charset +{ + if (!strcmp(charset, "UNICODE") || !strcmp(charset, "MULE_INTERNAL")) { + return NSUTF8StringEncoding; + } + else if (!strcmp(charset, "LATIN1")) { + return NSISOLatin1StringEncoding; + } + else if (!strcmp(charset, "LATIN2")) { + return NSISOLatin2StringEncoding; + } + else if (!strcmp(charset, "LATIN3")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin3); + } + else if (!strcmp(charset, "LATIN4")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin4); + } + else if (!strcmp(charset, "LATIN5")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin5); + } + else if (!strcmp(charset, "LATIN6")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin6); + } + else if (!strcmp(charset, "LATIN7")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin7); + } + else if (!strcmp(charset, "LATIN8")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin8); + } + else if (!strcmp(charset, "LATIN9")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin9); + } + else if (!strcmp(charset, "LATIN10")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatin10); + } + else if (!strcmp(charset, "SQL_ASCII")) { + return NSASCIIStringEncoding; + } + else if (!strcmp(charset, "EUC_JP")) { + return NSJapaneseEUCStringEncoding; + } + else if (!strcmp(charset, "EUC_CN")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_CN); + } + else if (!strcmp(charset, "EUC_KR")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_KR); + } + else if (!strcmp(charset, "JOHAB")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingWindowsKoreanJohab); + } + else if (!strcmp(charset, "EUC_TW")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingEUC_TW); + } + else if (!strcmp(charset, "ISO_8859_5")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinCyrillic); + } + else if (!strcmp(charset, "ISO_8859_6")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinArabic); + } + else if (!strcmp(charset, "ISO_8859_7")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinGreek); + } + else if (!strcmp(charset, "ISO_8859_8")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingISOLatinHebrew); + } + else if (!strcmp(charset, "KOI8")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingKOI8_R); + } + else if (!strcmp(charset, "ALT")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingDOSRussian); + } + else if (!strcmp(charset, "WIN")) { + return NSWindowsCP1251StringEncoding; + } + else if (!strcmp(charset, "WIN1256")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingWindowsArabic); + } + else if (!strcmp(charset, "TCVN")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingWindowsVietnamese); + } + else if (!strcmp(charset, "WIN874")) { + return CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingDOSThai); + } + + NSLog(@"PostgresKit: Warning: Unable to process unknown PostgreSQL encoding '%s'; falling back to UTF8.", charset); + + return FLXPostgresConnectionDefaultStringEncoding; +} + +/** + * Translates the supplied encoding identifier to it's corresponding encoding name. + * + * @param stringEncoding The string encoding to translate + * + * @return The encoding name as a string or nil if there's no mapping. + */ ++ (NSString *)postgreSQLCharsetForStringEncoding:(NSStringEncoding)stringEncoding +{ + switch (stringEncoding) + { + case NSASCIIStringEncoding: + return @"SQL_ASCII"; + + case NSJapaneseEUCStringEncoding: + return @"EUC_JP"; + + case NSUTF8StringEncoding: + case NSNonLossyASCIIStringEncoding: + return @"UNICODE"; + + case NSISOLatin1StringEncoding: + case NSWindowsCP1252StringEncoding: + return @"LATIN1"; + + case NSISOLatin2StringEncoding: + case NSWindowsCP1250StringEncoding: + return @"LATIN2"; + + case NSWindowsCP1251StringEncoding: + return @"WIN"; + + case NSWindowsCP1253StringEncoding: + return @"ISO_8859_7"; + + case NSWindowsCP1254StringEncoding: + return @"LATIN5"; + } + + return nil; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionParameters.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionParameters.h new file mode 100644 index 00000000..84864a1a --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionParameters.h @@ -0,0 +1,56 @@ +// +// $Id$ +// +// FLXPostgresConnectionParameters.h +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on August 29, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import <pthread.h> + +@class FLXPostgresConnection; + +@interface FLXPostgresConnectionParameters : NSObject +{ + FLXPostgresConnection *_connection; + + NSMutableArray *_parameterNames; + NSMutableDictionary *_parameters; + + pthread_mutex_t _readLock; +} + +/** + * @property connection The database connection to use. + */ +@property (readwrite, assign) FLXPostgresConnection *connection; + +- (id)initWithConnection:(FLXPostgresConnection *)connection; + +- (BOOL)loadParameters; + +- (id)valueForParameter:(NSString *)parameter; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionParameters.m b/Frameworks/PostgresKit/Source/FLXPostgresConnectionParameters.m new file mode 100644 index 00000000..f1161f89 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionParameters.m @@ -0,0 +1,220 @@ +// +// $Id$ +// +// FLXPostgresConnectionParameters.m +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on August 29, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import "FLXPostgresConnectionParameters.h" +#import "FLXPostgresConnectionPrivateAPI.h" +#import "FLXPostgresConnection.h" + +@interface FLXPostgresConnectionParameters () + +- (void)_loadParameters:(id)object; +- (BOOL)_isBooleanParameterValue:(NSString *)value; +- (BOOL)_booleanForParameterValue:(NSString *)value; + +@end + +@implementation FLXPostgresConnectionParameters + +@synthesize connection = _connection; + +#pragma mark - + +- (id)init +{ + return [self initWithConnection:nil]; +} + +/** + * Initialise a parameters instance with the supplied connection. + * + * @param connection The connection to use. + * + * @return The initialised instance. + */ +- (id)initWithConnection:(FLXPostgresConnection *)connection +{ + if ((self = [super init])) { + _connection = connection; + + pthread_mutex_init(&_readLock, NULL); + } + + return self; +} + +#pragma mark - +#pragma mark Public API + +/** + * Loads the database parameters. + * + * @return A BOOL indicating the success of the load. + */ +- (BOOL)loadParameters +{ + pthread_mutex_lock(&_readLock); + + if (!_connection || ![_connection isConnected]) { + pthread_mutex_unlock(&_readLock); + + return NO; + } + + if (!_parameterNames) { + _parameterNames = [[NSMutableArray alloc] init]; + + [_parameterNames addObject:FLXPostgresParameterServerEncoding]; + [_parameterNames addObject:FLXPostgresParameterClientEncoding]; + [_parameterNames addObject:FLXPostgresParameterSuperUser]; + [_parameterNames addObject:FLXPostgresParameterTimeZone]; + [_parameterNames addObject:FLXPostgresParameterIntegerDateTimes]; + } + + pthread_mutex_unlock(&_readLock); + + [self performSelectorInBackground:@selector(_loadParameters:) withObject:_parameterNames]; + + return YES; +} + +/** + * Gets the object for the supplied parameter. + * + * @param parameter The name of the parameter to lookup. + * + * @return The parameter value or nil if parameters haven't been loaded or it can't be found. + */ +- (id)valueForParameter:(NSString *)parameter +{ + pthread_mutex_lock(&_readLock); + + if (!_parameters || ![_parameters count]) { + pthread_mutex_unlock(&_readLock); + + return nil; + } + + id value = [_parameters objectForKey:parameter]; + + pthread_mutex_unlock(&_readLock); + + return value; +} + +#pragma mark - +#pragma mark Private API + +/** + * Loads the values of the supplied array of parameters by query the current connection. + * + * @param object The parameters to load. + */ +- (void)_loadParameters:(id)object +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + pthread_mutex_lock(&_readLock); + + NSArray *parameters = (NSArray *)object; + + if (!_parameters) { + _parameters = [[NSMutableDictionary alloc] initWithCapacity:[parameters count]]; + } + + for (NSString *parameter in parameters) + { + const char *value = PQparameterStatus([_connection postgresConnection], [parameter UTF8String]); + + if (!value) continue; + + NSString *stringValue = [NSString stringWithUTF8String:value]; + + id paramObject = [self _isBooleanParameterValue:stringValue] ? [NSNumber numberWithBool:[self _booleanForParameterValue:stringValue]] : stringValue; + + [_parameters setObject:paramObject forKey:parameter]; + } + + pthread_mutex_unlock(&_readLock); + + [pool release]; +} + +/** + * Determines whether or not the supplied value is a boolean value. + * + * @param value The value to look at. + * + * @return A BOOL indicating if the value is a boolean type. + */ +- (BOOL)_isBooleanParameterValue:(NSString *)value +{ + value = [value uppercaseString]; + + return + [value isEqualToString:@"ON"] || + [value isEqualToString:@"YES"] || + [value isEqualToString:@"TRUE"] || + [value isEqualToString:@"OFF"] || + [value isEqualToString:@"NO"] || + [value isEqualToString:@"FALSE"]; +} + +/** + * Determines the boolean value for the supplied boolean string representation. + * + * @param value The value to look at. + * + * @return A BOOL indicating the value of the string representation. + */ +- (BOOL)_booleanForParameterValue:(NSString *)value +{ + value = [value uppercaseString]; + + return + [value isEqualToString:@"ON"] || + [value isEqualToString:@"YES"] || + [value isEqualToString:@"TRUE"]; +} + +#pragma mark - + +- (void)dealloc +{ + _connection = nil; + + pthread_mutex_destroy(&_readLock); + + if (_parameters) [_parameters release], _parameters = nil; + if (_parameterNames) [_parameterNames release], _parameterNames = nil; + + [super dealloc]; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionPrivateAPI.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionPrivateAPI.h new file mode 100644 index 00000000..53bcf4ee --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionPrivateAPI.h @@ -0,0 +1,38 @@ +// +// $Id$ +// +// FLXPostgresConnectionPrivateAPI.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnection.h" + +@interface FLXPostgresConnection (FLXPostgresConnectionPrivateAPI) + +- (PGconn *)postgresConnection; +- (void)_createConnectionParameters; + +@end + +@interface FLXPostgresConnection (FLXPostgresConnectionQueryPreparationPrivateAPI) + +- (BOOL)_prepare:(FLXPostgresStatement *)statement num:(int)paramNum types:(FLXPostgresOid *)paramTypes; + +@end + + diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionPrivateAPI.m b/Frameworks/PostgresKit/Source/FLXPostgresConnectionPrivateAPI.m new file mode 100644 index 00000000..52610305 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionPrivateAPI.m @@ -0,0 +1,29 @@ +// +// FLXPostgresConnectionPrivateAPI.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnectionPrivateAPI.h" +#import "FLXPostgresConnectionDelegateProtocol.h" +#import "FLXPostgresResult.h" + +@implementation FLXPostgresConnection (FLXPostgresConnectionPrivateAPI) + + + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryExecution.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryExecution.h new file mode 100644 index 00000000..b1c8aed0 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryExecution.h @@ -0,0 +1,38 @@ +// +// $Id$ +// +// FLXPostgresConnectionQueryExecution.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnection.h" + +@interface FLXPostgresConnection (FLXPostgresConnectionQueryExecution) + +// Synchronous interface +- (FLXPostgresResult *)execute:(NSString *)query; +- (FLXPostgresResult *)executeWithFormat:(NSString *)query, ...; +- (FLXPostgresResult *)executePrepared:(FLXPostgresStatement *)statement; +- (FLXPostgresResult *)execute:(NSString *)query values:(NSArray *)values; +- (FLXPostgresResult *)execute:(NSString *)query value:(NSObject *)value; +- (FLXPostgresResult *)executePrepared:(FLXPostgresStatement *)statement values:(NSArray *)values; +- (FLXPostgresResult *)executePrepared:(FLXPostgresStatement *)statement value:(NSObject *)value; + +// Asynchronous interface + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryExecution.m b/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryExecution.m new file mode 100644 index 00000000..894338a7 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryExecution.m @@ -0,0 +1,322 @@ +// +// $Id$ +// +// FLXPostgresConnectionQueryExecution.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnectionQueryExecution.h" +#import "FLXPostgresConnectionPrivateAPI.h" +#import "FLXPostgresConnectionTypeHandling.h" +#import "FLXPostgresConnectionDelegate.h" +#import "FLXPostgresConnection.h" +#import "FLXPostgresException.h" +#import "FLXPostgresResult.h" +#import "FLXPostgresTypeHandlerProtocol.h" +#import "FLXPostgresStatement.h" + +// Constants +static int FLXPostgresResultsAsBinary = 1; + +// Internal query structure +typedef struct +{ + int paramNum; + const void **paramValues; + FLXPostgresOid* paramTypes; + int *paramLengths; + int *paramFormats; +} +FLXQueryParamData; + +@interface FLXPostgresConnection () + +- (FLXPostgresResult *)_execute:(NSObject *)query values:(NSArray *)values; +- (BOOL)_queryDidError:(PGresult *)result; +- (FLXQueryParamData *)_createParameterDataStructureWithCount:(int)paramNum; +- (void)_destroyParamDataStructure:(FLXQueryParamData *)paramData; + +@end + +@implementation FLXPostgresConnection (FLXPostgresConnectionQueryExecution) + +#pragma mark - +#pragma mark Synchronous Interface + +- (FLXPostgresResult *)execute:(NSString *)query +{ + return [self _execute:query values:nil]; +} + +- (FLXPostgresResult *)execute:(NSString *)query value:(NSObject *)value +{ + return [self _execute:query values:[NSArray arrayWithObject:value]]; +} + +- (FLXPostgresResult *)executePrepared:(FLXPostgresStatement *)statement value:(NSObject *)value +{ + return [self _execute:statement values:[NSArray arrayWithObject:value]]; +} + +- (FLXPostgresResult *)executePrepared:(FLXPostgresStatement *)statement +{ + return [self _execute:statement values:nil]; +} + +- (FLXPostgresResult *)executePrepared:(FLXPostgresStatement *)statement values:(NSArray *)values +{ + return [self _execute:statement values:values]; +} + +- (FLXPostgresResult *)execute:(NSString *)query values:(NSArray *)values +{ + return [self _execute:query values:values]; +} + +- (FLXPostgresResult *)executeWithFormat:(NSString *)query, ... +{ + va_list argumentList; + va_start(argumentList, query); + + NSMutableString *string = [[NSMutableString alloc] init]; + + CFStringAppendFormatAndArguments((CFMutableStringRef)string, (CFDictionaryRef)nil, (CFStringRef)query, argumentList); + + va_end(argumentList); + + FLXPostgresResult *result = [self _execute:string values:nil]; + + [string release]; + + return result; +} + +#pragma mark - +#pragma mark Asynchronous Interface + +#pragma mark - +#pragma mark Private API + +- (FLXPostgresResult *)_execute:(NSObject *)query values:(NSArray *)values +{ + _lastQueryWasCancelled = NO; + + if (![self isConnected] || !query || ![query isKindOfClass:[NSString class]] || [query isKindOfClass:[FLXPostgresStatement class]]) return nil; + + // Notify the delegate + if (_delegate && _delegateSupportsWillExecute) { + [_delegate connection:self willExecute:query values:values]; + } + + FLXQueryParamData *paramData = [self _createParameterDataStructureWithCount:values ? (int)[values count] : 0]; + + if (!paramData) return nil; + + // Fill the data structures + for (int i = 0; i < paramData->paramNum; i++) + { + id nativeObject = [values objectAtIndex:i]; + + NSParameterAssert(nativeObject); + + // Deterime if bound value is an NSNull + if ([nativeObject isKindOfClass:[NSNull class]]) { + paramData->paramValues[i] = NULL; + paramData->paramTypes[i] = 0; + paramData->paramLengths[i] = 0; + paramData->paramFormats[i] = 0; + + continue; + } + + // Obtain correct handler for this class + id <FLXPostgresTypeHandlerProtocol> typeHandler = [self typeHandlerForClass:[nativeObject class]]; + + if (!typeHandler) { + [self _destroyParamDataStructure:paramData]; + + // TODO: get rid of exceptions + [FLXPostgresException raise:FLXPostgresConnectionErrorDomain reason:[NSString stringWithFormat:@"Parameter $%u unsupported class %@", (i + 1), NSStringFromClass([nativeObject class])]]; + return nil; + } + + FLXPostgresOid type = 0; + NSData *data = [typeHandler remoteDataFromObject:nativeObject type:&type]; + + if (!data) { + [self _destroyParamDataStructure:paramData]; + + // TODO: get rid of exceptions + [FLXPostgresException raise:FLXPostgresConnectionErrorDomain reason:[NSString stringWithFormat:@"Parameter $%u cannot be converted into a bound value", (i + 1)]]; + return nil; + } + + // Check length of data + if ([data length] > INT_MAX) { + [self _destroyParamDataStructure:paramData]; + + // TODO: get rid of exceptions + [FLXPostgresException raise:FLXPostgresConnectionErrorDomain reason:[NSString stringWithFormat:@"Bound value $%u exceeds maximum size", (i + 1)]]; + return nil; + } + + // Assign data + paramData->paramTypes[i] = type; + + // NOTE: if data length is zero, we encode as text instead, as NSData returns 0 for + // empty data, and it gets encoded as a NULL. + if ([data length] == 0) { + paramData->paramValues[i] = ""; + paramData->paramFormats[i] = 0; + paramData->paramLengths[i] = 0; + } + else { + // Send as binary data + paramData->paramValues[i] = [data bytes]; + paramData->paramLengths[i] = (int)[data length]; + paramData->paramFormats[i] = 1; + } + } + + // Execute the command - return data in binary + PGresult *result = nil; + + if ([query isKindOfClass:[NSString class]]) { + + result = PQexecParams(_connection, + [(NSString *)query UTF8String], + paramData->paramNum, + paramData->paramTypes, + (const char **)paramData->paramValues, + (const int *)paramData->paramLengths, + (const int *)paramData->paramFormats, + FLXPostgresResultsAsBinary); + } + else if ([query isKindOfClass:[FLXPostgresStatement class]]) { + FLXPostgresStatement *statement = (FLXPostgresStatement *)query; + + // Statement has not been prepared yet, so prepare it with the given parameter types + if (![statement name]) { + BOOL prepareResult = [self _prepare:statement num:paramData->paramNum types:paramData->paramTypes]; + + if (!prepareResult || ![statement name]) return nil; + } + + result = PQexecPrepared(_connection, + [statement UTF8Name], + paramData->paramNum, + (const char **)paramData->paramValues, + (const int *)paramData->paramLengths, + (const int *)paramData->paramFormats, + FLXPostgresResultsAsBinary); + } + else { + // TODO: get rid of exceptions + [FLXPostgresException raise:FLXPostgresConnectionErrorDomain reason:[NSString stringWithFormat:@"Trying to execute a query that is not of type NSString or FLXPostgresStatement"]]; + return nil; + } + + [self _destroyParamDataStructure:paramData]; + + if (!result || [self _queryDidError:result]) return nil; + + return [[[FLXPostgresResult alloc] initWithResult:result connection:self] autorelease]; +} + +/** + * Determines whether or not the supplied result indicates an error occurred. + * + * @param result The result to examine. + * + * @return A BOOL indicating if an error occurred. + */ +- (BOOL)_queryDidError:(PGresult *)result +{ + ExecStatusType status = PQresultStatus(result); + + if (status == PGRES_BAD_RESPONSE || status == PGRES_FATAL_ERROR) { + NSString *error = [NSString stringWithUTF8String:PQresultErrorMessage(result)]; + + if (_lastErrorMessage) [_lastErrorMessage release], _lastErrorMessage = nil; + + _lastErrorMessage = [[NSString alloc] initWithString:error]; + + PQclear(result); + + return YES; + } + + return NO; +} + +/** + * Creates the internal query parameter data structure. + * + * @note This method will throw an exception if it can't allocated the required memory. + * + * @param paramNum The number of parameters the structure should accommodate. + * + * @return The data structure or nil if an exception occurred. + */ +- (FLXQueryParamData *)_createParameterDataStructureWithCount:(int)paramNum +{ + FLXQueryParamData *paramData = malloc(sizeof(FLXQueryParamData)); + + paramData->paramNum = paramNum; + paramData->paramValues = NULL; + paramData->paramTypes = NULL; + paramData->paramLengths = NULL; + paramData->paramFormats = NULL; + + if (paramData->paramNum) { + paramData->paramValues = malloc(sizeof(void *) * paramData->paramNum); + paramData->paramTypes = malloc(sizeof(FLXPostgresOid) * paramData->paramNum); + paramData->paramLengths = malloc(sizeof(int) * paramData->paramNum); + paramData->paramFormats = malloc(sizeof(int) * paramData->paramNum); + + if (!paramData->paramValues || !paramData->paramLengths || !paramData->paramFormats) { + [self _destroyParamDataStructure:paramData]; + + // Probably justifies throwing an exception if we can't allocate any memory! + [FLXPostgresException raise:FLXPostgresConnectionErrorDomain reason:@"Memory allocation error"]; + + return nil; + } + } + + return paramData; +} + +/** + * Frees the memory associated with the supplied parameter data structure. + * + * @param paramData The parameter data to destroy. + */ +- (void)_destroyParamDataStructure:(FLXQueryParamData *)paramData +{ + if (!paramData) return; + + if (paramData->paramValues) free(paramData->paramValues); + if (paramData->paramTypes) free(paramData->paramTypes); + if (paramData->paramLengths) free(paramData->paramLengths); + if (paramData->paramFormats) free(paramData->paramFormats); + + free(paramData); +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryPreparation.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryPreparation.h new file mode 100644 index 00000000..1d769b51 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryPreparation.h @@ -0,0 +1,32 @@ +// +// $Id$ +// +// FLXPostgresConnectionQueryPreparation.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnection.h" + +@interface FLXPostgresConnection (FLXPostgresConnectionQueryPreparation) + +- (NSString *)quote:(NSObject *)object; + +- (FLXPostgresStatement *)prepare:(NSString *)query; +- (FLXPostgresStatement *)prepareWithFormat:(NSString *)query, ...; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryPreparation.m b/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryPreparation.m new file mode 100644 index 00000000..d8bf59b7 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionQueryPreparation.m @@ -0,0 +1,131 @@ +// +// $Id$ +// +// FLXPostgresConnectionQueryPreparation.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnectionQueryPreparation.h" +#import "FLXPostgresConnectionTypeHandling.h" +#import "FLXPostgresConnectionPrivateAPI.h" +#import "FLXPostgresStatement.h" +#import "FLXPostgresException.h" + +@implementation FLXPostgresConnection (FLXPostgresConnectionQueryPreparation) + +/** + * Quotes the supplied object in accordance with it's data type. + * + * @param object The object to quote. + * + * @return A string representation of the quoted object. + */ +- (NSString *)quote:(NSObject *)object +{ + if (!object || [object isKindOfClass:[NSNull class]]) return @"NULL"; + + id <FLXPostgresTypeHandlerProtocol> handler = [self typeHandlerForClass:[object class]]; + + if (!handler) { + [FLXPostgresException raise:FLXPostgresConnectionErrorDomain + reason:[NSString stringWithFormat:@"Unsupported class '%@'", NSStringFromClass([object class])]]; + + return nil; + } + + return [handler quotedStringFromObject:object]; +} + +/** + * Creates a prepared statment from the supplied query. + * + * @param query The query to create the statement from. + * + * @return The prepared statement instance. + */ +- (FLXPostgresStatement *)prepare:(NSString *)query +{ + if (!query || ![query length]) return nil; + + return [[[FLXPostgresStatement alloc] initWithStatement:query] autorelease]; +} + +/** + * Creates a prepared statment from the supplied query format and values. + * + * @param query The query to create the statement from. + * @param ... Any values to insert into the query (optional). + * + * @return The prepared statement instance. + */ +- (FLXPostgresStatement *)prepareWithFormat:(NSString *)query, ... +{ + if (!query || ![query length]) return nil; + + va_list args; + va_start(args, query); + + NSMutableString *string = [[NSMutableString alloc] initWithFormat:query arguments:args]; + + va_end(args); + + FLXPostgresStatement *statement = [self prepare:string]; + + [string release]; + + return statement; +} + +#pragma mark - +#pragma mark Private API + +/** + * Actually prepares the supplied statement against the database. + * + * @param statement The statement to prepare. + * @param paranNum The number of parameters the statement contains. + * @param paramTypes Any of Postgres parameter types. + * + * @return A BOOL indicating succes. Returns NO if there's no statement, statement name or current connection. + */ +- (BOOL)_prepare:(FLXPostgresStatement *)statement num:(int)paramNum types:(FLXPostgresOid *)paramTypes +{ + if (!statement || ![statement name] || ![self isConnected]) return NO; + + NSString *name = [[NSProcessInfo processInfo] globallyUniqueString]; + + PGresult *result = PQprepare(_connection, [name UTF8String], [statement UTF8Statement], paramNum, paramTypes); + + if (!result) return NO; + + ExecStatusType resultStatus = PQresultStatus(result); + + if (resultStatus == PGRES_BAD_RESPONSE || resultStatus == PGRES_FATAL_ERROR) { + PQclear(result); + + return NO; + } + + PQclear(result); + + [statement setName:name]; + + return YES; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.h new file mode 100644 index 00000000..351b1d24 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.h @@ -0,0 +1,33 @@ +// +// $Id$ +// +// FLXPostgresConnectionTypeHandling.h +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on July 29, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnection.h" + +@interface FLXPostgresConnection (FLXPostgresConnectionTypeHandling) + +- (void)registerTypeHandlers; + +- (id <FLXPostgresTypeHandlerProtocol>)typeHandlerForClass:(Class)class; +- (id <FLXPostgresTypeHandlerProtocol>)typeHandlerForRemoteType:(FLXPostgresOid)type; + +- (void)registerTypeHandler:(Class)handlerClass; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.m b/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.m new file mode 100644 index 00000000..bd46e788 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionTypeHandling.m @@ -0,0 +1,105 @@ +// +// $Id$ +// +// FLXPostgresConnectionTypeHandling.m +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on July 29, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnectionTypeHandling.h" +#import "FLXPostgresTypeStringHandler.h" +#import "FLXPostgresTypeNumberHandler.h" +#import "FLXPostgresException.h" + +@implementation FLXPostgresConnection (FLXPostgresConnectionTypeHandling) + +/** + * Register all of our data type handlers for this connection. + */ +- (void)registerTypeHandlers +{ + if (_typeMap) { + [_typeMap release]; + + _typeMap = [[NSMutableDictionary alloc] init]; + } + + [self registerTypeHandler:[FLXPostgresTypeStringHandler class]]; + [self registerTypeHandler:[FLXPostgresTypeNumberHandler class]]; +} + +/** + * Get the data type handler for the supplied class. + * + * @param class The class to get the handler for. + * + * @return The handler or nil if there's none associated with the class. + */ +- (id <FLXPostgresTypeHandlerProtocol>)typeHandlerForClass:(Class)class +{ + return [_typeMap objectForKey:NSStringFromClass(class)]; +} + +/** + * Get the data type handler for the supplied PostgreSQL type. + * + * @param type The PostgreSQL type to get the handler for. + * + * @return The handler or nil if there's none associated with the type. + */ +- (id <FLXPostgresTypeHandlerProtocol>)typeHandlerForRemoteType:(FLXPostgresOid)type +{ + return [_typeMap objectForKey:[NSNumber numberWithUnsignedInteger:type]]; +} + +/** + * Register the supplied type handler class. + * + * @param handlerClass The handler class to register. + */ +- (void)registerTypeHandler:(Class)handlerClass +{ + if (![handlerClass conformsToProtocol:@protocol(FLXPostgresTypeHandlerProtocol)]) { + [FLXPostgresException raise:FLXPostgresConnectionErrorDomain + reason:@"Class '%@' does not conform to protocol '%@'", NSStringFromClass(handlerClass), NSStringFromProtocol(@protocol(FLXPostgresTypeHandlerProtocol))]; + } + + // Create an instance of this class + id <FLXPostgresTypeHandlerProtocol> handler = [[[handlerClass alloc] initWithConnection:self] autorelease]; + + // Add to the type map - for native class + [_typeMap setObject:handler forKey:NSStringFromClass([handler nativeClass])]; + + NSArray *aliases = [handler classAliases]; + + if (aliases) { + for (NSString *alias in aliases) + { + [_typeMap setObject:handler forKey:alias]; + } + } + + FLXPostgresOid *remoteTypes = [handler remoteTypes]; + + for (NSUInteger i = 0; remoteTypes[i]; i++) + { + NSNumber *key = [NSNumber numberWithUnsignedInteger:remoteTypes[i]]; + + [_typeMap setObject:handler forKey:key]; + } +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionUtils.h b/Frameworks/PostgresKit/Source/FLXPostgresConnectionUtils.h new file mode 100644 index 00000000..60eacfea --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionUtils.h @@ -0,0 +1,33 @@ +// +// $Id$ +// +// FLXPostgresConnectionUtils.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnection.h" + +@interface FLXPostgresConnection (FLXPostgresConnectionUtils) + +- (NSArray *)schemas; +- (NSArray *)databases; +- (NSArray *)tablesInSchema:(NSString *)schema; +- (NSArray *)columnNamesForTable:(NSString *)table inSchema:(NSString *)schema; +- (NSString *)primaryKeyForTable:(NSString *)table inSchema:(NSString *)schema; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresConnectionUtils.m b/Frameworks/PostgresKit/Source/FLXPostgresConnectionUtils.m new file mode 100644 index 00000000..e988c7f2 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresConnectionUtils.m @@ -0,0 +1,133 @@ +// +// $Id$ +// +// FLXPostgresConnectionUtils.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresConnectionQueryPreparation.h" +#import "FLXPostgresConnectionQueryExecution.h" +#import "FLXPostgresResult.h" + +@interface FLXPostgresConnection () + +- (NSArray *)_executeAndReturnResult:(NSString *)query; + +@end + +@implementation FLXPostgresConnection (FLXPostgresConnectionUtils) + +/** + * Returns an array of all databases. + * + * @return An array of strings or nil if no connection is present. + */ +- (NSArray *)databases +{ + return [self isConnected] ? [self _executeAndReturnResult:@"SELECT DISTINCT \"catalog_name\" FROM \"information_schema\".\"schemata\""] : nil; +} + +/** + * Returns an array of all schemas. + * + * @return An array of strings or nil if no connection is present. + */ +- (NSArray *)schemas +{ + return [self isConnected] ? [self _executeAndReturnResult:[NSString stringWithFormat:@"SELECT \"schema_name\" FROM \"information_schema\".\"schemata\" WHERE \"catalog_name\" = %@", [self quote:[self database]]]] : nil; +} + +/** + * Returns an array of tables in the supplied schema. + * + * @param schem The schema to get tables for. + * + * @return An array of strings or nil if not connected or parameters are not valid. + */ +- (NSArray * )tablesInSchema:(NSString *)schema +{ + if (![self isConnected] || !schema || ![schema length]) return nil; + + return [self _executeAndReturnResult:[NSString stringWithFormat:@"SELECT \"table_name\" FROM \"information_schema\".\"tables\" WHERE \"table_catalog\" = %@ AND \"table_schema\" = %@ AND \"table_type\" = 'BASE TABLE'", [self quote:[self database]], [self quote:schema]]]; +} + +/** + * Get the primary key column name on the supplied table in the supplied schema. + * + * @param table The table to get the primary key for. + * @param schema The schem the table belongs to. + * + * @return The column name as a string or nil not connected or parameters are not valid. + */ +- (NSString *)primaryKeyForTable:(NSString *)table inSchema:(NSString *)schema +{ + if (![self isConnected] || !table || ![table length] || !schema || ![schema length]) return nil; + + NSString *join = @"\"information_schema\".\"table_constraints\" t INNER JOIN \"information_schema\".\"key_column_usage\" k ON t.\"constraint_name\" = k.\"constraint_name\""; + NSString *where = [NSString stringWithFormat:@"t.\"constraint_type\" = 'PRIMARY KEY' AND t.\"table_catalog\" = %@ AND t.\"table_schema\" = %@ AND t.\"table_name\" = %@", [self quote:[self database]], [self quote:schema], [self quote:table]]; + + FLXPostgresResult *result = [self executeWithFormat:@"SELECT k.\"column_name\" FROM %@ WHERE %@", join, where]; + + return [result numberOfRows] == 0 ? nil : [[result rowAsArray] objectAtIndex:0]; +} + +/** + * Returns an array of column names for the supplied table and schema. + * + * @param table The table to get column names from. + * @param schema The schem the table belongs to. + * + * @return An array of strings or nil if not connected or parameters are not valid. + */ +- (NSArray *)columnNamesForTable:(NSString *)table inSchema:(NSString *)schema +{ + if (![self isConnected] || !table || ![table length] || !schema || ![schema length]) return nil; + + return [self _executeAndReturnResult:[NSString stringWithFormat:@"SELECT \"column_name\" FROM \"information_schema\".\"columns\" WHERE \"table_catalog\" = %@ AND \"table_schema\" = %@ AND \"table_name\" = %@", [self quote:[self database]], [self quote:schema], [self quote:table]]]; +} + +#pragma mark - +#pragma mark Private API + +/** + * Executes the supplied query and returns the result. + * + * @param query The query to execute. + * + * @return The result as an array. + */ +- (NSArray *)_executeAndReturnResult:(NSString *)query +{ + FLXPostgresResult *result = [self execute:query]; + + if (!result || ![result numberOfRows]) return nil; + + NSArray *row = nil; + NSMutableArray *data = [NSMutableArray arrayWithCapacity:(NSUInteger)[result numberOfRows]]; + + while ((row = [result rowAsArray])) + { + if (![row count]) continue; + + [data addObject:[row objectAtIndex:0]]; + } + + return data; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresError.h b/Frameworks/PostgresKit/Source/FLXPostgresError.h new file mode 100644 index 00000000..e9009ecb --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresError.h @@ -0,0 +1,74 @@ +// +// $Id$ +// +// FLXPostgresError.h +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on September 3, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +@interface FLXPostgresError : NSObject +{ + NSString *_errorSeverity; + NSString *_errorStateCode; + NSString *_errorPrimaryMessage; + NSString *_errorDetailMessage; + NSString *_errorMessageHint; + + NSUInteger _errorStatementPosition; +} + +/** + * @property errorSeverity + */ +@property (readonly) NSString *errorSeverity; + +/** + * @property errorStateCode + */ +@property (readonly) NSString *errorStateCode; + +/** + * @property errorPrimaryMessage + */ +@property (readonly) NSString *errorPrimaryMessage; + +/** + * @property errorDetailMessage + */ +@property (readonly) NSString *errorDetailMessage; + +/** + * @property errorMessageHint + */ +@property (readonly) NSString *errorMessageHint; + +/** + * @property errorStatementPosition + */ +@property (readonly) NSUInteger errorStatementPosition; + +- (id)initWithResult:(PGresult *)result; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresError.m b/Frameworks/PostgresKit/Source/FLXPostgresError.m new file mode 100644 index 00000000..6a0a6210 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresError.m @@ -0,0 +1,136 @@ +// +// $Id$ +// +// FLXPostgresError.m +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on September 3, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import "FLXPostgresError.h" +#import "FLXPostgresException.h" + +@interface FLXPostgresError () + +- (void)_extractErrorDetailsFromResult:(PGresult *)result; +- (NSString *)_extractErrorField:(int)field fromResult:(PGresult *)result; + +@end + +@implementation FLXPostgresError + +@synthesize errorSeverity = _errorSeverity; +@synthesize errorStateCode = _errorStateCode; +@synthesize errorPrimaryMessage = _errorPrimaryMessage; +@synthesize errorDetailMessage = _errorDetailMessage; +@synthesize errorMessageHint = _errorMessageHint; +@synthesize errorStatementPosition = _errorStatementPosition; + +#pragma mark - + +- (id)init +{ + [FLXPostgresException raise:NSInternalInconsistencyException + reason:@"%@ shouldn't be init'd directly; use initWithResult: instead.", [self className]]; + + return nil; +} + +- (id)initWithResult:(PGresult *)result +{ + if ((self = [super init])) { + + _errorSeverity = nil; + _errorStateCode = nil; + _errorPrimaryMessage = nil; + _errorDetailMessage = nil; + _errorMessageHint = nil; + _errorStatementPosition = -1; + + if (result) [self _extractErrorDetailsFromResult:result]; + } + + return self; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"<%@: Sev %@ (%@): %@>", [self className], _errorSeverity, _errorStateCode, _errorPrimaryMessage]; +} + +#pragma mark - +#pragma mark Private API + +/** + * Extracts all the error information from the supplied result. + * + * @param result The Postgres result to extract the information from. + */ +- (void)_extractErrorDetailsFromResult:(PGresult *)result +{ + // Note that we don't expose all the fields that are available. + // The ones we don't mostly include information internal to Postgres + // that generally isn't useful to end users. + _errorSeverity = [self _extractErrorField:PG_DIAG_SEVERITY fromResult:result]; + _errorStateCode = [self _extractErrorField:PG_DIAG_SQLSTATE fromResult:result]; + _errorPrimaryMessage = [self _extractErrorField:PG_DIAG_MESSAGE_PRIMARY fromResult:result]; + _errorDetailMessage = [self _extractErrorField:PG_DIAG_MESSAGE_DETAIL fromResult:result]; + _errorMessageHint = [self _extractErrorField:PG_DIAG_MESSAGE_HINT fromResult:result]; + + NSString *statementPosition = [self _extractErrorField:PG_DIAG_STATEMENT_POSITION fromResult:result]; + + _errorStatementPosition = [statementPosition integerValue]; + + [statementPosition release]; +} + +/** + * Extracts the supplied error field from the supplied Postgres result. + * + * @param field The error field to extract. + * @param result The Postgres result to extract the field from. + * + * @return A string representing the error value. The caller is responsible for freeing the associated memory. + */ +- (NSString *)_extractErrorField:(int)field fromResult:(PGresult *)result +{ + const char *errorData = PQresultErrorField(result, field); + + return [[NSString alloc] initWithBytes:errorData length:strlen(errorData) encoding:NSUTF8StringEncoding]; +} + +#pragma mark - + +- (void)dealloc +{ + if (_errorSeverity) [_errorSeverity release], _errorSeverity = nil; + if (_errorStateCode) [_errorStateCode release], _errorStateCode = nil; + if (_errorPrimaryMessage) [_errorPrimaryMessage release], _errorPrimaryMessage = nil; + if (_errorDetailMessage) [_errorDetailMessage release], _errorDetailMessage = nil; + if (_errorMessageHint) [_errorMessageHint release], _errorMessageHint = nil; + + [super dealloc]; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresException.h b/Frameworks/PostgresKit/Source/FLXPostgresException.h new file mode 100644 index 00000000..54b781c4 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresException.h @@ -0,0 +1,28 @@ +// +// $Id$ +// +// FLXPostgresException.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +@interface FLXPostgresException : NSException + ++ (void)raise:(NSString *)name connection:(void *)connection; ++ (void)raise:(NSString *)name reason:(NSString *)reason, ...; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresException.m b/Frameworks/PostgresKit/Source/FLXPostgresException.m new file mode 100644 index 00000000..266ac1a7 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresException.m @@ -0,0 +1,64 @@ +// +// $Id$ +// +// FLXPostgresException.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresException.h" + +@implementation FLXPostgresException + +/** + * Raise a new exception with the supplied details. + * + * @param name The name of the exception to raise. + * @param connection The connection associated with the exception being raised. + */ ++ (void)raise:(NSString *)name connection:(void *)connection +{ + const char *errorMessage = "Unknown error"; + + if (connection) errorMessage = PQerrorMessage(connection); + + errorMessage = strlen(errorMessage) ? errorMessage : "Unknown error"; + + [[[[FLXPostgresException alloc] initWithName:name reason:[NSString stringWithUTF8String:errorMessage] userInfo:nil] autorelease] raise]; +} + +/** + * Raise a new exception with the supplied details. + * + * @param name The name of the exception to raise. + * @param reason The reason for the exception being raised. + */ ++ (void)raise:(NSString *)name reason:(NSString *)reason, ... +{ + va_list args; + va_start(args, reason); + + NSString *reasonMessage = [[NSString alloc] initWithFormat:reason arguments:args]; + + va_end(args); + + [[[[FLXPostgresException alloc] initWithName:name reason:reasonMessage userInfo:nil] autorelease] raise]; + + [reasonMessage release]; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresResult.h b/Frameworks/PostgresKit/Source/FLXPostgresResult.h new file mode 100644 index 00000000..e198cee5 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresResult.h @@ -0,0 +1,71 @@ +// +// $Id$ +// +// FLXPostgresResult.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "libpq-fe.h" +#import "FLXConstants.h" + +@class FLXPostgresConnection; + +@interface FLXPostgresResult : NSObject +{ + void *_result; + void **_typeHandlers; + + unsigned long long _row; + unsigned int _numberOfFields; + unsigned long long _numberOfRows; + + NSString **_fields; + + NSStringEncoding _stringEncoding; + + FLXPostgresConnection *_connection; +} + +/** + * @property numberOfFields The number of fields this result has. + */ +@property (readonly) unsigned int numberOfFields; + +/** + * @property numberOfRows The number or rows this result has. + */ +@property (readonly) unsigned long long numberOfRows; + +/** + * @property stringEncoding The ecoding that was in use when this result was created. + */ +@property (readonly) NSStringEncoding stringEncoding; + +- (id)initWithResult:(PGresult *)result connection:(FLXPostgresConnection *)connection; + +- (unsigned int)numberOfFields; + +- (void)seekToRow:(unsigned long long)row; + +- (NSArray *)fields; + +- (NSArray *)rowAsArray; +- (NSDictionary *)rowAsDictionary; +- (id)rowAsType:(FLXPostgresResultRowType)type; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresResult.m b/Frameworks/PostgresKit/Source/FLXPostgresResult.m new file mode 100644 index 00000000..62e0d222 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresResult.m @@ -0,0 +1,264 @@ +// +// $Id$ +// +// FLXPostgresResult.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresResult.h" +#import "FLXPostgresException.h" +#import "FLXPostgresConnection.h" +#import "FLXPostgresConnectionTypeHandling.h" + +static NSString *FLXPostgresResultError = @"FLXPostgresResultError"; + +@interface FLXPostgresResult () + +- (void)_populateFields; +- (id)_objectForRow:(unsigned int)row column:(unsigned int)column; +- (id <FLXPostgresTypeHandlerProtocol>)_typeHandlerForColumn:(unsigned int)column; + +@end + +@implementation FLXPostgresResult + +@synthesize numberOfRows = _numberOfRows; +@synthesize numberOfFields = _numberOfFields; +@synthesize stringEncoding = _stringEncoding; + +#pragma mark - +#pragma mark Initialisation + +/** + * Prevent normal initialisation. + * + * @return nil + */ +- (id)init +{ + [FLXPostgresException raise:NSInternalInconsistencyException reason:@"%@ shouldn't be init'd directly; use initWithResult:connection: instead.", [self className]]; + + return nil; +} + +/** + * Initialises a result with the supplied details. + * + * @param result The underlying PostgreSQL result this wrapper represents. + * @param connection The connection the result came from. + * + * @return The result wrapper. + */ +- (id)initWithResult:(PGresult *)result connection:(FLXPostgresConnection *)connection +{ + NSParameterAssert(result); + + if ((self = [super init])) { + + _row = 0; + _result = result; + _numberOfRows = PQntuples(_result); + _numberOfFields = PQnfields(_result); + _connection = [connection retain]; + + _stringEncoding = [_connection stringEncoding]; + + _typeHandlers = (void **)calloc(sizeof(void *), _numberOfFields); + + unsigned long long affectedRows = (unsigned long long)[[NSString stringWithUTF8String:PQcmdTuples(_result)] longLongValue]; + + _numberOfRows = PQresultStatus(_result) == PGRES_TUPLES_OK ? _numberOfRows : affectedRows; + + [self _populateFields]; + } + + return self; +} + +#pragma mark - +#pragma mark Public API + +/** + * This result's fields as an array. + * + * @return The array of fields. + */ +- (NSArray *)fields +{ + return [NSArray arrayWithObjects:_fields count:_numberOfFields]; +} + +/** + * Sets the current row marker to the supplied row. + * + * @param row The row to seek to. + */ +- (void)seekToRow:(unsigned long long)row +{ + if (row >= _numberOfRows) row = _numberOfRows - 1; + + _row = row; +} + +#pragma mark - +#pragma mark Data Retrieval + +/** + * Return the current row as an array. + * + * @return The array of data. + */ +- (NSArray *)rowAsArray +{ + return [self rowAsType:FLXPostgresResultRowAsArray]; +} + +/** + * Return the current row as dictionary with keys as field names and values as the data. + * + * @return The row as a dictionary. + */ +- (NSDictionary *)rowAsDictionary +{ + return [self rowAsType:FLXPostgresResultRowAsDictionary]; +} + +/** + * Return the current row in the format specified by the supplied type. + * + * @return The data row as either an array or dictionary. + */ +- (id)rowAsType:(FLXPostgresResultRowType)type +{ + if (_row >= _numberOfRows) return nil; + + id data; + + data = (type == FLXPostgresResultRowAsArray) ? [NSMutableArray arrayWithCapacity:_numberOfFields] : [NSMutableDictionary dictionaryWithCapacity:_numberOfFields]; + + for (unsigned int i = 0; i < _numberOfFields; i++) + { + id object = [self _objectForRow:(int)_row column:i]; + + if (type == FLXPostgresResultRowAsArray) { + [(NSMutableArray *)data addObject:object]; + } + else { + [(NSMutableDictionary *)data setObject:object forKey:_fields[i]]; + } + } + + _row++; + + return data; +} + +#pragma mark - +#pragma mark Private API + +/** + * Populates the internal field names array. + */ +- (void)_populateFields +{ + _fields = malloc(sizeof(NSString *) * _numberOfFields); + + for (unsigned int i = 0; i < _numberOfFields; i++) + { + const char *bytes = PQfname(_result, i); + + if (!bytes) continue; + + _fields[i] = [[NSString alloc] initWithBytes:bytes length:strlen(bytes) encoding:_stringEncoding]; + } +} + +/** + * Get the native object at the supplied row and column. + * + * @param row The row index to get the data from. + * @param column The column index to get the data from. + * + * @return The native object or nil if out of this result's range. + */ +- (id)_objectForRow:(unsigned int)row column:(unsigned int)column +{ + if (row >= _numberOfRows || column >= _numberOfFields) return nil; + + // Check for null + if (PQgetisnull(_result, row, column)) return [NSNull null]; + + // Get bytes and length + const void *bytes = PQgetvalue(_result, row, column); + + NSUInteger length = PQgetlength(_result, row, column); + FLXPostgresOid type = PQftype(_result, column); + + // Get handler for this type + id <FLXPostgresTypeHandlerProtocol> handler = [self _typeHandlerForColumn:column]; + + if (!handler) { + NSLog(@"PostgresKit: Warning: No type handler found for type %d, return NSData.", type); + + return [NSData dataWithBytes:bytes length:length]; + } + + return [handler objectFromRemoteData:bytes length:length type:type]; +} + +/** + * Get the data type handler for the supplied column index. + * + * @param column The column index to get the handler for. + * + * @return The type handler or nil if out of this result's range. + */ +- (id <FLXPostgresTypeHandlerProtocol>)_typeHandlerForColumn:(unsigned int)column +{ + if (column >= _numberOfFields) return nil; + + id handler = _typeHandlers[column]; + + if (!handler) { + FLXPostgresOid type = PQftype(_result, column); + + _typeHandlers[column] = [_connection typeHandlerForRemoteType:type]; + + handler = _typeHandlers[column]; + } + + return handler; +} + +#pragma mark - + +-(void)dealloc +{ + PQclear(_result); + + for (unsigned int i = 0; i < _numberOfFields; i++) [_fields[i] release]; + + free(_fields); + free(_typeHandlers); + + if (_connection) [_connection release], _connection = nil; + + [super dealloc]; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresStatement.h b/Frameworks/PostgresKit/Source/FLXPostgresStatement.h new file mode 100644 index 00000000..fafbb8dc --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresStatement.h @@ -0,0 +1,44 @@ +// +// $Id$ +// +// FLXPostgresStatement.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +@interface FLXPostgresStatement : NSObject +{ + NSString *_statement; + NSString *_name; +} + +/** + * @property statement The query statement. + */ +@property (readwrite, retain) NSString *statement; + +/** + * @property name The name of this statement. + */ +@property (readwrite, retain) NSString *name; + +- (id)initWithStatement:(NSString *)queryStatement; + +- (const char *)UTF8Name; +- (const char *)UTF8Statement; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresStatement.m b/Frameworks/PostgresKit/Source/FLXPostgresStatement.m new file mode 100644 index 00000000..a1505ccd --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresStatement.m @@ -0,0 +1,81 @@ +// +// $Id$ +// +// FLXPostgresStatement.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresStatement.h" + +@implementation FLXPostgresStatement + +@synthesize name = _name; +@synthesize statement = _statement; + +#pragma mark - +#pragma mark Initialisation + +- (id)initWithStatement:(NSString *)queryStatement +{ + if ((self = [super init])) { + [self setStatement:queryStatement]; + [self setName:nil]; + } + + return self; +} + +#pragma mark - +#pragma mark Public API + +/** + * Returns a null terminated C string of the statement's name. + * + * @return The statement name. + */ +- (const char *)UTF8Name +{ + return [[self name] UTF8String]; +} + +/** + * Returns a null terminated C string of the statement. + * + * @return The prepared statement. + */ +- (const char *)UTF8Statement +{ + return [[self statement] UTF8String]; +} + +- (NSString *)description +{ + return [self name] ? [NSString stringWithFormat:@"<%@ %@>", [self className], [self name]] : [NSString stringWithFormat:@"<%@>", [self className]]; +} + +#pragma mark - + +- (void)dealloc +{ + if (_name) [_name release], _name = nil; + if (_statement) [_statement release], _statement = nil; + + [super dealloc]; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.h b/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.h new file mode 100644 index 00000000..154d364f --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.h @@ -0,0 +1,35 @@ +// +// $Id$ +// +// FLXPostgresTypeDateTimeHandler.h +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on September 1, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import "FLXPostgresTypeHandler.h" + +@interface FLXPostgresTypeDateTimeHandler : FLXPostgresTypeHandler <FLXPostgresTypeHandlerProtocol> + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.m b/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.m new file mode 100644 index 00000000..761e9e17 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeDateTimeHandler.m @@ -0,0 +1,86 @@ +// +// $Id$ +// +// FLXPostgresTypeDateTimeHandler.m +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on September 1, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +#import "FLXPostgresTypeDateTimeHandler.h" +#import "FLXPostgresConnection.h" + +static FLXPostgresOid FLXPostgresTypeDateTimeTypes[] = +{ + FLXPostgresOidAbsTime, + FLXPostgresOidDate, + FLXPostgresOidTime, + FLXPostgresOidTimeTZ, + 0 +}; + +@implementation FLXPostgresTypeDateTimeHandler + +#pragma mark - +#pragma mark Protocol Implementation + +- (FLXPostgresOid *)remoteTypes +{ + return FLXPostgresTypeDateTimeTypes; +} + +- (Class)nativeClass +{ + return [NSDate class]; +} + +- (NSArray *)classAliases +{ + return nil; +} + +- (NSData *)remoteDataFromObject:(id)object type:(FLXPostgresOid *)type +{ + if (!object || !type || ![object isKindOfClass:[NSDate class]]) return nil; + + return nil; +} + +- (id)objectFromRemoteData:(const void *)bytes length:(NSUInteger)length type:(FLXPostgresOid)type +{ + if (!bytes || !type) return nil; + + // TODO: Imeplement me! + return nil; +} + +- (NSString *)quotedStringFromObject:(id)object +{ + if (!object || ![object isKindOfClass:[NSString class]]) return nil; + + // TODO: Imeplement me! + return nil; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeHandler.h b/Frameworks/PostgresKit/Source/FLXPostgresTypeHandler.h new file mode 100644 index 00000000..f2808d52 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeHandler.h @@ -0,0 +1,38 @@ +// +// $Id$ +// +// FLXPostgresTypeHandler.h +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on July 27, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresTypeHandlerProtocol.h" + +@class FLXPostgresConnection; + +@interface FLXPostgresTypeHandler : NSObject +{ + FLXPostgresConnection *_connection; +} + +/** + * @property connection The connection this type handler is associated with. + */ +@property (readonly) FLXPostgresConnection *connection; + +- (id)initWithConnection:(FLXPostgresConnection *)connection; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeHandler.m b/Frameworks/PostgresKit/Source/FLXPostgresTypeHandler.m new file mode 100644 index 00000000..a1b5fac6 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeHandler.m @@ -0,0 +1,46 @@ +// +// $Id$ +// +// FLXPostgresTypeHandler.h +// PostgresKit +// +// Created by Stuart Connolly (stuconnolly.com) on July 27, 2012. +// Copyright (c) 2012 Stuart Connolly. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresTypeHandler.h" + +@implementation FLXPostgresTypeHandler + +@synthesize connection = _connection; + +- (id)initWithConnection:(FLXPostgresConnection *)connection +{ + if ((self = [super init])) { + _connection = [connection retain]; + } + + return self; +} + +#pragma mark - + +- (void)dealloc +{ + if (_connection) [_connection release], _connection = nil; + + [super dealloc]; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeHandlerProtocol.h b/Frameworks/PostgresKit/Source/FLXPostgresTypeHandlerProtocol.h new file mode 100644 index 00000000..49261e60 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeHandlerProtocol.h @@ -0,0 +1,84 @@ +// +// $Id$ +// +// FLXPostgresTypeHandlerProtocol.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresTypes.h" + +@class FLXPostgresConnection; + +/** + * @protocol FLXPostgresTypeHandlerProtocol + */ +@protocol FLXPostgresTypeHandlerProtocol + +/** + * The remote type values handled by this class (terminated by 0). + * + * @return The remote types as an array of FLXPostgresOid's. + */ +- (FLXPostgresOid *)remoteTypes; + +/** + * What is the native class this class handles. + * + * @return The native class. + */ +- (Class)nativeClass; + +/** + * Any aliases that the native class is known by. + * + * @return An of aliases as strings or nil if none. + */ +- (NSArray *)classAliases; + +/** + * Return a transmittable data representation from the supplied object, + * and set the remote type for the data. + * + * @param object The object to produce the data for. + * @param type The type of object we're supplying. + * + * @return The data represenation as an NSData instance. + */ +- (NSData *)remoteDataFromObject:(id)object type:(FLXPostgresOid *)type; + +/** + * Convert the supplied remote data into an object. + * + * @param bytes The remote data to convert. + * @param length The length of the data. + * @param type The type of data. + * + * @return An object represenation of the data. + */ +- (id)objectFromRemoteData:(const void *)bytes length:(NSUInteger)length type:(FLXPostgresOid)type; + +/** + * Return a quoted string from an object. + * + * @param object The object to quote. + * + * @return A string represenation of the object quoted. + */ +- (NSString *)quotedStringFromObject:(id)object; + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.h b/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.h new file mode 100644 index 00000000..a3305e19 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.h @@ -0,0 +1,28 @@ +// +// $Id$ +// +// FLXPostgresTypeNumberHandler.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresTypeHandler.h" + +@interface FLXPostgresTypeNumberHandler : FLXPostgresTypeHandler <FLXPostgresTypeHandlerProtocol> + +@end + diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.m b/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.m new file mode 100644 index 00000000..0c75e282 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeNumberHandler.m @@ -0,0 +1,325 @@ +// +// $Id$ +// +// FLXPostgresTypeNumberHandler.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresTypeNumberHandler.h" +#import "FLXPostgresTypes.h" + +static FLXPostgresOid FLXPostgresTypeNumberTypes[] = +{ + FLXPostgresOidInt8, + FLXPostgresOidInt2, + FLXPostgresOidInt4, + FLXPostgresOidFloat4, + FLXPostgresOidFloat8, + FLXPostgresOidBool, + 0 +}; + +@implementation FLXPostgresTypeNumberHandler + +#pragma mark - +#pragma mark Integer & Unsigned Integer + +- (SInt16)int16FromBytes:(const void *)bytes +{ + if (!bytes) return 0; + + return EndianS16_BtoN(*((SInt16 *)bytes)); +} + +- (SInt32)int32FromBytes:(const void *)bytes +{ + if (!bytes) return 0; + + return EndianS32_BtoN(*((SInt32 *)bytes)); +} + +- (SInt64)int64FromBytes:(const void *)bytes +{ + if (!bytes) return 0; + + return EndianS64_BtoN(*((SInt64 *)bytes)); +} + +- (UInt16)unsignedInt16FromBytes:(const void *)bytes +{ + if (!bytes) return 0; + + return EndianU16_BtoN(*((UInt16 *)bytes)); +} + +- (UInt32)unsignedInt32FromBytes:(const void *)bytes +{ + if (!bytes) return 0; + + return EndianU32_BtoN(*((UInt32 *)bytes)); +} + +- (UInt64)unsignedInt64FromBytes:(const void *)bytes +{ + if (!bytes) return 0; + + return EndianU64_BtoN(*((UInt64 *)bytes)); +} + +- (NSNumber *)integerObjectFromBytes:(const void *)bytes length:(NSUInteger)length +{ + if (!bytes) return nil; + + switch (length) + { + case 2: + return [NSNumber numberWithShort:[self int16FromBytes:bytes]]; + case 4: + return [NSNumber numberWithInteger:[self int32FromBytes:bytes]]; + case 8: + return [NSNumber numberWithLongLong:[self int64FromBytes:bytes]]; + } + + return nil; +} + +- (NSNumber *)unsignedIntegerObjectFromBytes:(const void *)bytes length:(NSUInteger)length +{ + if (!bytes) return nil; + + switch (length) + { + case 2: + return [NSNumber numberWithUnsignedShort:[self unsignedInt16FromBytes:bytes]]; + case 4: + return [NSNumber numberWithUnsignedInteger:[self unsignedInt32FromBytes:bytes]]; + case 8: + return [NSNumber numberWithUnsignedLongLong:[self unsignedInt64FromBytes:bytes]]; + } + + return nil; +} + +- (NSData *)remoteDataFromInt64:(SInt64)value +{ + if (sizeof(SInt64) != 8) return nil; + + value = EndianS64_NtoB(value); + + return [NSData dataWithBytes:&value length:sizeof(value)]; +} + +- (NSData *)remoteDataFromInt32:(SInt32)value +{ + if (sizeof(SInt32) != 4) return nil; + + value = EndianS32_NtoB(value); + + return [NSData dataWithBytes:&value length:sizeof(value)]; +} + +- (NSData *)remoteDataFromInt16:(SInt16)value +{ + if (sizeof(SInt16) != 2) return nil; + + value = EndianS16_NtoB(value); + + return [NSData dataWithBytes:&value length:sizeof(value)]; +} + +#pragma mark - +#pragma mark Floating Point + +- (Float32)float32FromBytes:(const void *)bytes +{ + if (!bytes) return 0; + + union { Float32 r; UInt32 i; } u32; + + u32.r = *((Float32 *)bytes); + u32.i = CFSwapInt32HostToBig(u32.i); + + return u32.r; +} + +- (Float64)float64FromBytes:(const void *)bytes +{ + if (!bytes) return 0; + + union { Float64 r; UInt64 i; } u64; + + u64.r = *((Float64 *)bytes); + u64.i = CFSwapInt64HostToBig(u64.i); + + return u64.r; +} + +- (NSNumber *)realObjectFromBytes:(const void *)bytes length:(NSUInteger)length +{ + switch (length) + { + case 4: + return [NSNumber numberWithFloat:[self float32FromBytes:bytes]]; + case 8: + return [NSNumber numberWithDouble:[self float64FromBytes:bytes]]; + } + + return nil; +} + + +- (NSData *)remoteDataFromFloat32:(Float32)value +{ + if (sizeof(Float32) != 4) return nil; + + union { Float32 r; UInt32 i; } u32; + + u32.r = value; + u32.i = CFSwapInt32HostToBig(u32.i); + + return [NSData dataWithBytes:&u32 length:sizeof(u32)]; +} + +- (NSData *)remoteDataFromFloat64:(Float64)value +{ + if (sizeof(Float64) != 8) return nil; + + union { Float64 r; UInt64 i; } u64; + + u64.r = value; + u64.i = CFSwapInt64HostToBig(u64.i); + + return [NSData dataWithBytes:&u64 length:sizeof(u64)]; +} + +#pragma mark - +#pragma mark Boolean + +- (BOOL)booleanFromBytes:(const void *)bytes +{ + if (!bytes) return NO; + + return (*((const int8_t *)bytes) ? YES : NO); +} + +- (NSNumber *)booleanObjectFromBytes:(const void *)bytes length:(NSUInteger)length +{ + if (!bytes || length != 1) return nil; + + return [NSNumber numberWithBool:[self booleanFromBytes:bytes]]; +} + + +- (NSData *)remoteDataFromBoolean:(BOOL)value +{ + return [NSData dataWithBytes:&value length:1]; +} + +#pragma mark - +#pragma mark Protocol Implementation + +- (FLXPostgresOid *)remoteTypes +{ + return FLXPostgresTypeNumberTypes; +} + +- (Class)nativeClass +{ + return [NSNumber class]; +} + +- (NSArray *)classAliases +{ + return nil; +} + +- (NSData *)remoteDataFromObject:(id)object type:(FLXPostgresOid *)type +{ + if (!object || !type || ![object isKindOfClass:[NSNumber class]]) return nil; + + NSNumber *number = (NSNumber *)object; + + const char *objectType = [number objCType]; + + switch (objectType[0]) + { + case 'c': + case 'C': + case 'B': // Boolean + (*type) = FLXPostgresOidBool; + return [self remoteDataFromBoolean:[(NSNumber *)object boolValue]]; + case 'i': // Integer + case 'l': // Long + case 'S': // Unsigned short + (*type) = FLXPostgresOidInt4; + return [self remoteDataFromInt32:[(NSNumber *)object shortValue]]; + case 's': + (*type) = FLXPostgresOidInt2; + return [self remoteDataFromInt16:[(NSNumber *)object shortValue]]; + case 'q': // Long long + case 'Q': // Unsigned long long + case 'I': // Unsigned integer + case 'L': // Unsigned long + (*type) = FLXPostgresOidInt8; + return [self remoteDataFromInt64:[(NSNumber *)object longLongValue]]; + case 'f': // Float + (*type) = FLXPostgresOidFloat4; + return [self remoteDataFromFloat32:[(NSNumber *)object floatValue]]; + case 'd': // Double + (*type) = FLXPostgresOidFloat8; + return [self remoteDataFromFloat64:[(NSNumber *)object doubleValue]]; + } + + return nil; +} + +- (id)objectFromRemoteData:(const void *)bytes length:(NSUInteger)length type:(FLXPostgresOid)type +{ + if (!bytes || !length || !type) return nil; + + switch (type) + { + case FLXPostgresOidInt8: + case FLXPostgresOidInt2: + case FLXPostgresOidInt4: + return [self integerObjectFromBytes:bytes length:length]; + case FLXPostgresOidFloat4: + case FLXPostgresOidFloat8: + return [self realObjectFromBytes:bytes length:length]; + case FLXPostgresOidBool: + return [self booleanObjectFromBytes:bytes length:length]; + default: + return nil; + } +} + +- (NSString *)quotedStringFromObject:(id)object +{ + if (!object || ![object isKindOfClass:[NSNumber class]]) return nil; + + const char *type = [object objCType]; + + if (type[0] == 'c' || type[0] == 'C' || type[0] == 'B') { + return ([(NSNumber *)object boolValue] ? @"true" : @"false"); + } + else { + return [(NSNumber *)object stringValue]; + } +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.h b/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.h new file mode 100644 index 00000000..43a70cfe --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.h @@ -0,0 +1,28 @@ +// +// $Id$ +// +// FLXPostgresTypeStringHandler.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresTypeHandler.h" + +@interface FLXPostgresTypeStringHandler : FLXPostgresTypeHandler <FLXPostgresTypeHandlerProtocol> + +@end + diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.m b/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.m new file mode 100644 index 00000000..de1d064d --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypeStringHandler.m @@ -0,0 +1,77 @@ +// +// $Id$ +// +// FLXPostgresTypeStringHandler.m +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresTypeStringHandler.h" +#import "FLXPostgresConnection.h" +#import "FLXPostgresTypes.h" + +static FLXPostgresOid FLXPostgresTypeStringTypes[] = +{ + FLXPostgresOidText, + FLXPostgresOidChar, + FLXPostgresOidVarchar, + FLXPostgresOidUnknown, + 0 +}; + +@implementation FLXPostgresTypeStringHandler + +#pragma mark - +#pragma mark Protocol Implementation + +- (FLXPostgresOid *)remoteTypes +{ + return FLXPostgresTypeStringTypes; +} + +- (Class)nativeClass +{ + return [NSString class]; +} + +- (NSArray *)classAliases +{ + return [NSArray arrayWithObject:@"NSCFString"]; +} + +- (NSData *)remoteDataFromObject:(id)object type:(FLXPostgresOid *)type +{ + if (!object || !type || ![object isKindOfClass:[NSString class]]) return nil; + + return [(NSString *)object dataUsingEncoding:[_connection stringEncoding]]; +} + +- (id)objectFromRemoteData:(const void *)bytes length:(NSUInteger)length type:(FLXPostgresOid)type +{ + if (!bytes || !type) return nil; + + return [[[NSString alloc] initWithBytes:bytes length:length encoding:[_connection stringEncoding]] autorelease]; +} + +- (NSString *)quotedStringFromObject:(id)object +{ + if (!object || ![object isKindOfClass:[NSString class]]) return nil; + + return [NSString stringWithFormat:@"'%@'", [[object description] stringByReplacingOccurrencesOfString:@"'" withString:@"''"]]; +} + +@end diff --git a/Frameworks/PostgresKit/Source/FLXPostgresTypes.h b/Frameworks/PostgresKit/Source/FLXPostgresTypes.h new file mode 100644 index 00000000..7c146e41 --- /dev/null +++ b/Frameworks/PostgresKit/Source/FLXPostgresTypes.h @@ -0,0 +1,80 @@ +// +// $Id$ +// +// FLXPostgresTypes.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "postgres_ext.h" + +// Generic PostgreSQL object ID +typedef Oid FLXPostgresOid; + +// See PostgreSQL source: include/catalog/pg_type.h + +enum +{ + FLXPostgresOidBool = 16, + FLXPostgresOidData = 17, + FLXPostgresOidName = 19, + FLXPostgresOidInt8 = 20, + FLXPostgresOidInt2 = 21, + FLXPostgresOidInt4 = 23, + FLXPostgresOidText = 25, + FLXPostgresOidOid = 26, + FLXPostgresOidXML = 142, + FLXPostgresOidPoint = 600, + FLXPostgresOidLSeg = 601, + FLXPostgresOidPath = 602, + FLXPostgresOidBox = 603, + FLXPostgresOidPolygon = 604, + FLXPostgresOidFloat4 = 700, + FLXPostgresOidFloat8 = 701, + FLXPostgresOidAbsTime = 702, + FLXPostgresOidUnknown = 705, + FLXPostgresOidCircle = 718, + FLXPostgresOidMoney = 790, + FLXPostgresOidMacAddr = 829, + FLXPostgresOidIPAddr = 869, + FLXPostgresOidNetAddr = 869, + FLXPostgresOidArrayBool = 1000, + FLXPostgresOidArrayData = 1001, + FLXPostgresOidArrayChar = 1002, + FLXPostgresOidArrayName = 1003, + FLXPostgresOidArrayInt2 = 1005, + FLXPostgresOidArrayInt4 = 1007, + FLXPostgresOidArrayText = 1009, + FLXPostgresOidArrayVarchar = 1015, + FLXPostgresOidArrayInt8 = 1016, + FLXPostgresOidArrayFloat4 = 1021, + FLXPostgresOidArrayFloat8 = 1022, + FLXPostgresOidArrayMacAddr = 1040, + FLXPostgresOidArrayIPAddr = 1041, + FLXPostgresOidChar = 1042, + FLXPostgresOidVarchar = 1043, + FLXPostgresOidDate = 1082, + FLXPostgresOidTime = 1083, + FLXPostgresOidTimestamp = 1114, + FLXPostgresOidTimestampTZ = 1184, + FLXPostgresOidInterval = 1186, + FLXPostgresOidTimeTZ = 1266, + FLXPostgresOidBit = 1560, + FLXPostgresOidVarbit = 1562, + FLXPostgresOidNumeric = 1700, + FLXPostgresOidMax = 1700 +}; diff --git a/Frameworks/PostgresKit/Source/PostgresKit-Prefix.pch b/Frameworks/PostgresKit/Source/PostgresKit-Prefix.pch new file mode 100644 index 00000000..822e702a --- /dev/null +++ b/Frameworks/PostgresKit/Source/PostgresKit-Prefix.pch @@ -0,0 +1,31 @@ +// +// $Id$ +// +// PostgresKit-Prefix.pch +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#ifdef __OBJC__ + #import <Foundation/Foundation.h> + + // PostgreSQL interface + #import "libpq-fe.h" + + // Framework constants + #import "FLXConstants.h" +#endif diff --git a/Frameworks/PostgresKit/Source/PostgresKit.h b/Frameworks/PostgresKit/Source/PostgresKit.h new file mode 100644 index 00000000..cc9c7f13 --- /dev/null +++ b/Frameworks/PostgresKit/Source/PostgresKit.h @@ -0,0 +1,27 @@ +// +// PostgresKit.h +// PostgresKit +// +// Copyright (c) 2008-2009 David Thorpe, djt@mutablelogic.com +// +// Forked by the Sequel Pro Team on July 22, 2012. +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +// License for the specific language governing permissions and limitations under +// the License. + +#import "FLXPostgresResult.h" +#import "FLXPostgresStatement.h" +#import "FLXPostgresException.h" +#import "FLXPostgresConnection.h" +#import "FLXPostgresConnectionUtils.h" +#import "FLXPostgresConnectionQueryExecution.h" +#import "FLXPostgresConnectionQueryPreparation.h" |