keywords.c 8.87 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * keywords.c
4
 *	  lexical token lookup for reserved words in PostgreSQL
5
 *
Bruce Momjian's avatar
Bruce Momjian committed
6
 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
7
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/backend/parser/keywords.c,v 1.119 2002/07/11 07:39:26 ishii Exp $
12 13 14
 *
 *-------------------------------------------------------------------------
 */
Bruce Momjian's avatar
Bruce Momjian committed
15
#include "postgres.h"
16

17 18
#include <ctype.h>

19 20
#include "nodes/parsenodes.h"
#include "parser/keywords.h"
21
#include "parser/parse.h"
22 23 24 25 26

/*
 * List of (keyword-name, keyword-token-value) pairs.
 *
 * !!WARNING!!: This list must be sorted, because binary
27
 *		 search is used to locate entries.
28
 */
29
static const ScanKeyword ScanKeywords[] = {
30
	/* name, value */
31
	{"abort", ABORT_TRANS},
32
	{"absolute", ABSOLUTE},
33
	{"access", ACCESS},
34
	{"action", ACTION},
35 36 37 38 39
	{"add", ADD},
	{"after", AFTER},
	{"aggregate", AGGREGATE},
	{"all", ALL},
	{"alter", ALTER},
40
	{"analyse", ANALYSE},		/* British spelling */
41 42
	{"analyze", ANALYZE},
	{"and", AND},
43
	{"any", ANY},
44 45
	{"as", AS},
	{"asc", ASC},
46
	{"assertion", ASSERTION},
47
	{"assignment", ASSIGNMENT},
48
	{"at", AT},
49
	{"authorization", AUTHORIZATION},
50 51 52 53
	{"backward", BACKWARD},
	{"before", BEFORE},
	{"begin", BEGIN_TRANS},
	{"between", BETWEEN},
54
	{"bigint", BIGINT},
55
	{"binary", BINARY},
56
	{"bit", BIT},
57
	{"boolean", BOOLEAN},
58 59
	{"both", BOTH},
	{"by", BY},
60
	{"cache", CACHE},
61
	{"called", CALLED},
62
	{"cascade", CASCADE},
63
	{"case", CASE},
64
	{"cast", CAST},
65
	{"chain", CHAIN},
Jan Wieck's avatar
Jan Wieck committed
66
	{"char", CHAR_P},
67
	{"character", CHARACTER},
68
	{"characteristics", CHARACTERISTICS},
69
	{"check", CHECK},
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
70
	{"checkpoint", CHECKPOINT},
71 72
	{"close", CLOSE},
	{"cluster", CLUSTER},
73
	{"coalesce", COALESCE},
74
	{"collate", COLLATE},
75
	{"column", COLUMN},
76
	{"comment", COMMENT},
77
	{"commit", COMMIT},
78
	{"committed", COMMITTED},
79
	{"constraint", CONSTRAINT},
80
	{"constraints", CONSTRAINTS},
81
	{"conversion", CONVERSION_P},
82 83
	{"copy", COPY},
	{"create", CREATE},
84 85
	{"createdb", CREATEDB},
	{"createuser", CREATEUSER},
86
	{"cross", CROSS},
87 88 89
	{"current_date", CURRENT_DATE},
	{"current_time", CURRENT_TIME},
	{"current_timestamp", CURRENT_TIMESTAMP},
90
	{"current_user", CURRENT_USER},
91
	{"cursor", CURSOR},
92
	{"cycle", CYCLE},
93
	{"database", DATABASE},
94
	{"day", DAY_P},
95
	{"dec", DEC},
96
	{"decimal", DECIMAL},
97 98
	{"declare", DECLARE},
	{"default", DEFAULT},
99 100
	{"deferrable", DEFERRABLE},
	{"deferred", DEFERRED},
101
	{"definer", DEFINER},
Jan Wieck's avatar
Jan Wieck committed
102
	{"delete", DELETE_P},
103
	{"delimiter", DELIMITER},
104 105 106 107
	{"delimiters", DELIMITERS},
	{"desc", DESC},
	{"distinct", DISTINCT},
	{"do", DO},
108
	{"domain", DOMAIN_P},
109
	{"double", DOUBLE},
110
	{"drop", DROP},
111
	{"each", EACH},
112
	{"else", ELSE},
113
	{"encoding", ENCODING},
114
	{"encrypted", ENCRYPTED},
115
	{"end", END_TRANS},
116
	{"escape", ESCAPE},
Bruce Momjian's avatar
Hi!  
Bruce Momjian committed
117
	{"except", EXCEPT},
118
	{"exclusive", EXCLUSIVE},
119 120 121
	{"execute", EXECUTE},
	{"exists", EXISTS},
	{"explain", EXPLAIN},
122
	{"external", EXTERNAL},
123
	{"extract", EXTRACT},
124
	{"false", FALSE_P},
125
	{"fetch", FETCH},
Jan Wieck's avatar
Jan Wieck committed
126
	{"float", FLOAT_P},
127
	{"for", FOR},
Hiroshi Inoue's avatar
Hiroshi Inoue committed
128
	{"force", FORCE},
129
	{"foreign", FOREIGN},
130
	{"forward", FORWARD},
131
	{"freeze", FREEZE},
132 133 134
	{"from", FROM},
	{"full", FULL},
	{"function", FUNCTION},
135
	{"get", GET},
136
	{"global", GLOBAL},
137
	{"grant", GRANT},
Jan Wieck's avatar
Jan Wieck committed
138
	{"group", GROUP_P},
139
	{"handler", HANDLER},
140
	{"having", HAVING},
141
	{"hour", HOUR_P},
142
	{"ilike", ILIKE},
143
	{"immediate", IMMEDIATE},
144 145
	{"immutable", IMMUTABLE},
	{"implicit", IMPLICIT},
Jan Wieck's avatar
Jan Wieck committed
146
	{"in", IN_P},
147
	{"increment", INCREMENT},
148 149
	{"index", INDEX},
	{"inherits", INHERITS},
150
	{"initially", INITIALLY},
151
	{"inner", INNER_P},
152
	{"inout", INOUT},
153
	{"input", INPUT},
154
	{"insensitive", INSENSITIVE},
Bruce Momjian's avatar
Bruce Momjian committed
155
	{"insert", INSERT},
156
	{"instead", INSTEAD},
157 158
	{"int", INT},
	{"integer", INTEGER},
Bruce Momjian's avatar
Hi!  
Bruce Momjian committed
159
	{"intersect", INTERSECT},
160 161
	{"interval", INTERVAL},
	{"into", INTO},
162
	{"invoker", INVOKER},
163 164
	{"is", IS},
	{"isnull", ISNULL},
165
	{"isolation", ISOLATION},
166
	{"join", JOIN},
167
	{"key", KEY},
168
	{"lancompiler", LANCOMPILER},
169 170 171
	{"language", LANGUAGE},
	{"leading", LEADING},
	{"left", LEFT},
172
	{"level", LEVEL},
173
	{"like", LIKE},
174
	{"limit", LIMIT},
175 176 177
	{"listen", LISTEN},
	{"load", LOAD},
	{"local", LOCAL},
178 179
	{"localtime", LOCALTIME},
	{"localtimestamp", LOCALTIMESTAMP},
180
	{"location", LOCATION},
181
	{"lock", LOCK_P},
182
	{"match", MATCH},
183
	{"maxvalue", MAXVALUE},
184
	{"minute", MINUTE_P},
185
	{"minvalue", MINVALUE},
186
	{"mode", MODE},
187
	{"month", MONTH_P},
188
	{"move", MOVE},
189
	{"names", NAMES},
190
	{"national", NATIONAL},
191
	{"natural", NATURAL},
192
	{"nchar", NCHAR},
193
	{"new", NEW},
194
	{"next", NEXT},
195
	{"no", NO},
196 197
	{"nocreatedb", NOCREATEDB},
	{"nocreateuser", NOCREATEUSER},
198 199 200 201 202
	{"none", NONE},
	{"not", NOT},
	{"nothing", NOTHING},
	{"notify", NOTIFY},
	{"notnull", NOTNULL},
203
	{"null", NULL_P},
204
	{"nullif", NULLIF},
205
	{"numeric", NUMERIC},
206
	{"of", OF},
207
	{"off", OFF},
208
	{"offset", OFFSET},
209
	{"oids", OIDS},
210
	{"old", OLD},
211
	{"on", ON},
212
	{"only", ONLY},
213 214 215 216
	{"operator", OPERATOR},
	{"option", OPTION},
	{"or", OR},
	{"order", ORDER},
Jan Wieck's avatar
Jan Wieck committed
217
	{"out", OUT_P},
218
	{"outer", OUTER_P},
219
	{"overlaps", OVERLAPS},
220
	{"overlay", OVERLAY},
221
	{"owner", OWNER},
222
	{"partial", PARTIAL},
223
	{"password", PASSWORD},
224
	{"path", PATH_P},
225
	{"pendant", PENDANT},
226
	{"placing", PLACING},
227
	{"position", POSITION},
228
	{"precision", PRECISION},
229
	{"primary", PRIMARY},
230
	{"prior", PRIOR},
231
	{"privileges", PRIVILEGES},
232
	{"procedural", PROCEDURAL},
233
	{"procedure", PROCEDURE},
234
	{"read", READ},
235
	{"real", REAL},
236
	{"references", REFERENCES},
Hiroshi Inoue's avatar
Hiroshi Inoue committed
237
	{"reindex", REINDEX},
238
	{"relative", RELATIVE},
239
	{"rename", RENAME},
240
	{"replace", REPLACE},
241
	{"reset", RESET},
242
	{"restrict", RESTRICT},
243 244 245 246
	{"returns", RETURNS},
	{"revoke", REVOKE},
	{"right", RIGHT},
	{"rollback", ROLLBACK},
247
	{"row", ROW},
248
	{"rule", RULE},
249
	{"schema", SCHEMA},
250
	{"scroll", SCROLL},
251
	{"second", SECOND_P},
252
	{"security", SECURITY},
253 254
	{"select", SELECT},
	{"sequence", SEQUENCE},
255
	{"serializable", SERIALIZABLE},
256
	{"session", SESSION},
257
	{"session_user", SESSION_USER},
258 259
	{"set", SET},
	{"setof", SETOF},
260
	{"share", SHARE},
261
	{"show", SHOW},
262
	{"similar", SIMILAR},
263
	{"simple", SIMPLE},
264
	{"smallint", SMALLINT},
265
	{"some", SOME},
266
	{"stable", STABLE},
267
	{"start", START},
268
	{"statement", STATEMENT},
269
	{"statistics", STATISTICS},
270 271
	{"stdin", STDIN},
	{"stdout", STDOUT},
272
	{"storage", STORAGE},
273
	{"strict", STRICT},
274
	{"substring", SUBSTRING},
275
	{"sysid", SYSID},
276
	{"table", TABLE},
277
	{"temp", TEMP},
278
	{"template", TEMPLATE},
Bruce Momjian's avatar
Bruce Momjian committed
279
	{"temporary", TEMPORARY},
280
	{"then", THEN},
281
	{"time", TIME},
282
	{"timestamp", TIMESTAMP},
283
	{"to", TO},
Jan Wieck's avatar
TOAST  
Jan Wieck committed
284
	{"toast", TOAST},
285
	{"trailing", TRAILING},
286
	{"transaction", TRANSACTION},
287
	{"treat", TREAT},
288 289
	{"trigger", TRIGGER},
	{"trim", TRIM},
290
	{"true", TRUE_P},
291
	{"truncate", TRUNCATE},
292
	{"trusted", TRUSTED},
293
	{"type", TYPE_P},
294
	{"unencrypted", UNENCRYPTED},
295 296
	{"union", UNION},
	{"unique", UNIQUE},
297
	{"unknown", UNKNOWN},
298
	{"unlisten", UNLISTEN},
299
	{"until", UNTIL},
300
	{"update", UPDATE},
301
	{"usage", USAGE},
302
	{"user", USER},
303 304
	{"using", USING},
	{"vacuum", VACUUM},
305
	{"valid", VALID},
306
	{"validator", VALIDATOR},
307
	{"values", VALUES},
308
	{"varchar", VARCHAR},
309
	{"varying", VARYING},
310 311 312
	{"verbose", VERBOSE},
	{"version", VERSION},
	{"view", VIEW},
313
	{"volatile", VOLATILE},
314
	{"when", WHEN},
315 316
	{"where", WHERE},
	{"with", WITH},
317
	{"without", WITHOUT},
318
	{"work", WORK},
319
	{"write", WRITE},
320
	{"year", YEAR_P},
321
	{"zone", ZONE},
322 323
};

