Skip to content

Commit 6206a88

Browse files
committed
Add SQL99 CONVERT() function.
1 parent 34f03b1 commit 6206a88

File tree

15 files changed

+1237
-211
lines changed

15 files changed

+1237
-211
lines changed

doc/src/sgml/func.sgml

Lines changed: 413 additions & 1 deletion
Large diffs are not rendered by default.

src/backend/catalog/namespace.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
1515
* IDENTIFICATION
16-
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.27 2002/07/29 23:46:35 tgl Exp $
16+
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.28 2002/08/06 05:40:44 ishii Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -1238,6 +1238,43 @@ PopSpecialNamespace(Oid namespaceId)
12381238
namespaceSearchPathValid = false;
12391239
}
12401240

1241+
/*
1242+
* FindConversionByName - find a conversion by possibly qualified name
1243+
*/
1244+
Oid FindConversionByName(List *name)
1245+
{
1246+
char *conversion_name;
1247+
Oid namespaceId;
1248+
Oid conoid;
1249+
List *lptr;
1250+
1251+
/* Convert list of names to a name and namespace */
1252+
namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
1253+
1254+
if (length(name) > 1)
1255+
{
1256+
/* Check we have usage rights in target namespace */
1257+
if (pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
1258+
return InvalidOid;
1259+
1260+
return FindConversion(conversion_name, namespaceId);
1261+
}
1262+
1263+
recomputeNamespacePath();
1264+
1265+
foreach(lptr, namespaceSearchPath)
1266+
{
1267+
Oid namespaceId = (Oid) lfirsti(lptr);
1268+
1269+
conoid = FindConversion(conversion_name, namespaceId);
1270+
if (OidIsValid(conoid))
1271+
return conoid;
1272+
}
1273+
1274+
/* Not found in path */
1275+
return InvalidOid;
1276+
}
1277+
12411278
/*
12421279
* FindDefaultConversionProc - find default encoding cnnversion proc
12431280
*/

src/backend/catalog/pg_conversion.c

Lines changed: 74 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.4 2002/08/05 03:29:16 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/catalog/pg_conversion.c,v 1.5 2002/08/06 05:40:45 ishii Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -221,7 +221,7 @@ RemoveConversionById(Oid conversionOid)
221221
if (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
222222
simple_heap_delete(rel, &tuple->t_self);
223223
else
224-
elog(ERROR, "Conversion %u does not exist", conversionOid);
224+
elog(ERROR, "conversion %u does not exist", conversionOid);
225225
heap_endscan(scan);
226226
heap_close(rel, RowExclusiveLock);
227227
}
@@ -233,47 +233,6 @@ RemoveConversionById(Oid conversionOid)
233233
* If found, returns the procedure's oid, otherwise InvalidOid.
234234
* ---------------
235235
*/
236-
#ifdef NOT_USED
237-
Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
238-
{
239-
Relation rel;
240-
HeapScanDesc scan;
241-
ScanKeyData scanKeyData;
242-
HeapTuple tuple;
243-
Form_pg_conversion body;
244-
Oid proc = InvalidOid;
245-
246-
/* Check we have usage rights in target namespace */
247-
if (pg_namespace_aclcheck(name_space, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
248-
return InvalidOid;
249-
250-
ScanKeyEntryInitialize(&scanKeyData,
251-
0,
252-
Anum_pg_conversion_connamespace,
253-
F_OIDEQ,
254-
ObjectIdGetDatum(name_space));
255-
256-
rel = heap_openr(ConversionRelationName, AccessShareLock);
257-
scan = heap_beginscan(rel, SnapshotNow,
258-
1, &scanKeyData);
259-
260-
while (HeapTupleIsValid(tuple = heap_getnext(scan, ForwardScanDirection)))
261-
{
262-
body = (Form_pg_conversion)GETSTRUCT(tuple);
263-
if (body->conforencoding == for_encoding &&
264-
body->contoencoding == to_encoding &&
265-
body->condefault == TRUE)
266-
{
267-
proc = body->conproc;
268-
break;
269-
}
270-
}
271-
heap_endscan(scan);
272-
heap_close(rel, AccessShareLock);
273-
return proc;
274-
}
275-
#endif
276-
277236
Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
278237
{
279238
CatCList *catlist;
@@ -309,34 +268,27 @@ Oid FindDefaultConversion(Oid name_space, int4 for_encoding, int4 to_encoding)
309268
/* ----------------
310269
* FindConversionByName
311270
*
312-
* Find conversion proc by possibly qualified conversion name.
271+
* Find conversion by namespace and conversion name.
272+
* Returns conversion oid.
313273
* ---------------
314274
*/
315-
Oid FindConversionByName(List *name)
275+
Oid FindConversion(const char *conname, Oid connamespace)
316276
{
317277
HeapTuple tuple;
318-
char *conversion_name;
319-
Oid namespaceId;
320278
Oid procoid;
279+
Oid conoid;
321280
AclResult aclresult;
322281

323-
/* Convert list of names to a name and namespace */
324-
namespaceId = QualifiedNameGetCreationNamespace(name, &conversion_name);
325-
326-
/* Check we have usage rights in target namespace */
327-
if (pg_namespace_aclcheck(namespaceId, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
328-
return InvalidOid;
329-
330-
/* search pg_conversion by namespaceId and conversion name */
282+
/* search pg_conversion by connamespace and conversion name */
331283
tuple = SearchSysCache(CONNAMESP,
332-
PointerGetDatum(conversion_name),
333-
ObjectIdGetDatum(namespaceId),
284+
PointerGetDatum(conname),
285+
ObjectIdGetDatum(connamespace),
334286
0,0);
335287

336288
if (!HeapTupleIsValid(tuple))
337289
return InvalidOid;
338-
339290
procoid = ((Form_pg_conversion)GETSTRUCT(tuple))->conproc;
291+
conoid = HeapTupleGetOid(tuple);
340292

341293
ReleaseSysCache(tuple);
342294

@@ -345,6 +297,69 @@ Oid FindConversionByName(List *name)
345297
if (aclresult != ACLCHECK_OK)
346298
return InvalidOid;
347299

348-
return procoid;
300+
return conoid;
349301
}
350302

303+
/*
304+
* Execute SQL99's CONVERT function.
305+
*
306+
* CONVERT <left paren> <character value expression>
307+
* USING <form-of-use conversion name> <right paren>
308+
*
309+
* TEXT convert3(TEXT string, OID conversion_oid);
310+
*/
311+
Datum
312+
pg_convert3(PG_FUNCTION_ARGS)
313+
{
314+
text *string = PG_GETARG_TEXT_P(0);
315+
Oid convoid = PG_GETARG_OID(1);
316+
HeapTuple tuple;
317+
Form_pg_conversion body;
318+
text *retval;
319+
unsigned char *str;
320+
unsigned char *result;
321+
int len;
322+
323+
if (!OidIsValid(convoid))
324+
elog(ERROR, "Conversion does not exist");
325+
326+
/* make sure that source string is null terminated */
327+
len = VARSIZE(string) - VARHDRSZ;
328+
str = palloc(len + 1);
329+
memcpy(str, VARDATA(string), len);
330+
*(str + len) = '\0';
331+
332+
tuple = SearchSysCache(CONOID,
333+
ObjectIdGetDatum(convoid),
334+
0,0,0);
335+
if (!HeapTupleIsValid(tuple))
336+
elog(ERROR, "Conversion %u search from syscache failed", convoid);
337+
338+
result = palloc(len * 4 + 1);
339+
340+
body = (Form_pg_conversion)GETSTRUCT(tuple);
341+
OidFunctionCall5(body->conproc,
342+
Int32GetDatum(body->conforencoding),
343+
Int32GetDatum(body->contoencoding),
344+
CStringGetDatum(str),
345+
CStringGetDatum(result),
346+
Int32GetDatum(len));
347+
348+
ReleaseSysCache(tuple);
349+
350+
/* build text data type structre. we cannot use textin() here,
351+
since textin assumes that input string encoding is same as
352+
database encoding. */
353+
len = strlen(result) + VARHDRSZ;
354+
retval = palloc(len);
355+
VARATT_SIZEP(retval) = len;
356+
memcpy(VARDATA(retval), result, len - VARHDRSZ);
357+
358+
pfree(result);
359+
pfree(str);
360+
361+
/* free memory if allocated by the toaster */
362+
PG_FREE_IF_COPY(string, 0);
363+
364+
PG_RETURN_TEXT_P(retval);
365+
}

src/backend/parser/gram.y

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*
1212
*
1313
* IDENTIFICATION
14-
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.356 2002/08/05 02:30:50 tgl Exp $
14+
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.357 2002/08/06 05:40:45 ishii Exp $
1515
*
1616
* HISTORY
1717
* AUTHOR DATE MAJOR EVENT
@@ -53,6 +53,7 @@
5353
#include "access/htup.h"
5454
#include "catalog/index.h"
5555
#include "catalog/namespace.h"
56+
#include "catalog/pg_conversion.h"
5657
#include "catalog/pg_type.h"
5758
#include "nodes/makefuncs.h"
5859
#include "nodes/params.h"
@@ -216,7 +217,8 @@ static void doNegateFloat(Value *v);
216217
insert_target_list, def_list, opt_indirection,
217218
group_clause, TriggerFuncArgs, select_limit,
218219
opt_select_limit, opclass_item_list, trans_options,
219-
TableFuncElementList, OptTableFuncElementList
220+
TableFuncElementList, OptTableFuncElementList,
221+
convert_args
220222

221223
%type <range> into_clause, OptTempTableName
222224

@@ -232,7 +234,7 @@ static void doNegateFloat(Value *v);
232234
%type <jtype> join_type
233235

234236
%type <list> extract_list, overlay_list, position_list
235-
%type <list> substr_list, trim_list
237+
%type <list> substr_list, trim_list, convert_list
236238
%type <ival> opt_interval
237239
%type <node> overlay_placing, substr_from, substr_for
238240

@@ -329,7 +331,7 @@ static void doNegateFloat(Value *v);
329331
CACHE, CALLED, CASCADE, CASE, CAST, CHAIN, CHAR_P,
330332
CHARACTER, CHARACTERISTICS, CHECK, CHECKPOINT, CLASS, CLOSE,
331333
CLUSTER, COALESCE, COLLATE, COLUMN, COMMENT, COMMIT,
332-
COMMITTED, CONSTRAINT, CONSTRAINTS, CONVERSION_P, COPY, CREATE, CREATEDB,
334+
COMMITTED, CONSTRAINT, CONSTRAINTS, CONVERSION_P, CONVERT, COPY, CREATE, CREATEDB,
333335
CREATEUSER, CROSS, CURRENT_DATE, CURRENT_TIME,
334336
CURRENT_TIMESTAMP, CURRENT_USER, CURSOR, CYCLE,
335337

@@ -6253,6 +6255,15 @@ c_expr: columnref { $$ = (Node *) $1; }
62536255
n->agg_distinct = FALSE;
62546256
$$ = (Node *)n;
62556257
}
6258+
| CONVERT '(' convert_list ')'
6259+
{
6260+
FuncCall *n = makeNode(FuncCall);
6261+
n->funcname = SystemFuncName("convert");
6262+
n->args = $3;
6263+
n->agg_star = FALSE;
6264+
n->agg_distinct = FALSE;
6265+
$$ = (Node *)n;
6266+
}
62566267
| select_with_parens %prec UMINUS
62576268
{
62586269
SubLink *n = makeNode(SubLink);
@@ -6418,6 +6429,48 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); }
64186429
| expr_list { $$ = $1; }
64196430
;
64206431

6432+
/* CONVERT() arguments. We accept followings:
6433+
* SQL99 syntax
6434+
* o CONVERT(TEXT string USING conversion_name)
6435+
*
6436+
* Function calls
6437+
* o CONVERT(TEXT string, NAME src_encoding_name, NAME dest_encoding_name)
6438+
* o CONVERT(TEXT string, NAME encoding_name)
6439+
*/
6440+
convert_list:
6441+
a_expr USING any_name
6442+
{
6443+
Oid oid = FindConversionByName($3);
6444+
Const *convoid = makeNode(Const);
6445+
6446+
if (!OidIsValid(oid))
6447+
{
6448+
elog(ERROR, "Conversion \"%s\" does not exist",
6449+
NameListToString($3));
6450+
}
6451+
6452+
convoid->consttype = OIDOID;
6453+
convoid->constlen = sizeof(Oid);
6454+
convoid->constvalue = oid;
6455+
convoid->constisnull = FALSE;
6456+
convoid->constbyval = TRUE;
6457+
convoid->constisset = FALSE;
6458+
convoid->constiscast = FALSE;
6459+
$$ = makeList2($1, convoid);
6460+
}
6461+
| convert_args
6462+
{
6463+
$$ = $1;
6464+
}
6465+
| /*EMPTY*/
6466+
{ $$ = NIL; }
6467+
;
6468+
6469+
convert_args: a_expr { $$ = makeList1($1); }
6470+
| convert_args ',' a_expr { $$ = lappend($1, $3); }
6471+
;
6472+
6473+
64216474
in_expr: select_with_parens
64226475
{
64236476
SubLink *n = makeNode(SubLink);

src/backend/parser/keywords.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.123 2002/07/29 22:14:11 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.124 2002/08/06 05:40:45 ishii Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -80,6 +80,7 @@ static const ScanKeyword ScanKeywords[] = {
8080
{"constraint", CONSTRAINT},
8181
{"constraints", CONSTRAINTS},
8282
{"conversion", CONVERSION_P},
83+
{"convert", CONVERT},
8384
{"copy", COPY},
8485
{"create", CREATE},
8586
{"createdb", CREATEDB},

src/backend/utils/mb/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# Makefile for utils/mb
55
#
66
# IDENTIFICATION
7-
# $Header: /cvsroot/pgsql/src/backend/utils/mb/Makefile,v 1.18 2002/07/18 02:02:30 ishii Exp $
7+
# $Header: /cvsroot/pgsql/src/backend/utils/mb/Makefile,v 1.19 2002/08/06 05:40:45 ishii Exp $
88
#
99
#-------------------------------------------------------------------------
1010

@@ -24,7 +24,7 @@ clean distclean maintainer-clean:
2424

2525
SUBSYS.o: $(OBJS)
2626
@for dir in $(DIRS); do $(MAKE) -C $$dir all || exit; done
27-
$(LD) $(LDREL) $(LDOUT) SUBSYS.o $(OBJS)
27+
$(LD) $(LDREL) $(LDOUT) $@ $^
2828

2929
depend dep:
3030
$(CC) -MM $(CFLAGS) *.c >depend

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy