libpqtypes - libpqtypes-int.h

Home Page

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