~ubuntu-branches/ubuntu/lucid/postgresql-8.4/lucid-proposed

« back to all changes in this revision

Viewing changes to contrib/ltree/_ltree_op.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-20 12:00:13 UTC
  • Revision ID: james.westby@ubuntu.com-20090320120013-hogj7egc5mjncc5g
Tags: upstream-8.4~0cvs20090328
ImportĀ upstreamĀ versionĀ 8.4~0cvs20090328

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $PostgreSQL:$ 
 
3
 *
 
4
 *
 
5
 * op function for ltree[]
 
6
 * Teodor Sigaev <teodor@stack.net>
 
7
 */
 
8
#include "postgres.h"
 
9
 
 
10
#include <ctype.h>
 
11
 
 
12
#include "utils/array.h"
 
13
#include "ltree.h"
 
14
 
 
15
PG_FUNCTION_INFO_V1(_ltree_isparent);
 
16
PG_FUNCTION_INFO_V1(_ltree_r_isparent);
 
17
PG_FUNCTION_INFO_V1(_ltree_risparent);
 
18
PG_FUNCTION_INFO_V1(_ltree_r_risparent);
 
19
PG_FUNCTION_INFO_V1(_ltq_regex);
 
20
PG_FUNCTION_INFO_V1(_ltq_rregex);
 
21
PG_FUNCTION_INFO_V1(_lt_q_regex);
 
22
PG_FUNCTION_INFO_V1(_lt_q_rregex);
 
23
PG_FUNCTION_INFO_V1(_ltxtq_exec);
 
24
PG_FUNCTION_INFO_V1(_ltxtq_rexec);
 
25
 
 
26
Datum           _ltree_r_isparent(PG_FUNCTION_ARGS);
 
27
Datum           _ltree_r_risparent(PG_FUNCTION_ARGS);
 
28
 
 
29
PG_FUNCTION_INFO_V1(_ltree_extract_isparent);
 
30
PG_FUNCTION_INFO_V1(_ltree_extract_risparent);
 
31
PG_FUNCTION_INFO_V1(_ltq_extract_regex);
 
32
PG_FUNCTION_INFO_V1(_ltxtq_extract_exec);
 
33
Datum           _ltree_extract_isparent(PG_FUNCTION_ARGS);
 
34
Datum           _ltree_extract_risparent(PG_FUNCTION_ARGS);
 
35
Datum           _ltq_extract_regex(PG_FUNCTION_ARGS);
 
36
Datum           _ltxtq_extract_exec(PG_FUNCTION_ARGS);
 
37
 
 
38
PG_FUNCTION_INFO_V1(_lca);
 
39
Datum           _lca(PG_FUNCTION_ARGS);
 
40
 
 
41
typedef Datum (*PGCALL2) (PG_FUNCTION_ARGS);
 
42
 
 
43
#define NEXTVAL(x) ( (ltree*)( (char*)(x) + INTALIGN( VARSIZE(x) ) ) )
 
44
 
 
45
static bool
 
46
array_iterator(ArrayType *la, PGCALL2 callback, void *param, ltree ** found)
 
47
{
 
48
        int                     num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
 
49
        ltree      *item = (ltree *) ARR_DATA_PTR(la);
 
50
 
 
51
        if (ARR_NDIM(la) != 1)
 
52
                ereport(ERROR,
 
53
                                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 
54
                                 errmsg("array must be one-dimensional")));
 
55
        if (ARR_HASNULL(la))
 
56
                ereport(ERROR,
 
57
                                (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 
58
                                 errmsg("array must not contain nulls")));
 
59
 
 
60
        if (found)
 
61
                *found = NULL;
 
62
        while (num > 0)
 
63
        {
 
64
                if (DatumGetBool(DirectFunctionCall2(callback,
 
65
                                                         PointerGetDatum(item), PointerGetDatum(param))))
 
66
                {
 
67
 
 
68
                        if (found)
 
69
                                *found = item;
 
70
                        return true;
 
71
                }
 
72
                num--;
 
73
                item = NEXTVAL(item);
 
74
        }
 
75
 
 
76
        return false;
 
77
}
 
78
 
 
79
Datum
 
80
_ltree_isparent(PG_FUNCTION_ARGS)
 
81
{
 
82
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
83
        ltree      *query = PG_GETARG_LTREE(1);
 
84
        bool            res = array_iterator(la, ltree_isparent, (void *) query, NULL);
 
85
 
 
86
        PG_FREE_IF_COPY(la, 0);
 
87
        PG_FREE_IF_COPY(query, 1);
 
88
        PG_RETURN_BOOL(res);
 
89
}
 
90
 
 
91
Datum
 
92
_ltree_r_isparent(PG_FUNCTION_ARGS)
 
93
{
 
94
        PG_RETURN_DATUM(DirectFunctionCall2(_ltree_isparent,
 
95
                                                                                PG_GETARG_DATUM(1),
 
96
                                                                                PG_GETARG_DATUM(0)
 
97
                                                                                ));
 
98
}
 