324 325 326 327 328 329 330 331 332 333 334 335
/*
 * ScanKeywordLookup - see if a given word is a keyword
 *
 * Returns a pointer to the ScanKeyword table entry, or NULL if no match.
 *
 * The match is done case-insensitively.  Note that we deliberately use a
 * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
 * even if we are in a locale where tolower() would produce more or different
 * translations.  This is to conform to the SQL99 spec, which says that
 * keywords are to be matched in this way even though non-keyword identifiers
 * receive a different case-normalization mapping.
 */
336 337
const ScanKeyword *
ScanKeywordLookup(const char *text)
338
{
339 340 341
	int			len,
				i;
	char		word[NAMEDATALEN];
342 343
	const ScanKeyword *low;
	const ScanKeyword *high;
344 345 346 347 348 349 350

	len = strlen(text);
	/* We assume all keywords are shorter than NAMEDATALEN. */
	if (len >= NAMEDATALEN)
		return NULL;

	/*
351 352
	 * Apply an ASCII-only downcasing.	We must not use tolower() since it
	 * may produce the wrong translation in some locales (eg, Turkish),
353
	 * and we don't trust isupper() very much either.  In an ASCII-based
354 355 356
	 * encoding the tests against A and Z are sufficient, but we also
	 * check isupper() so that we will work correctly under EBCDIC.  The
	 * actual case conversion step should work for either ASCII or EBCDIC.
357 358 359
	 */
	for (i = 0; i < len; i++)
	{
360
		char		ch = text[i];
361

362 363 364 365 366 367 368 369 370 371 372
		if (ch >= 'A' && ch <= 'Z' && isupper((unsigned char) ch))
			ch += 'a' - 'A';
		word[i] = ch;
	}
	word[len] = '\0';

	/*
	 * Now do a binary search using plain strcmp() comparison.
	 */
	low = &ScanKeywords[0];
	high = endof(ScanKeywords) - 1;
373 374
	while (low <= high)
	{
375
		const ScanKeyword *middle;
376 377
		int			difference;

378
		middle = low + (high - low) / 2;
379
		difference = strcmp(middle->name, word);
380
		if (difference == 0)
381
			return middle;
382 383 384 385 386 387
		else if (difference < 0)
			low = middle + 1;
		else
			high = middle - 1;
	}

388
	return NULL;
389
}