~vcs-imports/mammoth-replicator/trunk

« back to all changes in this revision

Viewing changes to contrib/pgcrypto/pgcrypto.c

  • Committer: alvherre
  • Date: 2005-12-16 21:24:52 UTC
  • Revision ID: svn-v4:db760fc0-0f08-0410-9d63-cc6633f64896:trunk:1
Initial import of the REL8_0_3 sources from the Pgsql CVS repository.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * pgcrypto.c
 
3
 *              Various cryptographic stuff for PostgreSQL.
 
4
 *
 
5
 * Copyright (c) 2001 Marko Kreen
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
11
 * 1. Redistributions of source code must retain the above copyright
 
12
 *        notice, this list of conditions and the following disclaimer.
 
13
 * 2. Redistributions in binary form must reproduce the above copyright
 
14
 *        notice, this list of conditions and the following disclaimer in the
 
15
 *        documentation and/or other materials provided with the distribution.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
20
 * ARE DISCLAIMED.      IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
27
 * SUCH DAMAGE.
 
28
 *
 
29
 * $PostgreSQL: pgsql/contrib/pgcrypto/pgcrypto.c,v 1.16 2004-05-07 00:24:57 tgl Exp $
 
30
 */
 
31
 
 
32
#include "postgres.h"
 
33
 
 
34
#include <ctype.h>
 
35
 
 
36
#include "fmgr.h"
 
37
#include "parser/scansup.h"
 
38
 
 
39
#include "px.h"
 
40
#include "px-crypt.h"
 
41
#include "pgcrypto.h"
 
42
 
 
43
/* private stuff */
 
44
 
 
45
typedef int (*PFN) (const char *name, void **res);
 
46
static void *
 
47
                        find_provider(text *name, PFN pf, char *desc, int silent);
 
48
 
 
49
/* SQL function: hash(text, text) returns text */
 
50
PG_FUNCTION_INFO_V1(pg_digest);
 
51
 
 
52
Datum
 
53
pg_digest(PG_FUNCTION_ARGS)
 
54
{
 
55
        bytea      *arg;
 
56
        text       *name;
 
57
        unsigned        len,
 
58
                                hlen;
 
59
        PX_MD      *md;
 
60
        bytea      *res;
 
61
 
 
62
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
 
63
                PG_RETURN_NULL();
 
64
 
 
65
        name = PG_GETARG_TEXT_P(1);
 
66
 
 
67
        /* will give error if fails */
 
68
        md = find_provider(name, (PFN) px_find_digest, "Digest", 0);
 
69
 
 
70
        hlen = px_md_result_size(md);
 
71
 
 
72
        res = (text *) palloc(hlen + VARHDRSZ);
 
73
        VARATT_SIZEP(res) = hlen + VARHDRSZ;
 
74
 
 
75
        arg = PG_GETARG_BYTEA_P(0);
 
76
        len = VARSIZE(arg) - VARHDRSZ;
 
77
 
 
78
        px_md_update(md, VARDATA(arg), len);
 
79
        px_md_finish(md, VARDATA(res));
 
80
        px_md_free(md);
 
81
 
 
82
        PG_FREE_IF_COPY(arg, 0);
 
83
        PG_FREE_IF_COPY(name, 1);
 
84
 
 
85
        PG_RETURN_BYTEA_P(res);
 
86
}
 
87
 
 
88
/* check if given hash exists */
 
89
PG_FUNCTION_INFO_V1(pg_digest_exists);
 
90
 
 
91
Datum
 
92
pg_digest_exists(PG_FUNCTION_ARGS)
 
93
{
 
94
        text       *name;
 
95
        PX_MD      *res;
 
96
 
 
97
        if (PG_ARGISNULL(0))
 
98
                PG_RETURN_NULL();
 
99
 
 
100
        name = PG_GETARG_TEXT_P(0);
 
101
 
 
102
        res = find_provider(name, (PFN) px_find_digest, "Digest", 1);
 
103
 
 
104
        PG_FREE_IF_COPY(name, 0);
 
105
 
 
106
        if (res == NULL)
 
107
                PG_RETURN_BOOL(false);
 
108
 
 
109
        res->free(res);
 
110
 
 
111
        PG_RETURN_BOOL(true);
 
112
}
 
