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 |