keywords.c 9.03 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-2003, 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
 *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.145 2004/02/21 00:34:52 tgl 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
/* NB: This file is also used by pg_dump. */

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

344 345 346 347 348 349 350 351 352 353 354 355
/*
 * 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.
 */
356 357
const ScanKeyword *
ScanKeywordLookup(const char *text)
358
{
359 360 361
	int			len,
				i;
	char		word[NAMEDATALEN];
362 363
	const ScanKeyword *low;
	const ScanKeyword *high;
364 365 366 367 368 369 370

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

	/*
371
	 * Apply an ASCII-only downcasing.	We must not use tolower() since it
372
	 * may produce the wrong translation in some locales (eg, Turkish).
373 374 375
	 */
	for (i = 0; i < len; i++)
	{
376
		char		ch = text[i];
377

378
		if (ch >= 'A' && ch <= 'Z')
379 380 381 382 383 384 385 386 387 388
			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;
389 390
	while (low <= high)
	{
391
		const ScanKeyword *middle;
392 393
		int			difference;

394
		middle = low + (high - low) / 2;
395
		difference = strcmp(middle->name, word);
396
		if (difference == 0)
397
			return middle;
398 399 400 401 402 403
		else if (difference < 0)
			low = middle + 1;
		else
			high = middle - 1;
	}

404
	return NULL;
405
}