113
 
 
114
/* SQL function: hmac(data:text, key:text, type:text) */
 
115
PG_FUNCTION_INFO_V1(pg_hmac);
 
116
 
 
117
Datum
 
118
pg_hmac(PG_FUNCTION_ARGS)
 
119
{
 
120
        bytea      *arg;
 
121
        bytea      *key;
 
122
        text       *name;
 
123
        unsigned        len,
 
124
                                hlen,
 
125
                                klen;
 
126
        PX_HMAC    *h;
 
127
        bytea      *res;
 
128
 
 
129
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
 
130
                PG_RETURN_NULL();
 
131
 
 
132
        name = PG_GETARG_TEXT_P(2);
 
133
 
 
134
        /* will give error if fails */
 
135
        h = find_provider(name, (PFN) px_find_hmac, "HMAC", 0);
 
136
 
 
137
        hlen = px_hmac_result_size(h);
 
138
 
 
139
        res = (text *) palloc(hlen + VARHDRSZ);
 
140
        VARATT_SIZEP(res) = hlen + VARHDRSZ;
 
141
 
 
142
        arg = PG_GETARG_BYTEA_P(0);
 
143
        key = PG_GETARG_BYTEA_P(1);
 
144
        len = VARSIZE(arg) - VARHDRSZ;
 
145
        klen = VARSIZE(key) - VARHDRSZ;
 
146
 
 
147
        px_hmac_init(h, VARDATA(key), klen);
 
148
        px_hmac_update(h, VARDATA(arg), len);
 
149
        px_hmac_finish(h, VARDATA(res));
 
150
        px_hmac_free(h);
 
151
 
 
152
        PG_FREE_IF_COPY(arg, 0);
 
153
        PG_FREE_IF_COPY(key, 1);
 
154
        PG_FREE_IF_COPY(name, 2);
 
155
 
 
156
        PG_RETURN_BYTEA_P(res);
 
157
}
 
158
 
 
159
/* check if given hmac type exists */
 
160
PG_FUNCTION_INFO_V1(pg_hmac_exists);
 
161
 
 
162
Datum
 
163
pg_hmac_exists(PG_FUNCTION_ARGS)
 
164
{
 
165
        text       *name;
 
166
        PX_HMAC    *h;
 
167
 
 
168
        if (PG_ARGISNULL(0))
 
169
                PG_RETURN_NULL();
 
170
 
 
171
        name = PG_GETARG_TEXT_P(0);
 
172
 
 
173
        h = find_provider(name, (PFN) px_find_hmac, "HMAC", 1);
 
174
 
 
175
        PG_FREE_IF_COPY(name, 0);
 
176
 
 
177
        if (h != NULL)
 
178
        {
 
179
                px_hmac_free(h);
 
180
                PG_RETURN_BOOL(true);
 
181
        }
 
182
        PG_RETURN_BOOL(false);
 
183
}
 
184
 
 
185
 
 
186
/* SQL function: pg_gen_salt(text) returns text */
 
187
PG_FUNCTION_INFO_V1(pg_gen_salt);
 
188
 
 
189
Datum
 
190
pg_gen_salt(PG_FUNCTION_ARGS)
 
191
{
 
192
        text       *arg0;
 
193
        unsigned        len;
 
194
        text       *res;
 
195
        char            buf[PX_MAX_SALT_LEN + 1];
 
196
 
 
197
        if (PG_ARGISNULL(0))
 
198
                PG_RETURN_NULL();
 
199
 
 
200
        arg0 = PG_GETARG_TEXT_P(0);
 
201
 
 
202
        len = VARSIZE(arg0) - VARHDRSZ;
 
203
        len = len > PX_MAX_SALT_LEN ? PX_MAX_SALT_LEN : len;
 
204
        memcpy(buf, VARDATA(arg0), len);
 
205
        buf[len] = 0;
 
206
        len = px_gen_salt(buf, buf, 0);
 
207
        if (len == 0)
 
208
                ereport(ERROR,
 
209
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
210
                                 errmsg("no such crypt algorithm")));
 
