1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include "postgres.h"
#include "funcapi.h"
#include "catalog/pg_type.h"
#include "fmgr.h"
#include "parseaddress-api.h"
#include <pcre.h>
#include <string.h>
#undef DEBUG
//#define DEBUG 1
#ifdef DEBUG
#define DBG(format, arg...) \
elog(NOTICE, format , ## arg)
#else
#define DBG(format, arg...) do { ; } while (0)
#endif
Datum parse_address(PG_FUNCTION_ARGS);
static char *text2char(text *in)
{
char *out = palloc(VARSIZE(in));
memcpy(out, VARDATA(in), VARSIZE(in) - VARHDRSZ);
out[VARSIZE(in) - VARHDRSZ] = '\0';
return out;
}
PG_FUNCTION_INFO_V1(parse_address);
Datum parse_address(PG_FUNCTION_ARGS)
{
TupleDesc tupdesc;
AttInMetadata *attinmeta;
Datum result;
ADDRESS *paddr;
HHash *stH;
char *str;
char **values;
int err;
HeapTuple tuple;
DBG("Start standardize_address");
str = text2char(PG_GETARG_TEXT_P(0));
DBG("str='%s'", str);
if (get_call_result_type( fcinfo, NULL, &tupdesc ) != TYPEFUNC_COMPOSITE ) {
elog(ERROR, "function returning record called in context"
" that cannot accept type record");
return -1;
}
BlessTupleDesc(tupdesc);
attinmeta = TupleDescGetAttInMetadata(tupdesc);
DBG("Got tupdesc, allocating HHash");
stH = (HHash *) palloc0(sizeof(HHash));
if (!stH) {
elog(ERROR, "parse_address: Failed to allocate memory for hash!");
return -1;
}
DBG("going to load_state_hash");
err = load_state_hash(stH);
if (err) {
DBG("got err=%d from load_state_hash().", err);
#ifdef USE_HSEARCH
DBG("calling hdestroy_r(stH).");
hdestroy_r(stH);
#endif
elog(ERROR, "parse_address: load_state_hash() failed(%d)!", err);
return -1;
}
DBG("calling parseaddress()");
paddr = parseaddress(stH, str, &err);
if (!paddr) {
elog(ERROR, "parse_address: parseaddress() failed!");
return -1;
}
DBG("setup values array for natts=%d", tupdesc->natts);
values = (char **) palloc(9 * sizeof(char *));
if (!values) {
elog(ERROR, "parse_address: out of memory!");
return -1;
}
values[0] = paddr->num;
values[1] = paddr->street;
values[2] = paddr->street2;
values[3] = paddr->address1;
values[4] = paddr->city;
values[5] = paddr->st;
values[6] = paddr->zip;
values[7] = paddr->zipplus;
values[8] = paddr->cc;
DBG("calling heap_form_tuple");
tuple = BuildTupleFromCStrings(attinmeta, values);
/* make the tuple into a datum */
DBG("calling HeapTupleGetDatum");
result = HeapTupleGetDatum(tuple);
/* clean up (this is not really necessary */
DBG("freeing values, hash, and paddr");
free_state_hash(stH);
DBG("returning parsed address result");
return result;
}
|