OSDN Git Service

Update copyrights to 2003.
[pg-rex/syncrep.git] / src / backend / parser / keywords.c
1 /*-------------------------------------------------------------------------
2  *
3  * keywords.c
4  *        lexical token lookup for reserved words in PostgreSQL
5  *
6  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
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.141 2003/08/04 02:40:01 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include <ctype.h>
18
19 #include "nodes/parsenodes.h"
20 #include "parser/keywords.h"
21 #include "parser/parse.h"
22
23 /* NB: This file is also used by pg_dump. */
24
25 /*
26  * List of (keyword-name, keyword-token-value) pairs.
27  *
28  * !!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         {"add", ADD},
38         {"after", AFTER},
39         {"aggregate", AGGREGATE},
40         {"all", ALL},
41         {"alter", ALTER},
42         {"analyse", ANALYSE},           /* British spelling */
43         {"analyze", ANALYZE},
44         {"and", AND},
45         {"any", ANY},
46         {"array", ARRAY},
47         {"as", AS},
48         {"asc", ASC},
49         {"assertion", ASSERTION},
50         {"assignment", ASSIGNMENT},
51         {"at", AT},
52         {"authorization", AUTHORIZATION},
53         {"backward", BACKWARD},
54         {"before", BEFORE},
55         {"begin", BEGIN_P},
56         {"between", BETWEEN},
57         {"bigint", BIGINT},
58         {"binary", BINARY},
59         {"bit", BIT},
60         {"boolean", BOOLEAN_P},
61         {"both", BOTH},
62         {"by", BY},
63         {"cache", CACHE},
64         {"called", CALLED},
65         {"cascade", CASCADE},
66         {"case", CASE},
67         {"cast", CAST},
68         {"chain", CHAIN},
69         {"char", CHAR_P},
70         {"character", CHARACTER},
71         {"characteristics", CHARACTERISTICS},
72         {"check", CHECK},
73         {"checkpoint", CHECKPOINT},
74         {"class", CLASS},
75         {"close", CLOSE},
76         {"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},
86         {"convert", CONVERT},
87         {"copy", COPY},
88         {"create", CREATE},
89         {"createdb", CREATEDB},
90         {"createuser", CREATEUSER},
91         {"cross", CROSS},
92         {"current_date", CURRENT_DATE},
93         {"current_time", CURRENT_TIME},
94         {"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         {"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},
112         {"desc", DESC},
113         {"distinct", DISTINCT},
114         {"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},
124         {"except", EXCEPT},
125         {"excluding", EXCLUDING},
126         {"exclusive", EXCLUSIVE},
127         {"execute", EXECUTE},
128         {"exists", EXISTS},
129         {"explain", EXPLAIN},
130         {"external", EXTERNAL},
131         {"extract", EXTRACT},
132         {"false", FALSE_P},
133         {"fetch", FETCH},
134         {"first", FIRST_P},
135         {"float", FLOAT_P},
136         {"for", FOR},
137         {"force", FORCE},
138         {"foreign", FOREIGN},
139         {"forward", FORWARD},
140         {"freeze", FREEZE},
141         {"from", FROM},
142         {"full", FULL},
143         {"function", FUNCTION},
144         {"global", GLOBAL},
145         {"grant", GRANT},
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},
155         {"in", IN_P},
156         {"including", INCLUDING},
157         {"increment", INCREMENT},
158         {"index", INDEX},
159         {"inherits", INHERITS},
160         {"initially", INITIALLY},
161         {"inner", INNER_P},
162         {"inout", INOUT},
163         {"input", INPUT_P},
164         {"insensitive", INSENSITIVE},
165         {"insert", INSERT},
166         {"instead", INSTEAD},
167         {"int", INT_P},
168         {"integer", INTEGER},
169         {"intersect", INTERSECT},
170         {"interval", INTERVAL},
171         {"into", INTO},
172         {"invoker", INVOKER},
173         {"is", IS},
174         {"isnull", ISNULL},
175         {"isolation", ISOLATION},
176         {"join", JOIN},
177         {"key", KEY},
178         {"lancompiler", LANCOMPILER},
179         {"language", LANGUAGE},
180         {"last", LAST_P},
181         {"leading", LEADING},
182         {"left", LEFT},
183         {"level", LEVEL},
184         {"like", LIKE},
185         {"limit", LIMIT},
186         {"listen", LISTEN},
187         {"load", LOAD},
188         {"local", LOCAL},
189         {"localtime", LOCALTIME},
190         {"localtimestamp", LOCALTIMESTAMP},
191         {"location", LOCATION},
192         {"lock", LOCK_P},
193         {"match", MATCH},
194         {"maxvalue", MAXVALUE},
195         {"minute", MINUTE_P},
196         {"minvalue", MINVALUE},
197         {"mode", MODE},
198         {"month", MONTH_P},
199         {"move", MOVE},
200         {"names", NAMES},
201         {"national", NATIONAL},
202         {"natural", NATURAL},
203         {"nchar", NCHAR},
204         {"new", NEW},
205         {"next", NEXT},
206         {"no", NO},
207         {"nocreatedb", NOCREATEDB},
208         {"nocreateuser", NOCREATEUSER},
209         {"none", NONE},
210         {"not", NOT},
211         {"nothing", NOTHING},
212         {"notify", NOTIFY},
213         {"notnull", NOTNULL},
214         {"null", NULL_P},
215         {"nullif", NULLIF},
216         {"numeric", NUMERIC},
217         {"of", OF},
218         {"off", OFF},
219         {"offset", OFFSET},
220         {"oids", OIDS},
221         {"old", OLD},
222         {"on", ON},
223         {"only", ONLY},
224         {"operator", OPERATOR},
225         {"option", OPTION},
226         {"or", OR},
227         {"order", ORDER},
228         {"out", OUT_P},
229         {"outer", OUTER_P},
230         {"overlaps", OVERLAPS},
231         {"overlay", OVERLAY},
232         {"owner", OWNER},
233         {"partial", PARTIAL},
234         {"password", PASSWORD},
235         {"path", PATH_P},
236         {"pendant", PENDANT},
237         {"placing", PLACING},
238         {"position", POSITION},
239         {"precision", PRECISION},
240         {"prepare", PREPARE},
241         {"preserve", PRESERVE},
242         {"primary", PRIMARY},
243         {"prior", PRIOR},
244         {"privileges", PRIVILEGES},
245         {"procedural", PROCEDURAL},
246         {"procedure", PROCEDURE},
247         {"read", READ},
248         {"real", REAL},
249         {"recheck", RECHECK},
250         {"references", REFERENCES},
251         {"reindex", REINDEX},
252         {"relative", RELATIVE_P},
253         {"rename", RENAME},
254         {"replace", REPLACE},
255         {"reset", RESET},
256         {"restart", RESTART},
257         {"restrict", RESTRICT},
258         {"returns", RETURNS},
259         {"revoke", REVOKE},
260         {"right", RIGHT},
261         {"rollback", ROLLBACK},
262         {"row", ROW},
263         {"rows", ROWS},
264         {"rule", RULE},
265         {"schema", SCHEMA},
266         {"scroll", SCROLL},
267         {"second", SECOND_P},
268         {"security", SECURITY},
269         {"select", SELECT},
270         {"sequence", SEQUENCE},
271         {"serializable", SERIALIZABLE},
272         {"session", SESSION},
273         {"session_user", SESSION_USER},
274         {"set", SET},
275         {"setof", SETOF},
276         {"share", SHARE},
277         {"show", SHOW},
278         {"similar", SIMILAR},
279         {"simple", SIMPLE},
280         {"smallint", SMALLINT},
281         {"some", SOME},
282         {"stable", STABLE},
283         {"start", START},
284         {"statement", STATEMENT},
285         {"statistics", STATISTICS},
286         {"stdin", STDIN},
287         {"stdout", STDOUT},
288         {"storage", STORAGE},
289         {"strict", STRICT_P},
290         {"substring", SUBSTRING},
291         {"sysid", SYSID},
292         {"table", TABLE},
293         {"temp", TEMP},
294         {"template", TEMPLATE},
295         {"temporary", TEMPORARY},
296         {"then", THEN},
297         {"time", TIME},
298         {"timestamp", TIMESTAMP},
299         {"to", TO},
300         {"toast", TOAST},
301         {"trailing", TRAILING},
302         {"transaction", TRANSACTION},
303         {"treat", TREAT},
304         {"trigger", TRIGGER},
305         {"trim", TRIM},
306         {"true", TRUE_P},
307         {"truncate", TRUNCATE},
308         {"trusted", TRUSTED},
309         {"type", TYPE_P},
310         {"unencrypted", UNENCRYPTED},
311         {"union", UNION},
312         {"unique", UNIQUE},
313         {"unknown", UNKNOWN},
314         {"unlisten", UNLISTEN},
315         {"until", UNTIL},
316         {"update", UPDATE},
317         {"usage", USAGE},
318         {"user", USER},
319         {"using", USING},
320         {"vacuum", VACUUM},
321         {"valid", VALID},
322         {"validator", VALIDATOR},
323         {"values", VALUES},
324         {"varchar", VARCHAR},
325         {"varying", VARYING},
326         {"verbose", VERBOSE},
327         {"version", VERSION},
328         {"view", VIEW},
329         {"volatile", VOLATILE},
330         {"when", WHEN},
331         {"where", WHERE},
332         {"with", WITH},
333         {"without", WITHOUT},
334         {"work", WORK},
335         {"write", WRITE},
336         {"year", YEAR_P},
337         {"zone", ZONE},
338 };
339
340 /*
341  * ScanKeywordLookup - see if a given word is a keyword
342  *
343  * Returns a pointer to the ScanKeyword table entry, or NULL if no match.
344  *
345  * The match is done case-insensitively.  Note that we deliberately use a
346  * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
347  * even if we are in a locale where tolower() would produce more or different
348  * translations.  This is to conform to the SQL99 spec, which says that
349  * keywords are to be matched in this way even though non-keyword identifiers
350  * receive a different case-normalization mapping.
351  */
352 const ScanKeyword *
353 ScanKeywordLookup(const char *text)
354 {
355         int                     len,
356                                 i;
357         char            word[NAMEDATALEN];
358         const ScanKeyword *low;
359         const ScanKeyword *high;
360
361         len = strlen(text);
362         /* We assume all keywords are shorter than NAMEDATALEN. */
363         if (len >= NAMEDATALEN)
364                 return NULL;
365
366         /*
367          * Apply an ASCII-only downcasing.      We must not use tolower() since it
368          * may produce the wrong translation in some locales (eg, Turkish),
369          * and we don't trust isupper() very much either.  In an ASCII-based
370          * encoding the tests against A and Z are sufficient, but we also
371          * check isupper() so that we will work correctly under EBCDIC.  The
372          * actual case conversion step should work for either ASCII or EBCDIC.
373          */
374         for (i = 0; i < len; i++)
375         {
376                 char            ch = text[i];
377
378                 if (ch >= 'A' && ch <= 'Z' && isupper((unsigned char) ch))
379                         ch += 'a' - 'A';
380                 word[i] = ch;
381         }
382         word[len] = '\0';
383
384         /*
385          * Now do a binary search using plain strcmp() comparison.
386          */
387         low = &ScanKeywords[0];
388         high = endof(ScanKeywords) - 1;
389         while (low <= high)
390         {
391                 const ScanKeyword *middle;
392                 int                     difference;
393
394                 middle = low + (high - low) / 2;
395                 difference = strcmp(middle->name, word);
396                 if (difference == 0)
397                         return middle;
398                 else if (difference < 0)
399                         low = middle + 1;
400                 else
401                         high = middle - 1;
402         }
403
404         return NULL;
405 }