211
 
 
212
        res = (text *) palloc(len + VARHDRSZ);
 
213
        VARATT_SIZEP(res) = len + VARHDRSZ;
 
214
        memcpy(VARDATA(res), buf, len);
 
215
 
 
216
        PG_FREE_IF_COPY(arg0, 0);
 
217
 
 
218
        PG_RETURN_TEXT_P(res);
 
219
}
 
220
 
 
221
/* SQL function: pg_gen_salt(text, int4) returns text */
 
222
PG_FUNCTION_INFO_V1(pg_gen_salt_rounds);
 
223
 
 
224
Datum
 
225
pg_gen_salt_rounds(PG_FUNCTION_ARGS)
 
226
{
 
227
        text       *arg0;
 
228
        int                     rounds;
 
229
        unsigned        len;
 
230
        text       *res;
 
231
        char            buf[PX_MAX_SALT_LEN + 1];
 
232
 
 
233
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
 
234
                PG_RETURN_NULL();
 
235
 
 
236
        arg0 = PG_GETARG_TEXT_P(0);
 
237
        rounds = PG_GETARG_INT32(1);
 
238
 
 
239
        len = VARSIZE(arg0) - VARHDRSZ;
 
240
        len = len > PX_MAX_SALT_LEN ? PX_MAX_SALT_LEN : len;
 
241
        memcpy(buf, VARDATA(arg0), len);
 
242
        buf[len] = 0;
 
243
        len = px_gen_salt(buf, buf, rounds);
 
244
        if (len == 0)
 
245
                ereport(ERROR,
 
246
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
247
                         errmsg("no such crypt algorithm or bad number of rounds")));
 
248
 
 
249
        res = (text *) palloc(len + VARHDRSZ);
 
250
        VARATT_SIZEP(res) = len + VARHDRSZ;
 
251
        memcpy(VARDATA(res), buf, len);
 
252
 
 
253
        PG_FREE_IF_COPY(arg0, 0);
 
254
 
 
255
        PG_RETURN_TEXT_P(res);
 
256
}
 
257
 
 
258
/* SQL function: pg_crypt(psw:text, salt:text) returns text */
 
259
PG_FUNCTION_INFO_V1(pg_crypt);
 
260
 
 
261
Datum
 
262
pg_crypt(PG_FUNCTION_ARGS)
 
263
{
 
264
        text       *arg0;
 
265
        text       *arg1;
 
266
        unsigned        len0,
 
267
                                len1,
 
268
                                clen;
 
269
        char       *buf0,
 
270
                           *buf1,
 
271
                           *cres,
 
272
                           *resbuf;
 
273
        text       *res;
 
274
 
 
275
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
 
276
                PG_RETURN_NULL();
 
277
 
 
278
        arg0 = PG_GETARG_TEXT_P(0);
 
279
        arg1 = PG_GETARG_TEXT_P(1);
 
280
        len0 = VARSIZE(arg0) - VARHDRSZ;
 
281
        len1 = VARSIZE(arg1) - VARHDRSZ;
 
282
 
 
283
        buf0 = palloc(len0 + 1);
 
284
        buf1 = palloc(len1 + 1);
 
285
 
 
286
        memcpy(buf0, VARDATA(arg0), len0);
 
287
        memcpy(buf1, VARDATA(arg1), len1);
 
288
 
 
289
        buf0[len0] = '\0';
 
290
        buf1[len1] = '\0';
 
291
 
 
292
        resbuf = palloc(PX_MAX_CRYPT);
 
293
 
 
294
        memset(resbuf, 0, PX_MAX_CRYPT);
 
295
 
 
296
        cres = px_crypt(buf0, buf1, resbuf, PX_MAX_CRYPT);
 
297
 
 
298
        pfree(buf0);
 
299
        pfree(buf1);
 
300
 
 
301
        if (cres == NULL)
 
302
                ereport(ERROR,
 
303
                                (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
 
304
                                 errmsg("crypt(3) returned NULL")));
 
305
 
 
306
        clen = strlen(cres);
 
307
 
 
308
        res = (text *) palloc(clen + VARHDRSZ);
 
309
        VARATT_SIZEP(res) = clen + VARHDRSZ;
 
310
        memcpy(VARDATA(res), cres, clen);
 
311
        pfree(resbuf);
 
312
 
 
313
        PG_FREE_IF_COPY(arg0, 0);
 
314
        PG_FREE_IF_COPY(arg1, 1);
 
315
 
 
316
        PG_RETURN_TEXT_P(res);
 
317
}
 
