]> granicus.if.org Git - postgresql/blob - src/interfaces/ecpg/preproc/keywords.c
Synced parser and keyword list.
[postgresql] / src / interfaces / ecpg / preproc / keywords.c
1 /*-------------------------------------------------------------------------
2  *
3  * keywords.c
4  *        lexical token lookup for reserved words in PostgreSQL
5  *
6  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.80 2007/06/12 07:55:56 meskes Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres_fe.h"
16
17 #include <ctype.h>
18
19 #include "extern.h"
20 #include "preproc.h"
21
22
23 /*
24  * List of (keyword-name, keyword-token-value) pairs.
25  *
26  * !!WARNING!!: This list must be sorted, because binary
27  *               search is used to locate entries.
28  */
29 static ScanKeyword ScanKeywords[] = {
30         /* name, value */
31         {"abort", ABORT_P},
32         {"absolute", ABSOLUTE_P},
33         {"access", ACCESS},
34         {"action", ACTION},
35         {"add", ADD_P},
36         {"admin", ADMIN},
37         {"after", AFTER},
38         {"aggregate", AGGREGATE},
39         {"all", ALL},
40         {"also", ALSO},
41         {"alter", ALTER},
42         {"always", ALWAYS},
43         {"analyse", ANALYSE},           /* British spelling */
44         {"analyze", ANALYZE},
45         {"and", AND},
46         {"any", ANY},
47         {"array", ARRAY},
48         {"as", AS},
49         {"asc", ASC},
50         {"assertion", ASSERTION},
51         {"assignment", ASSIGNMENT},
52         {"asymmetric", ASYMMETRIC},
53         {"at", AT},
54         {"authorization", AUTHORIZATION},
55         {"backward", BACKWARD},
56         {"before", BEFORE},
57         {"begin", BEGIN_P},
58         {"between", BETWEEN},
59         {"bigint", BIGINT},
60         {"binary", BINARY},
61         {"bit", BIT},
62         {"boolean", BOOLEAN_P},
63         {"both", BOTH},
64         {"by", BY},
65         {"cache", CACHE},
66         {"called", CALLED},
67         {"cascade", CASCADE},
68         {"cascaded", CASCADED},
69         {"case", CASE},
70         {"cast", CAST},
71         {"chain", CHAIN},
72         {"char", CHAR_P},
73         {"character", CHARACTER},
74         {"characteristics", CHARACTERISTICS},
75         {"check", CHECK},
76         {"checkpoint", CHECKPOINT},
77         {"class", CLASS},
78         {"close", CLOSE},
79         {"cluster", CLUSTER},
80         {"coalesce", COALESCE},
81         {"collate", COLLATE},
82         {"column", COLUMN},
83         {"comment", COMMENT},
84         {"commit", COMMIT},
85         {"committed", COMMITTED},
86         {"concurrently", CONCURRENTLY},
87         {"concurrently", CONCURRENTLY},
88         {"connection", CONNECTION},
89         {"constraint", CONSTRAINT},
90         {"constraints", CONSTRAINTS},
91         {"content", CONTENT_P},
92         {"conversion", CONVERSION_P},
93         {"convert", CONVERT},
94         {"copy", COPY},
95         {"cost", COST},
96         {"create", CREATE},
97         {"createdb", CREATEDB},
98         {"createrole", CREATEROLE},
99         {"createuser", CREATEUSER},
100         {"cross", CROSS},
101         {"csv", CSV},
102         {"current", CURRENT_P},
103         {"current_date", CURRENT_DATE},
104         {"current_role", CURRENT_ROLE},
105         {"current_time", CURRENT_TIME},
106         {"current_timestamp", CURRENT_TIMESTAMP},
107         {"cursor", CURSOR},
108         {"cycle", CYCLE},
109         {"database", DATABASE},
110         {"day", DAY_P},
111         {"deallocate", DEALLOCATE},
112         {"dec", DEC},
113         {"decimal", DECIMAL_P},
114         {"declare", DECLARE},
115         {"default", DEFAULT},
116         {"defaults", DEFAULTS},
117         {"deferrable", DEFERRABLE},
118         {"deferred", DEFERRED},
119         {"definer", DEFINER},
120         {"delete", DELETE_P},
121         {"delimiter", DELIMITER},
122         {"delimiters", DELIMITERS},
123         {"desc", DESC},
124         {"disable", DISABLE_P},
125         {"discard", DISCARD},
126         {"distinct", DISTINCT},
127         {"do", DO},
128         {"document", DOCUMENT_P},
129         {"domain", DOMAIN_P},
130         {"double", DOUBLE_P},
131         {"drop", DROP},
132         {"each", EACH},
133         {"else", ELSE},
134         {"enable", ENABLE_P},
135         {"encoding", ENCODING},
136         {"encrypted", ENCRYPTED},
137         {"end", END_P},
138         {"enum", ENUM_P},
139         {"escape", ESCAPE},
140         {"except", EXCEPT},
141         {"excluding", EXCLUDING},
142         {"exclusive", EXCLUSIVE},
143         {"execute", EXECUTE},
144         {"exists", EXISTS},
145         {"explain", EXPLAIN},
146         {"external", EXTERNAL},
147         {"extract", EXTRACT},
148         {"false", FALSE_P},
149         {"family", FAMILY},
150         {"fetch", FETCH},
151         {"first", FIRST_P},
152         {"float", FLOAT_P},
153         {"for", FOR},
154         {"force", FORCE},
155         {"foreign", FOREIGN},
156         {"forward", FORWARD},
157         {"freeze", FREEZE},
158         {"from", FROM},
159         {"full", FULL},
160         {"function", FUNCTION},
161         {"get", GET},
162         {"global", GLOBAL},
163         {"grant", GRANT},
164         {"granted", GRANTED},
165         {"greatest", GREATEST},
166         {"group", GROUP_P},
167         {"handler", HANDLER},
168         {"having", HAVING},
169         {"header", HEADER_P},
170         {"hold", HOLD},
171         {"hour", HOUR_P},
172         {"if", IF_P},
173         {"ilike", ILIKE},
174         {"immediate", IMMEDIATE},
175         {"immutable", IMMUTABLE},
176         {"implicit", IMPLICIT_P},
177         {"in", IN_P},
178         {"including", INCLUDING},
179         {"increment", INCREMENT},
180         {"index", INDEX},
181         {"indexes", INDEXES},
182         {"inherit", INHERIT},
183         {"inherits", INHERITS},
184         {"initially", INITIALLY},
185         {"inner", INNER_P},
186         {"inout", INOUT},
187         {"input", INPUT_P},
188         {"insensitive", INSENSITIVE},
189         {"insert", INSERT},
190         {"instead", INSTEAD},
191         {"int", INT_P},
192         {"integer", INTEGER},
193         {"intersect", INTERSECT},
194         {"interval", INTERVAL},
195         {"into", INTO},
196         {"invoker", INVOKER},
197         {"is", IS},
198         {"isnull", ISNULL},
199         {"isolation", ISOLATION},
200         {"join", JOIN},
201         {"key", KEY},
202         {"lancompiler", LANCOMPILER},
203         {"language", LANGUAGE},
204         {"large", LARGE_P},
205         {"last", LAST_P},
206         {"leading", LEADING},
207         {"least", LEAST},
208         {"left", LEFT},
209         {"level", LEVEL},
210         {"like", LIKE},
211         {"limit", LIMIT},
212         {"listen", LISTEN},
213         {"load", LOAD},
214         {"local", LOCAL},
215         {"location", LOCATION},
216         {"lock", LOCK_P},
217         {"login", LOGIN_P},
218         {"match", MATCH},
219         {"maxvalue", MAXVALUE},
220         {"minute", MINUTE_P},
221         {"minvalue", MINVALUE},
222         {"mode", MODE},
223         {"month", MONTH_P},
224         {"move", MOVE},
225         {"name", NAME_P},
226         {"names", NAMES},
227         {"national", NATIONAL},
228         {"natural", NATURAL},
229         {"nchar", NCHAR},
230         {"new", NEW},
231         {"next", NEXT},
232         {"no", NO},
233         {"nocreatedb", NOCREATEDB},
234         {"nocreaterole", NOCREATEROLE},
235         {"nocreateuser", NOCREATEUSER},
236         {"noinherit", NOINHERIT},
237         {"nologin", NOLOGIN_P},
238         {"none", NONE},
239         {"nosuperuser", NOSUPERUSER},
240         {"not", NOT},
241         {"nothing", NOTHING},
242         {"notify", NOTIFY},
243         {"notnull", NOTNULL},
244         {"nowait", NOWAIT},
245         {"null", NULL_P},
246         {"nullif", NULLIF},
247         {"nulls", NULLS_P},
248         {"numeric", NUMERIC},
249         {"object", OBJECT_P},
250         {"of", OF},
251         {"off", OFF},
252         {"offset", OFFSET},
253         {"oids", OIDS},
254         {"old", OLD},
255         {"on", ON},
256         {"only", ONLY},
257         {"operator", OPERATOR},
258         {"option", OPTION},
259         {"or", OR},
260         {"order", ORDER},
261         {"out", OUT_P},
262         {"outer", OUTER_P},
263         {"overlaps", OVERLAPS},
264         {"owned", OWNED},
265         {"owner", OWNER},
266         {"partial", PARTIAL},
267         {"password", PASSWORD},
268         {"placing", PLACING},
269         {"plans", PLANS},
270         {"position", POSITION},
271         {"precision", PRECISION},
272         {"prepare", PREPARE},
273         {"prepared", PREPARED},
274         {"preserve", PRESERVE},
275         {"primary", PRIMARY},
276         {"prior", PRIOR},
277         {"privileges", PRIVILEGES},
278         {"procedural", PROCEDURAL},
279         {"procedure", PROCEDURE},
280         {"quote", QUOTE},
281         {"read", READ},
282         {"real", REAL},
283         {"reassign", REASSIGN},
284         {"recheck", RECHECK},
285         {"references", REFERENCES},
286         {"reindex", REINDEX},
287         {"relative", RELATIVE_P},
288         {"release", RELEASE},
289         {"rename", RENAME},
290         {"repeatable", REPEATABLE},
291         {"replace", REPLACE},
292         {"replica", REPLICA},
293         {"reset", RESET},
294         {"restart", RESTART},
295         {"restrict", RESTRICT},
296         {"returning", RETURNING},
297         {"returns", RETURNS},
298         {"revoke", REVOKE},
299         {"right", RIGHT},
300         {"role", ROLE},
301         {"rollback", ROLLBACK},
302         {"row", ROW},
303         {"rows", ROWS},
304         {"rule", RULE},
305         {"savepoint", SAVEPOINT},
306         {"schema", SCHEMA},
307         {"scroll", SCROLL},
308         {"second", SECOND_P},
309         {"security", SECURITY},
310         {"select", SELECT},
311         {"sequence", SEQUENCE},
312         {"serializable", SERIALIZABLE},
313         {"session", SESSION},
314         {"session_user", SESSION_USER},
315         {"set", SET},
316         {"setof", SETOF},
317         {"share", SHARE},
318         {"show", SHOW},
319         {"similar", SIMILAR},
320         {"simple", SIMPLE},
321         {"smallint", SMALLINT},
322         {"some", SOME},
323         {"stable", STABLE},
324         {"standalone", STANDALONE_P},
325         {"start", START},
326         {"statement", STATEMENT},
327         {"statistics", STATISTICS},
328         {"stdin", STDIN},
329         {"stdout", STDOUT},
330         {"storage", STORAGE},
331         {"strict", STRICT_P},
332         {"strip", STRIP_P},
333         {"substring", SUBSTRING},
334         {"superuser", SUPERUSER_P},
335         {"symmetric", SYMMETRIC},
336         {"sysid", SYSID},
337         {"system", SYSTEM_P},
338         {"table", TABLE},
339         {"tablespace", TABLESPACE},
340         {"temp", TEMP},
341         {"template", TEMPLATE},
342         {"temporary", TEMPORARY},
343         {"then", THEN},
344         {"time", TIME},
345         {"timestamp", TIMESTAMP},
346         {"to", TO},
347         {"trailing", TRAILING},
348         {"transaction", TRANSACTION},
349         {"treat", TREAT},
350         {"trigger", TRIGGER},
351         {"trim", TRIM},
352         {"true", TRUE_P},
353         {"truncate", TRUNCATE},
354         {"trusted", TRUSTED},
355         {"type", TYPE_P},
356         {"uncommitted", UNCOMMITTED},
357         {"unencrypted", UNENCRYPTED},
358         {"union", UNION},
359         {"unique", UNIQUE},
360         {"unknown", UNKNOWN},
361         {"unlisten", UNLISTEN},
362         {"until", UNTIL},
363         {"update", UPDATE},
364         {"user", USER},
365         {"using", USING},
366         {"vacuum", VACUUM},
367         {"valid", VALID},
368         {"validator", VALIDATOR},
369         {"value", VALUE_P},
370         {"values", VALUES},
371         {"varchar", VARCHAR},
372         {"varying", VARYING},
373         {"verbose", VERBOSE},
374         {"version", VERSION_P},
375         {"view", VIEW},
376         {"volatile", VOLATILE},
377         {"when", WHEN},
378         {"where", WHERE},
379         {"whitespace", WHITESPACE_P},
380         {"with", WITH},
381         {"without", WITHOUT},
382         {"work", WORK},
383         {"write", WRITE},
384         {"xml", XML_P},
385         {"xmlattributes", XMLATTRIBUTES},
386         {"xmlconcat", XMLCONCAT},
387         {"xmlelement", XMLELEMENT},
388         {"xmlforest", XMLFOREST},
389         {"xmlparse", XMLPARSE},
390         {"xmlpi", XMLPI},
391         {"xmlroot", XMLROOT},
392         {"xmlserialize", XMLSERIALIZE},
393         {"year", YEAR_P},
394         {"yes", YES_P},
395         {"zone", ZONE},
396 };
397
398 /*
399  * ScanKeywordLookup - see if a given word is a keyword
400  *
401  * Returns a pointer to the ScanKeyword table entry, or NULL if no match.
402  *
403  * The match is done case-insensitively.  Note that we deliberately use a
404  * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
405  * even if we are in a locale where tolower() would produce more or different
406  * translations.  This is to conform to the SQL99 spec, which says that
407  * keywords are to be matched in this way even though non-keyword identifiers
408  * receive a different case-normalization mapping.
409  */
410 ScanKeyword *
411 ScanKeywordLookup(char *text)
412 {
413         int                     len,
414                                 i;
415         char            word[NAMEDATALEN];
416         ScanKeyword *low;
417         ScanKeyword *high;
418
419         len = strlen(text);
420         /* We assume all keywords are shorter than NAMEDATALEN. */
421         if (len >= NAMEDATALEN)
422                 return NULL;
423
424         /*
425          * Apply an ASCII-only downcasing.      We must not use tolower() since it may
426          * produce the wrong translation in some locales (eg, Turkish).
427          */
428         for (i = 0; i < len; i++)
429         {
430                 char            ch = text[i];
431
432                 if (ch >= 'A' && ch <= 'Z')
433                         ch += 'a' - 'A';
434                 word[i] = ch;
435         }
436         word[len] = '\0';
437
438         /*
439          * Now do a binary search using plain strcmp() comparison.
440          */
441         low = &ScanKeywords[0];
442         high = endof(ScanKeywords) - 1;
443         while (low <= high)
444         {
445                 ScanKeyword *middle;
446                 int                     difference;
447
448                 middle = low + (high - low) / 2;
449                 difference = strcmp(middle->name, word);
450                 if (difference == 0)
451                         return middle;
452                 else if (difference < 0)
453                         low = middle + 1;
454                 else
455                         high = middle - 1;
456         }
457
458         return NULL;
459 }