1
/*-------------------------------------------------------------------------
4
* lexical token lookup for reserved words in PostgreSQL
6
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
7
* Portions Copyright (c) 1994, Regents of the University of California
11
* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.68 2004-12-31 22:03:48 pgsql Exp $
13
*-------------------------------------------------------------------------
15
#include "postgres_fe.h"
24
* List of (keyword-name, keyword-token-value) pairs.
26
* !!WARNING!!: This list must be sorted, because binary
27
* search is used to locate entries.
29
static ScanKeyword ScanKeywords[] = {
32
{"absolute", ABSOLUTE_P},
37
{"aggregate", AGGREGATE},
41
{"analyse", ANALYSE}, /* British spelling */
48
{"assertion", ASSERTION},
49
{"assignment", ASSIGNMENT},
51
{"authorization", AUTHORIZATION},
52
{"backward", BACKWARD},
59
{"boolean", BOOLEAN_P},
69
{"character", CHARACTER},
70
{"characteristics", CHARACTERISTICS},
72
{"checkpoint", CHECKPOINT},
76
{"coalesce", COALESCE},
81
{"committed", COMMITTED},
82
{"constraint", CONSTRAINT},
83
{"constraints", CONSTRAINTS},
84
{"conversion", CONVERSION_P},
88
{"createdb", CREATEDB},
89
{"createuser", CREATEUSER},
92
{"current_date", CURRENT_DATE},
93
{"current_time", CURRENT_TIME},
94
{"current_timestamp", CURRENT_TIMESTAMP},
95
{"current_user", CURRENT_USER},
98
{"database", DATABASE},
100
{"deallocate", DEALLOCATE},
102
{"decimal", DECIMAL_P},
103
{"declare", DECLARE},
104
{"default", DEFAULT},
105
{"defaults", DEFAULTS},
106
{"deferrable", DEFERRABLE},
107
{"deferred", DEFERRED},
108
{"definer", DEFINER},
109
{"delete", DELETE_P},
110
{"delimiter", DELIMITER},
111
{"delimiters", DELIMITERS},
113
{"distinct", DISTINCT},
115
{"domain", DOMAIN_P},
116
{"double", DOUBLE_P},
120
{"encoding", ENCODING},
121
{"encrypted", ENCRYPTED},
125
{"excluding", EXCLUDING},
126
{"exclusive", EXCLUSIVE},
127
{"execute", EXECUTE},
129
{"explain", EXPLAIN},
130
{"external", EXTERNAL},
131
{"extract", EXTRACT},
138
{"foreign", FOREIGN},
139
{"forward", FORWARD},
143
{"function", FUNCTION},
148
{"handler", HANDLER},
153
{"immediate", IMMEDIATE},
154
{"immutable", IMMUTABLE},
155
{"implicit", IMPLICIT_P},
157
{"including", INCLUDING},
158
{"increment", INCREMENT},
160
{"inherits", INHERITS},
161
{"initially", INITIALLY},
165
{"insensitive", INSENSITIVE},
167
{"instead", INSTEAD},
169
{"integer", INTEGER},
170
{"intersect", INTERSECT},
171
{"interval", INTERVAL},
173
{"invoker", INVOKER},
176
{"isolation", ISOLATION},
179
{"lancompiler", LANCOMPILER},
180
{"language", LANGUAGE},
183
{"leading", LEADING},
191
{"location", LOCATION},
194
{"maxvalue", MAXVALUE},
195
{"minute", MINUTE_P},
196
{"minvalue", MINVALUE},
201
{"national", NATIONAL},
202
{"natural", NATURAL},
207
{"nocreatedb", NOCREATEDB},
208
{"nocreateuser", NOCREATEUSER},
211
{"nothing", NOTHING},
213
{"notnull", NOTNULL},
217
{"numeric", NUMERIC},
218
{"object", OBJECT_P},
226
{"operator", OPERATOR},
232
{"overlaps", OVERLAPS},
234
{"partial", PARTIAL},
235
{"password", PASSWORD},
236
{"position", POSITION},
237
{"precision", PRECISION},
238
{"prepare", PREPARE},
239
{"preserve", PRESERVE},
240
{"primary", PRIMARY},
242
{"privileges", PRIVILEGES},
243
{"procedural", PROCEDURAL},
244
{"procedure", PROCEDURE},
248
{"recheck", RECHECK},
249
{"references", REFERENCES},
250
{"reindex", REINDEX},
251
{"relative", RELATIVE_P},
252
{"release", RELEASE},
254
{"repeatable", REPEATABLE},
255
{"replace", REPLACE},
257
{"restart", RESTART},
258
{"restrict", RESTRICT},
259
{"returns", RETURNS},
262
{"rollback", ROLLBACK},
266
{"savepoint", SAVEPOINT},
269
{"second", SECOND_P},
270
{"security", SECURITY},
272
{"sequence", SEQUENCE},
273
{"serializable", SERIALIZABLE},
274
{"session", SESSION},
275
{"session_user", SESSION_USER},
280
{"similar", SIMILAR},
282
{"smallint", SMALLINT},
286
{"statement", STATEMENT},
287
{"statistics", STATISTICS},
290
{"storage", STORAGE},
291
{"strict", STRICT_P},
292
{"substring", SUBSTRING},
295
{"tablespace", TABLESPACE},
297
{"template", TEMPLATE},
298
{"temporary", TEMPORARY},
301
{"timestamp", TIMESTAMP},
304
{"trailing", TRAILING},
305
{"transaction", TRANSACTION},
307
{"trigger", TRIGGER},
310
{"truncate", TRUNCATE},
311
{"trusted", TRUSTED},
313
{"uncommitted", UNCOMMITTED},
314
{"unencrypted", UNENCRYPTED},
317
{"unknown", UNKNOWN},
318
{"unlisten", UNLISTEN},
327
{"varchar", VARCHAR},
328
{"varying", VARYING},
329
{"verbose", VERBOSE},
331
{"volatile", VOLATILE},
335
{"without", WITHOUT},
343
* ScanKeywordLookup - see if a given word is a keyword
345
* Returns a pointer to the ScanKeyword table entry, or NULL if no match.
347
* The match is done case-insensitively. Note that we deliberately use a
348
* dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
349
* even if we are in a locale where tolower() would produce more or different
350
* translations. This is to conform to the SQL99 spec, which says that
351
* keywords are to be matched in this way even though non-keyword identifiers
352
* receive a different case-normalization mapping.
355
ScanKeywordLookup(char *text)
359
char word[NAMEDATALEN];
364
/* We assume all keywords are shorter than NAMEDATALEN. */
365
if (len >= NAMEDATALEN)
369
* Apply an ASCII-only downcasing. We must not use tolower()
370
* since it may produce the wrong translation in some locales (eg,
373
for (i = 0; i < len; i++)
377
if (ch >= 'A' && ch <= 'Z')
384
* Now do a binary search using plain strcmp() comparison.
386
low = &ScanKeywords[0];
387
high = endof(ScanKeywords) - 1;
393
middle = low + (high - low) / 2;
394
difference = strcmp(middle->name, word);
397
else if (difference < 0)