318
 
 
319
/* SQL function: pg_encrypt(text, text, text) returns text */
 
320
PG_FUNCTION_INFO_V1(pg_encrypt);
 
321
 
 
322
Datum
 
323
pg_encrypt(PG_FUNCTION_ARGS)
 
324
{
 
325
        int                     err;
 
326
        bytea      *data,
 
327
                           *key,
 
328
                           *res;
 
329
        text       *type;
 
330
        PX_Combo   *c;
 
331
        unsigned        dlen,
 
332
                                klen,
 
333
                                rlen;
 
334
 
 
335
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
 
336
                PG_RETURN_NULL();
 
337
 
 
338
        type = PG_GETARG_TEXT_P(2);
 
339
        c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
 
340
 
 
341
        data = PG_GETARG_BYTEA_P(0);
 
342
        key = PG_GETARG_BYTEA_P(1);
 
343
        dlen = VARSIZE(data) - VARHDRSZ;
 
344
        klen = VARSIZE(key) - VARHDRSZ;
 
345
 
 
346
        rlen = px_combo_encrypt_len(c, dlen);
 
347
        res = palloc(VARHDRSZ + rlen);
 
348
 
 
349
        err = px_combo_init(c, VARDATA(key), klen, NULL, 0);
 
350
        if (!err)
 
351
                err = px_combo_encrypt(c, VARDATA(data), dlen, VARDATA(res), &rlen);
 
352
        px_combo_free(c);
 
353
 
 
354
        PG_FREE_IF_COPY(data, 0);
 
355
        PG_FREE_IF_COPY(key, 1);
 
356
        PG_FREE_IF_COPY(type, 2);
 
357
 
 
358
        if (err)
 
359
        {
 
360
                pfree(res);
 
361
                ereport(ERROR,
 
362
                                (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
 
363
                                 errmsg("encrypt error: %d", err)));
 
364
        }
 
365
 
 
366
        VARATT_SIZEP(res) = VARHDRSZ + rlen;
 
367
        PG_RETURN_BYTEA_P(res);
 
368
}
 
369
 
 
370
/* SQL function: pg_decrypt(text, text, text) returns text */
 
371
PG_FUNCTION_INFO_V1(pg_decrypt);
 
372
 
 
373
Datum
 
374
pg_decrypt(PG_FUNCTION_ARGS)
 
375
{
 
376
        int                     err;
 
377
        bytea      *data,
 
378
                           *key,
 
379
                           *res;
 
380
        text       *type;
 
381
        PX_Combo   *c;
 
382
        unsigned        dlen,
 
383
                                klen,
 
384
                                rlen;
 
385
 
 
386
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1) || PG_ARGISNULL(2))
 
387
                PG_RETURN_NULL();
 
388
 
 
389
        type = PG_GETARG_TEXT_P(2);
 
390
        c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
 
391
 
 
392
        data = PG_GETARG_BYTEA_P(0);
 
393
        key = PG_GETARG_BYTEA_P(1);
 