99
 
 
100
Datum
 
101
_ltree_risparent(PG_FUNCTION_ARGS)
 
102
{
 
103
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
104
        ltree      *query = PG_GETARG_LTREE(1);
 
105
        bool            res = array_iterator(la, ltree_risparent, (void *) query, NULL);
 
106
 
 
107
        PG_FREE_IF_COPY(la, 0);
 
108
        PG_FREE_IF_COPY(query, 1);
 
109
        PG_RETURN_BOOL(res);
 
110
}
 
111
 
 
112
Datum
 
113
_ltree_r_risparent(PG_FUNCTION_ARGS)
 
114
{
 
115
        PG_RETURN_DATUM(DirectFunctionCall2(_ltree_risparent,
 
116
                                                                                PG_GETARG_DATUM(1),
 
117
                                                                                PG_GETARG_DATUM(0)
 
118
                                                                                ));
 
119
}
 
120
 
 
121
Datum
 
122
_ltq_regex(PG_FUNCTION_ARGS)
 
123
{
 
124
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
125
        lquery     *query = PG_GETARG_LQUERY(1);
 
126
        bool            res = array_iterator(la, ltq_regex, (void *) query, NULL);
 
127
 
 
128
        PG_FREE_IF_COPY(la, 0);
 
129
        PG_FREE_IF_COPY(query, 1);
 
130
        PG_RETURN_BOOL(res);
 
131
}
 
132
 
 
133
Datum
 
134
_ltq_rregex(PG_FUNCTION_ARGS)
 
135
{
 
136
        PG_RETURN_DATUM(DirectFunctionCall2(_ltq_regex,
 
137
                                                                                PG_GETARG_DATUM(1),
 
138
                                                                                PG_GETARG_DATUM(0)
 
139
                                                                                ));
 
140
}
 
141
 
 
142
Datum
 
143
_lt_q_regex(PG_FUNCTION_ARGS)
 
144
{
 
145
        ArrayType  *_tree = PG_GETARG_ARRAYTYPE_P(0);
 
146
        ArrayType  *_query = PG_GETARG_ARRAYTYPE_P(1);
 
147
        lquery     *query = (lquery *) ARR_DATA_PTR(_query);
 
148
        bool            res = false;
 
149
        int                     num = ArrayGetNItems(ARR_NDIM(_query), ARR_DIMS(_query));
 
150
 
 
151
        if (ARR_NDIM(_query) != 1)
 
152
                ereport(ERROR,
 
153
                                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 
154
                                 errmsg("array must be one-dimensional")));
 
155
        if (ARR_HASNULL(_query))
 
156
                ereport(ERROR,
 
157
                                (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 
158
                                 errmsg("array must not contain nulls")));
 
159
 
 
160
        while (num > 0)
 
161
        {
 
162
                if (array_iterator(_tree, ltq_regex, (void *) query, NULL))
 
163
                {
 
164
                        res = true;
 
165
                        break;
 
166
                }
 
167
                num--;
 
168
                query = (lquery *) NEXTVAL(query);
 
169
        }
 
170
 
 
171
        PG_FREE_IF_COPY(_tree, 0);
 
172
        PG_FREE_IF_COPY(_query, 1);
 
173
        PG_RETURN_BOOL(res);
 
174
}
 
175
 
 
176
Datum
 
177
_lt_q_rregex(PG_FUNCTION_ARGS)
 
178
{
 
179
        PG_RETURN_DATUM(DirectFunctionCall2(_lt_q_regex,
 
180
                                                                                PG_GETARG_DATUM(1),
 
181
                                                                                PG_GETARG_DATUM(0)
 
182
                                                                                ));
 
183
}
 
184
 
 
185
 
 
186
Datum
 
187
_ltxtq_exec(PG_FUNCTION_ARGS)
 
188
{
 
189
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
190
        ltxtquery  *query = PG_GETARG_LTXTQUERY(1);
 
191
        bool            res = array_iterator(la, ltxtq_exec, (void *) query, NULL);
 
192
 
 
193
        PG_FREE_IF_COPY(la, 0);
 
194
        PG_FREE_IF_COPY(query, 1);
 
195
        PG_RETURN_BOOL(res);
 
196
}
 
197
 
 
198
Datum
 
199
_ltxtq_rexec(PG_FUNCTION_ARGS)
 
200
{
 
201
        PG_RETURN_DATUM(DirectFunctionCall2(_ltxtq_exec,
 
202
                                                                                PG_GETARG_DATUM(1),
 
203
                                                                                PG_GETARG_DATUM(0)
 
204
                                                                                ));
 
205
}
 
206
 
 
207
 
 
208
Datum
 
209
_ltree_extract_isparent(PG_FUNCTION_ARGS)
 
