File: address_parser.c

package info (click to toggle)
postgis 2.5.1%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 75,792 kB
  • sloc: ansic: 139,314; sql: 136,281; xml: 48,954; sh: 4,906; perl: 4,509; makefile: 2,897; python: 1,198; yacc: 441; cpp: 305; lex: 132
file content (120 lines) | stat: -rw-r--r-- 2,995 bytes parent folder | download | duplicates (4)
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;
}