394
        dlen = VARSIZE(data) - VARHDRSZ;
 
395
        klen = VARSIZE(key) - VARHDRSZ;
 
396
 
 
397
        rlen = px_combo_decrypt_len(c, dlen);
 
398
        res = palloc(VARHDRSZ + rlen);
 
399
 
 
400
        err = px_combo_init(c, VARDATA(key), klen, NULL, 0);
 
401
        if (!err)
 
402
                err = px_combo_decrypt(c, VARDATA(data), dlen, VARDATA(res), &rlen);
 
403
 
 
404
        px_combo_free(c);
 
405
 
 
406
        if (err)
 
407
                ereport(ERROR,
 
408
                                (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
 
409
                                 errmsg("decrypt error: %d", err)));
 
410
 
 
411
        VARATT_SIZEP(res) = VARHDRSZ + rlen;
 
412
 
 
413
        PG_FREE_IF_COPY(data, 0);
 
414
        PG_FREE_IF_COPY(key, 1);
 
415
        PG_FREE_IF_COPY(type, 2);
 
416
 
 
417
        PG_RETURN_BYTEA_P(res);
 
418
}
 
419
 
 
420
/* SQL function: pg_encrypt(text, text, text) returns text */
 
421
PG_FUNCTION_INFO_V1(pg_encrypt_iv);
 
422
 
 
423
Datum
 
424
pg_encrypt_iv(PG_FUNCTION_ARGS)
 
425
{
 
426
        int                     err;
 
427
        bytea      *data,
 
428
                           *key,
 
429
                           *iv,
 
430
                           *res;
 
431
        text       *type;
 
432
        PX_Combo   *c;
 
433
        unsigned        dlen,
 
434
                                klen,
 
435
                                ivlen,
 
436
                                rlen;
 
437
 
 
438
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1)
 
439
                || PG_ARGISNULL(2) || PG_ARGISNULL(3))
 
440
                PG_RETURN_NULL();
 
441
 
 
442
        type = PG_GETARG_TEXT_P(3);
 
443
        c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
 
444
 
 
445
        data = PG_GETARG_BYTEA_P(0);
 
446
        key = PG_GETARG_BYTEA_P(1);
 
447
        iv = PG_GETARG_BYTEA_P(2);
 
448
        dlen = VARSIZE(data) - VARHDRSZ;
 
449
        klen = VARSIZE(key) - VARHDRSZ;
 
450
        ivlen = VARSIZE(iv) - VARHDRSZ;
 
451
 
 
452
        rlen = px_combo_encrypt_len(c, dlen);
 
453
        res = palloc(VARHDRSZ + rlen);
 
454
 
 
455
        err = px_combo_init(c, VARDATA(key), klen, VARDATA(iv), ivlen);
 
456
        if (!err)
 
457
                px_combo_encrypt(c, VARDATA(data), dlen, VARDATA(res), &rlen);
 
458
 
 
459
        px_combo_free(c);
 
460
 
 
461
        if (err)
 
462
                ereport(ERROR,
 
463
                                (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
 
464
                                 errmsg("encrypt_iv error: %d", err)));
 
465
 
 
466
        VARATT_SIZEP(res) = VARHDRSZ + rlen;
 
467
 
 
468
        PG_FREE_IF_COPY(data, 0);
 
469
        PG_FREE_IF_COPY(key, 1);
 
470
        PG_FREE_IF_COPY(iv, 2);
 
471
        PG_FREE_IF_COPY(type, 3);
 
472
 
 
473
        PG_RETURN_BYTEA_P(res);
 
474
}
 
475
 
 
476
/* SQL function: pg_decrypt_iv(text, text, text) returns text */
 
477
PG_FUNCTION_INFO_V1(pg_decrypt_iv);
 
478
 
 
479
Datum
 
480
pg_decrypt_iv(PG_FUNCTION_ARGS)
 
