8
8
* Portions Copyright (c) 1994, Regents of the University of California
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.22 2001/11/12 21:04:46 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/format_type.c,v 1.23 2001/11/19 19:51:20 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
27
27
#include "mb/pg_wchar.h"
28
28
#endif
29
29
30
+
30
31
#define MASK (b ) (1 << (b))
31
32
32
33
#define MAX_INT32_LEN 11
33
34
#define _textin (str ) DirectFunctionCall1(textin, CStringGetDatum(str))
34
35
35
-
36
- static char * format_type_internal (Oid type_oid ,int32 typemod ,bool allow_invalid );
37
-
38
-
39
- static char *
40
- psnprintf (size_t len ,const char * fmt ,...)
41
- {
42
- va_list ap ;
43
- char * buf ;
44
-
45
- buf = palloc (len );
46
-
47
- va_start (ap ,fmt );
48
- vsnprintf (buf ,len ,fmt ,ap );
49
- va_end (ap );
50
-
51
- return buf ;
52
- }
36
+ static char * format_type_internal (Oid type_oid ,int32 typemod ,
37
+ bool typemod_given ,bool allow_invalid );
38
+ static char * psnprintf (size_t len ,const char * fmt , ...)
39
+ /* This lets gcc check the format string for consistency. */
40
+ __attribute__((format (printf ,2 ,3 )));
53
41
54
42
55
43
/*
@@ -61,11 +49,22 @@ psnprintf(size_t len, const char *fmt,...)
61
49
* a standard type. Otherwise you just get pg_type.typname back,
62
50
* double quoted if it contains funny characters.
63
51
*
64
- * If typemod is null (in the SQL sense) then you won't get any
65
- * "..(x)" type qualifiers. The result is not technically correct,
66
- * because the various types interpret missing type modifiers
67
- * differently, but it can be used as a convenient way to format
68
- * system catalogs, e.g., pg_aggregate, in psql.
52
+ * If typemod is NULL then we are formatting a type name in a context where
53
+ * no typemod is available, eg a function argument or result type. This
54
+ * yields a slightly different result from specifying typemod = -1 in some
55
+ * cases. Given typemod = -1 we feel compelled to produce an output that
56
+ * the parser will interpret as having typemod -1, so that pg_dump will
57
+ * produce CREATE TABLE commands that recreate the original state. But
58
+ * given NULL typemod, we assume that the parser's interpretation of
59
+ * typemod doesn't matter, and so we are willing to output a slightly
60
+ * "prettier" representation of the same type. For example, type = bpchar
61
+ * and typemod = NULL gets you "character", whereas typemod = -1 gets you
62
+ * "bpchar" --- the former will be interpreted as character(1) by the
63
+ * parser, which does not yield typemod -1.
64
+ *
65
+ * XXX encoding a meaning in typemod = NULL is ugly; it'd have been
66
+ * cleaner to make two functions of one and two arguments respectively.
67
+ * Not worth changing it now, however.
69
68
*/
70
69
Datum
71
70
format_type (PG_FUNCTION_ARGS )
@@ -74,17 +73,21 @@ format_type(PG_FUNCTION_ARGS)
74
73
int32 typemod ;
75
74
char * result ;
76
75
76
+ /* Since this function is not strict, we must test for null args */
77
77
if (PG_ARGISNULL (0 ))
78
78
PG_RETURN_NULL ();
79
79
80
80
type_oid = PG_GETARG_OID (0 );
81
81
82
- if (!PG_ARGISNULL (1 ))
83
- typemod = PG_GETARG_INT32 (1 );
82
+ if (PG_ARGISNULL (1 ))
83
+ {
84
+ result = format_type_internal (type_oid ,-1 , false, true);
85
+ }
84
86
else
85
- typemod = -1 ;/* default typmod */
86
-
87
- result = format_type_internal (type_oid ,typemod , true);
87
+ {
88
+ typemod = PG_GETARG_INT32 (1 );
89
+ result = format_type_internal (type_oid ,typemod , true, true);
90
+ }
88
91
89
92
PG_RETURN_DATUM (_textin (result ));
90
93
}
@@ -98,7 +101,7 @@ format_type(PG_FUNCTION_ARGS)
98
101
char *
99
102
format_type_be (Oid type_oid )
100
103
{
101
- return format_type_internal (type_oid ,-1 , false);
104
+ return format_type_internal (type_oid ,-1 , false, false );
102
105
}
103
106
104
107
/*
@@ -107,15 +110,16 @@ format_type_be(Oid type_oid)
107
110
char *
108
111
format_type_with_typemod (Oid type_oid ,int32 typemod )
109
112
{
110
- return format_type_internal (type_oid ,typemod , false);
113
+ return format_type_internal (type_oid ,typemod ,true, false);
111
114
}
112
115
113
116
114
117
115
118
static char *
116
- format_type_internal (Oid type_oid ,int32 typemod ,bool allow_invalid )
119
+ format_type_internal (Oid type_oid ,int32 typemod ,
120
+ bool typemod_given ,bool allow_invalid )
117
121
{
118
- bool with_typemod = (typemod >=0 );
122
+ bool with_typemod = typemod_given && (typemod >=0 );
119
123
HeapTuple tuple ;
120
124
Oid array_base_type ;
121
125
int16 typlen ;
@@ -140,7 +144,7 @@ format_type_internal(Oid type_oid, int32 typemod, bool allow_invalid)
140
144
141
145
array_base_type = ((Form_pg_type )GETSTRUCT (tuple ))-> typelem ;
142
146
typlen = ((Form_pg_type )GETSTRUCT (tuple ))-> typlen ;
143
- if (array_base_type != 0 && typlen < 0 )
147
+ if (array_base_type != InvalidOid && typlen < 0 )
144
148
{
145
149
/* Switch our attention to the array element type */
146
150
ReleaseSysCache (tuple );
@@ -167,15 +171,17 @@ format_type_internal(Oid type_oid, int32 typemod, bool allow_invalid)
167
171
if (with_typemod )
168
172
buf = psnprintf (5 + MAX_INT32_LEN + 1 ,"bit(%d)" ,
169
173
(int )typemod );
170
- else
174
+ else if ( typemod_given )
171
175
{
172
176
/*
173
- * bit withno typmod is not the same as BIT, which means
177
+ * bit with typmod -1 is not the same as BIT, which means
174
178
* BIT(1) per SQL spec. Report it as the quoted typename
175
179
* so that parser will not assign a bogus typmod.
176
180
*/
177
181
buf = pstrdup ("\"bit\"" );
178
182
}
183
+ else
184
+ buf = pstrdup ("bit" );
179
185
break ;
180
186
181
187
case BOOLOID :
@@ -186,15 +192,17 @@ format_type_internal(Oid type_oid, int32 typemod, bool allow_invalid)
186
192
if (with_typemod )
187
193
buf = psnprintf (11 + MAX_INT32_LEN + 1 ,"character(%d)" ,
188
194
(int ) (typemod - VARHDRSZ ));
189
- else
195
+ else if ( typemod_given )
190
196
{
191
197
/*
192
- * bpchar withno typmod is not the same as CHARACTER,
198
+ * bpchar with typmod -1 is not the same as CHARACTER,
193
199
* which means CHARACTER(1) per SQL spec. Report it as
194
200
* bpchar so that parser will not assign a bogus typmod.
195
201
*/
196
202
buf = pstrdup ("bpchar" );
197
203
}
204
+ else
205
+ buf = pstrdup ("character" );
198
206
break ;
199
207
200
208
case CHAROID :
@@ -352,6 +360,10 @@ format_type_internal(Oid type_oid, int32 typemod, bool allow_invalid)
352
360
353
361
default :
354
362
name = NameStr (((Form_pg_type )GETSTRUCT (tuple ))-> typname );
363
+ /*
364
+ * Double-quote the name if it's not a standard identifier.
365
+ * Note this is *necessary* for ruleutils.c's use.
366
+ */
355
367
if (strspn (name ,"abcdefghijklmnopqrstuvwxyz0123456789_" )!= strlen (name )
356
368
|| isdigit ((unsignedchar )name [0 ]))
357
369
buf = psnprintf (strlen (name )+ 3 ,"\"%s\"" ,name );
@@ -456,13 +468,15 @@ oidvectortypes(PG_FUNCTION_ARGS)
456
468
457
469
for (num = 0 ;num < numargs ;num ++ )
458
470
{
459
- char * typename = format_type_internal (oidArray [num ],-1 , true);
471
+ char * typename = format_type_internal (oidArray [num ],-1 ,
472
+ false, true);
473
+ size_t slen = strlen (typename );
460
474
461
- if (left < strlen ( typename ) + 2 )
475
+ if (left < ( slen + 2 ) )
462
476
{
463
- total += strlen ( typename ) + 2 ;
477
+ total += slen + 2 ;
464
478
result = repalloc (result ,total );
465
- left += strlen ( typename ) + 2 ;
479
+ left += slen + 2 ;
466
480
}
467
481
468
482
if (num > 0 )
@@ -471,8 +485,25 @@ oidvectortypes(PG_FUNCTION_ARGS)
471
485
left -= 2 ;
472
486
}
473
487
strcat (result ,typename );
474
- left -= strlen ( typename ) ;
488
+ left -= slen ;
475
489
}
476
490
477
491
PG_RETURN_DATUM (_textin (result ));
478
492
}
493
+
494
+
495
+ /* snprintf into a palloc'd string */
496
+ static char *
497
+ psnprintf (size_t len ,const char * fmt , ...)
498
+ {
499
+ va_list ap ;
500
+ char * buf ;
501
+
502
+ buf = palloc (len );
503
+
504
+ va_start (ap ,fmt );
505
+ vsnprintf (buf ,len ,fmt ,ap );
506
+ va_end (ap );
507
+
508
+ return buf ;
509
+ }