libpqtypes - libpqtypes-int.h

Home Page

  1 
  2 /*
  3  * libpqtypes-int.h
  4  *   Private header file for libpqtypes.  All source files include
  5  *   this header.
  6  *
  7  * Copyright (c) 2009 eSilo, LLC. All rights reserved.
  8  * This is free software; see the source for copying conditions.  There is
  9  * NO warranty; not even for MERCHANTABILITY or  FITNESS FOR A  PARTICULAR
 10  * PURPOSE.
 11  */
 12 
 13 #ifndef LIBPQTYPES_INT_H
 14 #define LIBPQTYPES_INT_H
 15 
 16 #define PLN do{ \
 17   printf("%s:%d\n", __FUNCTION__, __LINE__); \
 18   fflush(stdout); \
 19 }while(0)
 20 
 21 #ifdef HAVE_CONFIG_H
 22 # include "pqt_config.h"
 23 #endif
 24 
 25 /* Using the windows compiler */
 26 #ifdef _MSC_VER
 27 # define PQT_MSVC _MSC_VER
 28 #endif
 29 
 30 /* We can/should use the Windows API */
 31 #if defined(PQT_MSVC) || defined(__MINGW32__)
 32 # define PQT_WINAPI
 33 #endif
 34 
 35 /* Compiling on a windows platform */
 36 #if defined(PQT_WINAPI) || defined(__CYGWIN__)
 37 # define PQT_WIN32
 38 #endif
 39 
 40 /* WINAPI is available, include needed winsock headers */
 41 #ifdef PQT_WINAPI
 42 # ifdef PQT_MSVC
 43 #   pragma warning (disable : 4706 4100 4711 4127 4702 4706 4100 4514 4710 4201 4206)
 44 # endif
 45 # include <winsock2.h>
 46 # include <ws2tcpip.h>
 47 # include <Wspiapi.h> /* need for getaddrinfo (2000 and below */
 48 # include <windows.h>
 49 #else
 50 # if defined(__CYGWIN__) || defined(HAVE_SYS_TYPES_H)
 51 #   include <sys/types.h>
 52 # endif
 53 # if defined(__CYGWIN__) || defined(HAVE_SYS_SOCKET_H)
 54 #   include <sys/socket.h>
 55 # endif
 56 # if defined(__CYGWIN__) || defined(HAVE_NETDB_H)
 57 #   include <netdb.h>
 58 # endif
 59 # if defined(__CYGWIN__) || defined(HAVE_NETINET_IN_H)
 60 #   include <netinet/in.h>
 61 # endif
 62 # if defined(__CYGWIN__) || defined(HAVE_ARPA_INET_H)
 63 #   include <arpa/inet.h>
 64 # endif
 65 #endif
 66 
 67 #include <stdio.h>
 68 #include <stdlib.h>
 69 #include <ctype.h>
 70 #include <errno.h>
 71 
 72 /* string*.h, windows platforms just include string.h */
 73 #ifdef PQT_WIN32
 74 # include <string.h>
 75 #else
 76 # ifdef HAVE_STRING_H
 77 #   include <string.h>
 78 # endif
 79 # ifdef HAVE_STRINGS_H
 80 #   include <strings.h>
 81 # endif
 82 #endif
 83 
 84 /* Include stddef.h if on windows or if we have it */
 85 #if defined(PQT_WIN32) || defined(HAVE_STDDEF_H)
 86 # include <stddef.h>
 87 #endif
 88 
 89 /* Include limits.h if on windows or if we have it */
 90 #if defined(PQT_WIN32) || defined(HAVE_LIMITS_H)
 91 # include <limits.h>
 92 #endif
 93 
 94 /* Include linux/limits.h if available */
 95 #if defined(HAVE_CONFIG_H) && defined(HAVE_LINUX_LIMITS_H)
 96 # include <linux/limits.h>
 97 #endif
 98 
 99 /* Include math.h if on windows or if we have it */