481
{
 
482
        int                     err;
 
483
        bytea      *data,
 
484
                           *key,
 
485
                           *iv,
 
486
                           *res;
 
487
        text       *type;
 
488
        PX_Combo   *c;
 
489
        unsigned        dlen,
 
490
                                klen,
 
491
                                rlen,
 
492
                                ivlen;
 
493
 
 
494
        if (PG_ARGISNULL(0) || PG_ARGISNULL(1)
 
495
                || PG_ARGISNULL(2) || PG_ARGISNULL(3))
 
496
                PG_RETURN_NULL();
 
497
 
 
498
        type = PG_GETARG_TEXT_P(3);
 
499
        c = find_provider(type, (PFN) px_find_combo, "Cipher", 0);
 
500
 
 
501
        data = PG_GETARG_BYTEA_P(0);
 
502
        key = PG_GETARG_BYTEA_P(1);
 
503
        iv = PG_GETARG_BYTEA_P(2);
 
504
        dlen = VARSIZE(data) - VARHDRSZ;
 
505
        klen = VARSIZE(key) - VARHDRSZ;
 
506
        ivlen = VARSIZE(iv) - VARHDRSZ;
 
507
 
 
508
        rlen = px_combo_decrypt_len(c, dlen);
 
509
        res = palloc(VARHDRSZ + rlen);
 
510
 
 
511
        err = px_combo_init(c, VARDATA(key), klen, VARDATA(iv), ivlen);
 
512
        if (!err)
 
513
                px_combo_decrypt(c, VARDATA(data), dlen, VARDATA(res), &rlen);
 
514
 
 
515
        px_combo_free(c);
 
516
 
 
517
        if (err)
 
518
                ereport(ERROR,
 
519
                                (errcode(ERRCODE_EXTERNAL_ROUTINE_INVOCATION_EXCEPTION),
 
520
                                 errmsg("decrypt_iv error: %d", err)));
 
521
 
 
522
        VARATT_SIZEP(res) = VARHDRSZ + rlen;
 
523
 
 
524
        PG_FREE_IF_COPY(data, 0);
 
525
        PG_FREE_IF_COPY(key, 1);
 
526
        PG_FREE_IF_COPY(iv, 2);
 
527
        PG_FREE_IF_COPY(type, 3);
 
528
 
 
529
        PG_RETURN_BYTEA_P(res);
 
530
}
 
531
 
 
532
/* SQL function: pg_decrypt(text, text, text) returns text */
 
533
PG_FUNCTION_INFO_V1(pg_cipher_exists);
 
534
 
 
535
Datum
 
536
pg_cipher_exists(PG_FUNCTION_ARGS)
 
537
{
 
538
        text       *arg;
 
539
        PX_Combo   *c;
 
540
 
 
541
        if (PG_ARGISNULL(0))
 
542
                PG_RETURN_NULL();
 
543
 
 
544
        arg = PG_GETARG_TEXT_P(0);
 
545
 
 
546
        c = find_provider(arg, (PFN) px_find_combo, "Cipher", 1);
 
547
        if (c != NULL)
 
548
                px_combo_free(c);
 
549
 
 
550
        PG_RETURN_BOOL((c != NULL) ? true : false);
 
551
}
 
552
 
 
553
 
 
554
static void *
 
555
find_provider(text *name,
 
556
                          PFN provider_lookup,
 
557
                          char *desc, int silent)
 
558
{
 
559
        void       *res;
 
560
        char       *buf;
 
561
        int                     err;
 
562
 
 
563
        buf = downcase_truncate_identifier(VARDATA(name),
 
564
                                                                           VARSIZE(name) - VARHDRSZ,
 
565
                                                                           false);
 
566
 
 
567
        err = provider_lookup(buf, &res);
 
568
 
 
569
        if (err && !silent)
 
570
                ereport(ERROR,
 
571
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 
572
                                 errmsg("%s type does not exist: \"%s\"", desc, buf)));
 
573
 
 
574
        pfree(buf);
 
575
 
 
576
        return err ? NULL : res;
 
577
}