int pqt_get_lseg(PGtypeArgs *args) { DECLVALUE(args); unsigned int *v; PGlseg *lseg = va_arg(args->ap, PGlseg *); CHKGETVALS(args, lseg); if (args->format == TEXTFMT) { PGpoint *pts = (PGpoint *)lseg; if (*value++ != '[' || !text2point(pts, value, &value) || *value++ != ',' || !text2point(pts + 1, value, &value) || *value != ']') RERR_STR2INT(args); return 0; } v = (unsigned int *) value; pqt_swap8(&lseg->pts[0].x, v, 0); pqt_swap8(&lseg->pts[0].y, v + 2, 0); pqt_swap8(&lseg->pts[1].x, v + 4, 0); pqt_swap8(&lseg->pts[1].y, v + 6, 0); return 0; }
int pqt_get_circle(PGtypeArgs *args) { DECLVALUE(args); unsigned int *v; PGcircle *circle = va_arg(args->ap, PGcircle *); CHKGETVALS(args, circle); if (args->format == TEXTFMT) { if (*value++ != '<' || !text2point((PGpoint *)circle, value, &value) || *value++ != ',' || !pqt_text_to_float8(&circle->radius, value, &value) || *value != '>') RERR_STR2INT(args); return 0; } v = (unsigned int *) value; pqt_swap8(&circle->center.x, v, 0); pqt_swap8(&circle->center.y, v + 2, 0); pqt_swap8(&circle->radius, v + 4, 0); return 0; }
int pqt_get_box(PGtypeArgs *args) { DECLVALUE(args); unsigned int *v; PGbox *box = va_arg(args->ap, PGbox *); CHKGETVALS(args, box); if (args->format == TEXTFMT) { PGpoint *pts = (PGpoint *)box; if (!text2point(pts, value, &value) || *value++ != ',' || !text2point(pts + 1, value, NULL)) RERR_STR2INT(args); return 0; } v = (unsigned int *) value; pqt_swap8(&box->high.x, v, 0); pqt_swap8(&box->high.y, v + 2, 0); pqt_swap8(&box->low.x, v + 4, 0); pqt_swap8(&box->low.y, v + 6, 0); return 0; }
int pqt_get_point(PGtypeArgs *args) { DECLVALUE(args); PGpoint *pt = va_arg(args->ap, PGpoint *); CHKGETVALS(args, pt); if (args->format == TEXTFMT) { if (!text2point(pt, value, NULL)) RERR_STR2INT(args); return 0; } pqt_swap8(&pt->x, (unsigned int *) value, 0); pqt_swap8(&pt->y, ((unsigned int *) (value)) + 2, 0); return 0; }
int pqt_get_array(PGtypeArgs *args) { int i,t; int vlen; int ntups; int nattrs; Oid elemoid; DECLVALUE(args); PGresult *res; int first_tup; PGarray *arr = va_arg(args->ap, PGarray *); CHKGETVALS(args, arr); if (args->format == TEXTFMT) return args->errorf(args, "array does not support text results"); /* number of dims */ arr->ndims = pqt_buf_getint4(value); value += 4; /* skip NULL flag */ value += 4; /* check the element oid */ elemoid = (Oid)pqt_buf_getint4(value); if (elemoid != args->typhandler->typoid) return args->errorf(args, "array element type %u is different than what server says %u", args->typhandler->typoid, elemoid); value += 4; /* arr dims and lbounds */ first_tup = 1; for (i=0, ntups=1; i < arr->ndims; i++) { arr->dims[i] = pqt_buf_getint4(value); value += 4; arr->lbound[i] = pqt_buf_getint4(value); value += 4; ntups *= arr->dims[i]; } /* This means ndims is zero because the above loop never iterated. */ if (i == 0) ntups = 0; /* numTuples is the number of array items * and numAttributes is 1 for non-composites. */ nattrs = (args->typhandler->nattrs > 0) ? args->typhandler->nattrs : 1; if (!(res = pqt_copyresult(args, nattrs))) RERR_MEM(args); for (t=0; t < ntups; t++) { /* get the value len */ vlen = pqt_buf_getint4(value); value += 4; /* Regular Array with 1 attr per tuple */ if (args->typhandler->nattrs == 0) { /* set the field value */ if (!PQsetvalue(res, t, 0, value, vlen)) { PQclear(res); return -1; } if (vlen > 0) value += vlen; continue; } /* ------------------------ * COMPOSITE/RECORD */ /* NULL compsoite array item, fill in attrs with NULL */ if (vlen == NULL_LEN) { int x; for (x=0; x < nattrs; x++) { if (!PQsetvalue(res, t, x, NULL, NULL_LEN)) { PQclear(res); return -1; } } /* move on to next tuple, done here. */ continue; } /* verify that server's attr count matches ours */ if (first_tup) { int attcnt = pqt_buf_getint4(value); /* watch for invalidation issues */ if (attcnt != nattrs) { PQclear(res); return args->errorf(args, "type handler attribute count is %d but server says it's %d", args->typhandler->nattrs, attcnt); } } /* skip attr count */ value += 4; /* composite attributes (record columns) */ for (i=0; i < nattrs; i++) { /* watch for invalidation issues */ if (first_tup && (Oid) pqt_buf_getint4(value) != args->typhandler->attDescs[i].attoid) { Oid server_oid = (Oid) pqt_buf_getint4(value); args->errorf(args, "type handler attribute OID is %u but server says it's %u", args->typhandler->attDescs[i].attoid, server_oid); PQclear(res); return -1; } /* skip oid */ value += 4; /* get the value length */ vlen = pqt_buf_getint4(value); value += 4; /* set the field value */ if (!PQsetvalue(res, t, i, value, vlen)) { PQclear(res); return -1; } if (vlen > 0) value += vlen; } first_tup = 0; } arr->res = res; return 0; }
static int get_inet2(PGtypeArgs *args, int is_cidr) { DECLVALUE(args); unsigned short family; PGinet *inet = va_arg(args->ap, PGinet *); CHKGETVALS(args, inet); if (args->format == TEXTFMT) { int r; char *p; char ipstr[80]; struct addrinfo *ai = NULL; struct addrinfo hints; pqt_strcpy(ipstr, sizeof(ipstr), value); if ((p = strrchr(ipstr, '/'))) { *p = 0; inet->mask = atoi(p+1); } else { inet->mask = 32; } inet->is_cidr = is_cidr; /* suppress hostname lookups */ memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_NUMERICHOST; /* Without this, windows chokes with WSAHOST_NOT_FOUND */ #ifdef PQT_WIN32 hints.ai_family = AF_INET; #endif if ((r = getaddrinfo(ipstr, NULL, &hints, &ai)) || !ai) { if(r == EAI_BADFLAGS) { hints.ai_flags = 0; r = getaddrinfo(ipstr, NULL, &hints, &ai); } /* Another WSAHOST_NOT_FOUND work around, but for IPv6 */ #if defined(PQT_WIN32) && defined(AF_INET6) else if(r == WSAHOST_NOT_FOUND) { hints.ai_flags = 0; hints.ai_family = AF_INET6; r = getaddrinfo(ipstr, NULL, &hints, &ai); } #endif if(r) RERR_STR2INT(args); } inet->sa_buf_len = (int) ai->ai_addrlen; memcpy(inet->sa_buf, ai->ai_addr, inet->sa_buf_len); /* Some platforms, lika AIX 4.3, do not zero this structure properly. * The family and port are dirty, so set the first 4 bytes to 0 and * then re-set the family. I saw "0x1002" as the first 2 bytes of * this structure (dumb getaddrinfo), it should be "0x0002" for AF_INET. */ memset(inet->sa_buf, 0, 4); ((struct sockaddr *)inet->sa_buf)->sa_family = ai->ai_addr->sa_family; /* Uninitialized memory, postgres inet/cidr types don't store this. * Make sure its set to 0. Another AIX problem (maybe other platforms). */ #ifdef AF_INET6 if (ai->ai_addr->sa_family == AF_INET6) ((struct sockaddr_in6 *)inet->sa_buf)->sin6_flowinfo = 0; #endif freeaddrinfo(ai); return 0; } family = (unsigned short) *value++; if (family == PGSQL_AF_INET) { struct sockaddr_in *sa = (struct sockaddr_in *) inet->sa_buf; sa->sin_family = AF_INET; inet->mask = (unsigned char) *value++; inet->is_cidr = *value++; memcpy(&sa->sin_addr, value + 1, *value); inet->sa_buf_len = (int) sizeof(struct sockaddr_in); } #ifdef AF_INET6 else if (family == PGSQL_AF_INET6) { struct sockaddr_in6 *sa = (struct sockaddr_in6 *) inet->sa_buf; sa->sin6_family = AF_INET6; inet->mask = (unsigned char) *value++; inet->is_cidr = *value++; memcpy(&sa->sin6_addr, value + 1, *value); inet->sa_buf_len = (int) sizeof(struct sockaddr_in6); } #endif else { return args->errorf(args, "Unknown inet address family %d", family); } return 0; }