100 #if defined(PQT_WIN32) || defined(HAVE_MATH_H)
101 # include <math.h>
102 #endif
103 
104 /* Include the public API, pulls in libpq-fe.h for us. */
105 #include "libpqtypes.h"
106 #include "libpq-events.h"
107 
108 #ifdef __cplusplus
109 extern "C" {
110 #endif
111 
112 #ifndef TRUE
113 # define TRUE 1
114 #endif
115 
116 #ifndef FALSE
117 # define FALSE 0
118 #endif
119 
120 #ifndef NULL_LEN
121 # define NULL_LEN (-1)
122 #endif
123 
124 /* Win32 builds use _timezone and _tzname: manually define HAVE_TZNAME. */
125 #ifdef PQT_WIN32
126 # define HAVE_TZNAME
127 # define pqt_timezone _timezone
128 # define pqt_tzname   _tzname
129 #else
130 # define pqt_timezone timezone
131 # define pqt_tzname   tzname
132 #endif
133 
134 #define PQT_OUTOFMEMORY "Out of memory error"
135 #define PQT_MAXIDLEN 64
136 
137 #define TEXTFMT 0
138 #define BINARYFMT 1
139 #define TYPFLAG_CASEFOLD 0x01
140 #define TYPFLAG_ARRAY    0x02
141 #define TYPFLAG_POINTER  0x04
142 #define TYPFLAG_INVALID  0x08
143 #define TYPFLAG_BYNAME   0x10
144 
145 /* Avoid passing NULL to realloc, some systems don't support it */
146 #define pqt_realloc(ptr, size) (ptr) ? realloc(ptr, size) : malloc(size)
147 
148 #define countof(array) (int) (sizeof(array) / sizeof(array[0]))
149 
150 /* MSVC 8 deprecated quite a few POSIX names */
151 #if defined(PQT_MSVC) && PQT_MSVC >= 1400
152 # undef strdup
153 # undef sscanf
154 # define strdup _strdup
155 # define sscanf sscanf_s
156 #endif
157 
158 /* define va_copy */
159 #ifndef va_copy
160 # ifdef __va_copy
161 #   define va_copy(dest, src) __va_copy(dest, src)
162 # else
163 #   define va_copy(dest, src) (dest) = (src)
164 # endif
165 #endif
166 
167 #define pqt_hex_to_dec(v) \
168   (unsigned char) (((v) > '9') ? ((v) - 'a') + 10 : (v) - '0')
169 
170 enum
171 {
172   PQT_REGTYPE_SUBCLASS,
173   PQT_REGTYPE_COMPOSITE,
174   PQT_REGTYPE_USERDEFINED
175 };
176 
177 /* --------------------------------
178  * Macros used by built-in handlers
179  */
180 
181 /* used by get handlers */
182 #define DECLLENGTH(args) \
183   int valuel = PQgetlength((args)->get.result, (args)->get.tup_num, \
184     (args)->get.field_num)
185 
186 /* used by get handlers */
187 #define DECLVALUE(getargs) \
188   char *value = PQgetvalue((getargs)->get.result, (getargs)->get.tup_num, \
189     (getargs)->get.field_num)
190 
191 /* used by put handlers */
192 #define PUTNULLCHK(args, valp) do{ \
193   if (!(valp)) \
194     return pqt_put_null(args); \
195 }while (0)
196 
197 /* used by get handlers, checks for NULL pointers and PQgetisnull */
198 #define CHKGETVALS(args, outp) do{ \
199   if (!(outp)) \
200     RERR(args, "output pointer is NULL"); \
201   memset(outp, 0, sizeof(*(outp))); \
202   if (PQgetisnull((args)->get.result, (args)->get.tup_num, \
203       (args)->get.field_num)) \
204     return 0; \
205 }while (0)
206 
207 /* RERR for return error: errorf always returns -1 */
208 #define RERR(_args, msg) return (_args)->errorf(_args, msg)
209 #define RERR_STR2INT(args) RERR(args, "String to integer conversion failed")
210 #define RERR_MEM(args) RERR(args, PQT_OUTOFMEMORY)
211 
212 #ifdef STRICT_MEMORY_ALIGNMENT
213 # define pqt_buf_putint2(_buffer, _val) do{ \
214     short _v = (short) htons((short) (_val)); \
215     memcpy(_buffer, &_v, sizeof(short)); \
216   } while (0)
217 
218 # define pqt_buf_putint4(_buffer, _val) do{ \
219     int _v = (int) htonl((int) (_val)); \
220     memcpy(_buffer, &_v, sizeof(int)); \
221   } while (0)
222 
223   short pqt_buf_getint2(char *buffer);
224   int pqt_buf_getint4(char *buffer);
225 #else
226 # define pqt_buf_putint2(_out, _val) \
227   *(short *) (_out) = (short) htons((short) (_val))
228 # define pqt_buf_getint2(_buffer) (short) ntohs(*(short *) (_buffer))
229 # define pqt_buf_putint4(_out, _val) \
230   *(int *) (_out) = (int) htonl((int) (_val))
231 # define pqt_buf_getint4(_buffer) (int) ntohl(*(int *) (_buffer))
232 #endif
233 
234 /* ----------------------------------
235  * See: src/include/catalog/pg_type.h
236  * Used by built-in type handlers
237  */
238 
239 /* numerics types */
240 #define INT2OID            21
241 #define INT4OID            23
242 #define INT8OID            20
243 #define FLOAT4OID         700
244 #define FLOAT8OID         701
245 #define NUMERICOID       1700
246 /* geo types */
247 #define POINTOID          600
248 #define LSEGOID           601
249 #define PATHOID           602
250 #define BOXOID            603
251 #define POLYGONOID        604
252 #define LINEOID           628 /* not supported yet */
253 #define CIRCLEOID         718
254 /* network types */
255 #define INETOID           869
256 #define CIDROID           650
257 #define MACADDROID        829
258 /* variable length types */
259 #define BPCHAROID        1042
260 #define VARCHAROID       1043
261 #define NAMEOID            19
262 #define TEXTOID            25
263 #define ZPBITOID         1560 /* not supported yet */
264 #define VARBITOID        1562 /* not supported yet */
265 #define BYTEAOID           17
266 /* date and time types */
267 #define DATEOID          1082
268 #define TIMEOID          1083
269 #define TIMETZOID        1266
270 #define TIMESTAMPOID     1114
271 #define TIMESTAMPTZOID   1184
272 #define INTERVALOID      1186
273 /* misc types */
274 #define CHAROID            18
275 #define BOOLOID            16
276 #define OIDOID             26
277 #define CASHOID           790
278 #define RECORDOID        2249
279 #define UUIDOID          2950
280 
281 /* --------------------------------
282  * Private Structures
283  */
284 
285 /* Represents a param value.  An array of PGvalues was choosen over
286  * allocating 4 separate arrays: oids, values, lengths, formats.  Instead
287  * of 4 allocations you only have one.  The PGvalue array can easily be
288  * converted to 4 arrays for execution.
289  */
290 typedef struct
291 {
292   int ptrl;   /* Length of value's pointer */
293   void *ptr;  /* value pointer, data member uses this for non-NULL values */
294   int datal;  /* Length of current value: always <= ptrl */
295   char *data; /* current value data, can be NULL ... thus the ptr member. */
296   int format; /* format: 0=text, 1=binary */
297   Oid oid;    /* Oid of the data */
298 } PGvalue;
299 
300 /* performance driven structure.  Instead of parsing and looking up
301  * type specs each put or get, PQspecPrepare can be used to compile
302  * a spec format string into a PGtypeSpec object.  The biggest wins are
303  * large results sets and arrays.
304  */
305 typedef struct
306 {
307   char *name;           /* name for the prepared spec, used for lookup. */
308   char *stmt;           /* parameterized version of stmt, if supplied */
309   int idcnt;            /* number of handler ids */
310   int *idlist;          /* handler ids */
311   unsigned char *flags; /* handler flags */
312 } PGtypeSpec;
313 
314 /* PGparam structure */
315 struct pg_param
316 {
317   int vcnt;         /* current number of param values */
318   int vmax;         /* number of PGvalue structs in 'vals' array. */
319   PGvalue *vals;    /* array of param values, grown when needed */
320 
321   /* assigned during PQparamCreate */
322   PGtypeFormatInfo fmtinfo;
323   int typhcnt;
324   PGtypeHandler *typhandlers;
325 
326   int typspeccnt;
327   PGtypeSpec *typspecs;
328 };
329 
330 typedef struct
331 {
332   PGtypeFormatInfo fmtinfo;
333   int typhcnt;
334   int typhmax;
335   PGtypeHandler *typhandlers;
336 
337   int typspeccnt;
338   int typspecmax;
339   PGtypeSpec *typspecs;
340 } PGtypeData;
341 
342 /* --------------------------------
343  * Internal API functions (not exported)
344  */
345 
346 /* === in events.c === */
347 
348 /* The libpq PGEventProc */
349 int pqt_eventproc(PGEventId id, void *info, void *passThrough);
350 
351 /* === in param.c === */
352 
353 int pqt_putparam(PGparam *param, const void *data, int datal,
354   int flags, int format, Oid typoid);
355 
356 /* === in spec.c === */
357 
358 int pqt_growspec(PGtypeSpec *cache, int idmax);
359 PGtypeSpec *pqt_getspec(PGtypeSpec *specs, int count, const char *name);
360 PGtypeSpec *pqt_dupspecs(PGtypeSpec *specs, int count);
361 void pqt_clearspec(PGtypeSpec *cache);
362 void pqt_freespecs(PGtypeSpec *specs, int count);
363 
364 char *pqt_parse(const char *format, PGtypeHandler *h, int hcnt,
365   char *stmtBuf, size_t stmtBufLen, PGtypeHandler **out, size_t *stmtPos,
366   int *typpos, int *flags);
367 
368 char *pqt_parsetype(const char *spec, char *schema, char *typname,
369   int *flags, int typpos);
370 
371 /* === in handler.c === */
372 
373 int pqt_allowsptr(PGtypeHandler *h);
374 void pqt_getfmtinfo(const PGconn *conn, PGtypeFormatInfo *info);
375 PGtypeHandler *pqt_duphandlers(PGtypeHandler *handlers, int hcnt);
376 void pqt_freehandlers(PGtypeHandler *handlers, int hcnt);
377 int pqt_argssuper(PGtypeArgs *args, ...);
378 int pqt_argserrorf(PGtypeArgs *args, const char *format, ...);
379 void pqt_setresultfields(const PGresult *res);
380 
381 PGtypeHandler *pqt_gethandler(PGtypeHandler *handlers, int hcnt,
382   const char *schema, const char *typname);
383 
384 PGtypeHandler *pqt_gethandlerbyid(PGtypeHandler *handlers,
385   int hcnt, int id);
386 
387 /* FQTN standards for Fully Qualified Type Name.  Returns a pointer to out.
388  * Only returns NULL if out is NULL or outl <= 0.
389  */
390 char *pqt_fqtn(char *out, size_t outl,
391   const char *schema, const char *typname);
392 
393 /* == in utils.c == */
394 
395 PGresult *pqt_copyresult(PGtypeArgs *args, int nattrs);
396 void pqt_swap8(void *outp, void *inp, int tonet);
397 int pqt_text_to_int8(char *val, void *out);
398 int pqt_text_to_float8(double *f8, char *text, char **endptr);
399 
400 /* Checks buffer and truncates 'src' if 'dest' is too small. */
401 char *pqt_strcpy(char *dest, size_t size, const char *src);
402 
403 /* Taken from postgres project (named pg_xxx) */
404 unsigned char pqt_tolower(unsigned char ch);
405 int pqt_strcasecmp(const char *s1, const char *s2);
406 int pqt_strncasecmp(const char *s1, const char *s2, size_t n);
407 
408 /* == in port.c == */
409 
410 /* Define a strtoll macro for windows, except for MinGW & Cygwin
411  * which always have it.  MSVC has _strtoi64, but MSVC 6 and under
412  * require that we declare the prototype.
413  */
414 #ifdef PQT_MSVC
415 # if PQT_MSVC <= 1200
416     __int64 __cdecl _strtoi64(const char *, char **, int);
417 # endif
418 # define strtoll _strtoi64
419 #endif
420 
421 /* In rare cases these could be absent (older platforms).  We implement
422  * drop-in replacements in port.c for those cases.  strtod handled by
423  * configure, which adds a replacement for us.
424  *
425  * NOTE: only unixes use configure so sections wrapped around
426  * HAVE_CONFIG_H exclude windows.
427  */
428 #ifdef HAVE_CONFIG_H
429 # ifndef HAVE_STRTOL
430     long strtol(const char *nptr, char **endptr, int base);
431 # endif
432 # ifndef HAVE_STRTOUL
433     unsigned long strtoul(const char *nptr, char **endptr, int base);
434 # endif
435 # ifndef HAVE_STRTOLL
436     long long int strtoll(const char *nptr, char **endptr, int base);
437 # endif
438 #endif
439 
440 /* Handles platform differences and always returns -1 for failure.
441  * On windows: MSVC 8 uses _snprintf_s, otherwise _snprintf.
442  */
443 int pqt_snprintf(char *buf, size_t size, const char *format, ...);
444 int pqt_vsnprintf(char *buf, size_t size, const char *format, va_list ap);
445 
446 /* --------------------------------
447  * Built-in Type Handlers
448  */
449 
450 /* === in array.c === */
451 
452 int pqt_put_array(PGtypeArgs *args);
453 int pqt_get_array(PGtypeArgs *args);
454 
455 /* == in datetime.c == */
456 
457 int pqt_put_date(PGtypeArgs *args);
458 int pqt_get_date(PGtypeArgs *args);
459 int pqt_put_time(PGtypeArgs *args);
460 int pqt_get_time(PGtypeArgs *args);
461 int pqt_put_timetz(PGtypeArgs *args);
462 int pqt_get_timetz(PGtypeArgs *args);
463 int pqt_put_timestamp(PGtypeArgs *args);
464 int pqt_get_timestamp(PGtypeArgs *args);
465 int pqt_put_timestamptz(PGtypeArgs *args);
466 int pqt_get_timestamptz(PGtypeArgs *args);
467 int pqt_put_interval(PGtypeArgs *args);
468 int pqt_get_interval(PGtypeArgs *args);
469 
470 /* == in geo.c == */
471 
472 int pqt_put_point(PGtypeArgs *args);
473 int pqt_get_point(PGtypeArgs *args);
474 int pqt_put_lseg(PGtypeArgs *args);
475 int pqt_get_lseg(PGtypeArgs *args);
476 int pqt_put_box(PGtypeArgs *args);
477 int pqt_get_box(PGtypeArgs *args);
478 int pqt_put_circle(PGtypeArgs *args);
479 int pqt_get_circle(PGtypeArgs *args);
480 int pqt_put_path(PGtypeArgs *args);
481 int pqt_get_path(PGtypeArgs *args);
482 int pqt_put_polygon(PGtypeArgs *args);
483 int pqt_get_polygon(PGtypeArgs *args);
484 
485 /* == in misc.c == */
486 
487 int pqt_put_char(PGtypeArgs *args); /* "char" type, not char(N) */
488 int pqt_get_char(PGtypeArgs *args);
489 int pqt_put_bool(PGtypeArgs *args);
490 int pqt_get_bool(PGtypeArgs *args);
491 int pqt_put_money(PGtypeArgs *args);
492 int pqt_get_money(PGtypeArgs *args);
493 int pqt_put_uuid(PGtypeArgs *args);
494 int pqt_get_uuid(PGtypeArgs *args);
495 int pqt_put_null(PGtypeArgs *args); /* no get for null */
496 
497 /* == in network.c == */
498 
499 int pqt_put_inet(PGtypeArgs *args); /* handles cidr */
500 int pqt_get_inet(PGtypeArgs *args);
501 int pqt_get_cidr(PGtypeArgs *args);
502 int pqt_put_macaddr(PGtypeArgs *args);
503 int pqt_get_macaddr(PGtypeArgs *args);
504 
505 /* == in numerics.c == */
506 
507 int pqt_put_int2(PGtypeArgs *args);
508 int pqt_get_int2(PGtypeArgs *args);
509 int pqt_put_int4(PGtypeArgs *args); /* handles oid */
510 int pqt_get_int4(PGtypeArgs *args); /* handles oid */
511 int pqt_put_int8(PGtypeArgs *args);
512 int pqt_get_int8(PGtypeArgs *args);
513 int pqt_put_float4(PGtypeArgs *args);
514 int pqt_get_float4(PGtypeArgs *args);
515 int pqt_put_float8(PGtypeArgs *args);
516 int pqt_get_float8(PGtypeArgs *args);
517 int pqt_put_numeric(PGtypeArgs *args);
518 int pqt_get_numeric(PGtypeArgs *args);
519 
520 /* == record.c (composites) == */
521 
522 int pqt_put_record(PGtypeArgs *args);
523 int pqt_get_record(PGtypeArgs *args);
524 
525 /* == in varlena.c == */
526 
527 int pqt_put_str(PGtypeArgs *args);  /* no get for str - use PQgetvalue */
528 int pqt_put_text(PGtypeArgs *args); /* handles varchar, bpchar and name */
529 int pqt_get_text(PGtypeArgs *args); /* handles varchar, bpchar and name */
530 int pqt_put_bytea(PGtypeArgs *args);
531 int pqt_get_bytea(PGtypeArgs *args);
532 
533 #ifdef __cplusplus
534 }
535 #endif
536 #endif