210
{
 
211
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
212
        ltree      *query = PG_GETARG_LTREE(1);
 
213
        ltree      *found,
 
214
                           *item;
 
215
 
 
216
        if (!array_iterator(la, ltree_isparent, (void *) query, &found))
 
217
        {
 
218
                PG_FREE_IF_COPY(la, 0);
 
219
                PG_FREE_IF_COPY(query, 1);
 
220
                PG_RETURN_NULL();
 
221
        }
 
222
 
 
223
        item = (ltree *) palloc(VARSIZE(found));
 
224
        memcpy(item, found, VARSIZE(found));
 
225
 
 
226
        PG_FREE_IF_COPY(la, 0);
 
227
        PG_FREE_IF_COPY(query, 1);
 
228
        PG_RETURN_POINTER(item);
 
229
}
 
230
 
 
231
Datum
 
232
_ltree_extract_risparent(PG_FUNCTION_ARGS)
 
233
{
 
234
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
235
        ltree      *query = PG_GETARG_LTREE(1);
 
236
        ltree      *found,
 
237
                           *item;
 
238
 
 
239
        if (!array_iterator(la, ltree_risparent, (void *) query, &found))
 
240
        {
 
241
                PG_FREE_IF_COPY(la, 0);
 
242
                PG_FREE_IF_COPY(query, 1);
 
243
                PG_RETURN_NULL();
 
244
        }
 
245
 
 
246
        item = (ltree *) palloc(VARSIZE(found));
 
247
        memcpy(item, found, VARSIZE(found));
 
248
 
 
249
        PG_FREE_IF_COPY(la, 0);
 
250
        PG_FREE_IF_COPY(query, 1);
 
251
        PG_RETURN_POINTER(item);
 
252
}
 
253
 
 
254
Datum
 
255
_ltq_extract_regex(PG_FUNCTION_ARGS)
 
256
{
 
257
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
258
        lquery     *query = PG_GETARG_LQUERY(1);
 
259
        ltree      *found,
 
260
                           *item;
 
261
 
 
262
        if (!array_iterator(la, ltq_regex, (void *) query, &found))
 
263
        {
 
264
                PG_FREE_IF_COPY(la, 0);
 
265
                PG_FREE_IF_COPY(query, 1);
 
266
                PG_RETURN_NULL();
 
267
        }
 
268
 
 
269
        item = (ltree *) palloc(VARSIZE(found));
 
270
        memcpy(item, found, VARSIZE(found));
 
271
 
 
272
        PG_FREE_IF_COPY(la, 0);
 
273
        PG_FREE_IF_COPY(query, 1);
 
274
        PG_RETURN_POINTER(item);
 
275
}
 
276
 
 
277
Datum
 
278
_ltxtq_extract_exec(PG_FUNCTION_ARGS)
 
279
{
 
280
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
281
        ltxtquery  *query = PG_GETARG_LTXTQUERY(1);
 
282
        ltree      *found,
 
283
                           *item;
 
284
 
 
285
        if (!array_iterator(la, ltxtq_exec, (void *) query, &found))
 
286
        {
 
287
                PG_FREE_IF_COPY(la, 0);
 
288
                PG_FREE_IF_COPY(query, 1);
 
289
                PG_RETURN_NULL();
 
290
        }
 
291
 
 
292
        item = (ltree *) palloc(VARSIZE(found));
 
293
        memcpy(item, found, VARSIZE(found));
 
294
 
 
295
        PG_FREE_IF_COPY(la, 0);
 
296
        PG_FREE_IF_COPY(query, 1);
 
297
        PG_RETURN_POINTER(item);
 
298
}
 
299
 
 
300
Datum
 
301
_lca(PG_FUNCTION_ARGS)
 
302
{
 
303
        ArrayType  *la = PG_GETARG_ARRAYTYPE_P(0);
 
304
        int                     num = ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la));
 
305
        ltree      *item = (ltree *) ARR_DATA_PTR(la);
 
306
        ltree     **a,
 
307
                           *res;
 
308
 
 
309
        if (ARR_NDIM(la) != 1)
 
310
                ereport(ERROR,
 
311
                                (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
 
312
                                 errmsg("array must be one-dimensional")));
 
313
        if (ARR_HASNULL(la))
 
314
                ereport(ERROR,
 
315
                                (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
 
316
                                 errmsg("array must not contain nulls")));
 
317
 
 
318
        a = (ltree **) palloc(sizeof(ltree *) * num);
 
319
        while (num > 0)
 
320
        {
 
321
                num--;
 
322
                a[num] = item;
 
323
                item = NEXTVAL(item);
 
324
        }
 
325
        res = lca_inner(a, ArrayGetNItems(ARR_NDIM(la), ARR_DIMS(la)));
 
326
        pfree(a);
 
327
 
 
328
        PG_FREE_IF_COPY(la, 0);
 
329
 
 
330
        if (res)
 
331
                PG_RETURN_POINTER(res);
 
332
        else
 
333
                PG_RETURN_NULL();
 
334
}