]> granicus.if.org Git - postgresql/blob - src/backend/parser/keywords.c
Add DOMAIN check constraints.
[postgresql] / 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-2002, 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.131 2002/11/15 02:50:08 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_TRANS},
34         {"absolute", ABSOLUTE},
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         {"as", AS},
47         {"asc", ASC},
48         {"assertion", ASSERTION},
49         {"assignment", ASSIGNMENT},
50         {"at", AT},
51         {"authorization", AUTHORIZATION},
52         {"backward", BACKWARD},
53         {"before", BEFORE},
54         {"begin", BEGIN_TRANS},
55         {"between", BETWEEN},
56         {"bigint", BIGINT},
57         {"binary", BINARY},
58         {"bit", BIT},
59         {"boolean", BOOLEAN},
60         {"both", BOTH},
61         {"by", BY},
62         {"cache", CACHE},
63         {"called", CALLED},
64         {"cascade", CASCADE},
65         {"case", CASE},
66         {"cast", CAST},
67         {"chain", CHAIN},
68         {"char", CHAR_P},
69         {"character", CHARACTER},
70         {"characteristics", CHARACTERISTICS},
71         {"check", CHECK},
72         {"checkpoint", CHECKPOINT},
73         {"class", CLASS},
74         {"close", CLOSE},
75         {"cluster", CLUSTER},
76         {"coalesce", COALESCE},
77         {"collate", COLLATE},
78         {"column", COLUMN},
79         {"comment", COMMENT},
80         {"commit", COMMIT},
81         {"committed", COMMITTED},
82         {"constraint", CONSTRAINT},
83         {"constraints", CONSTRAINTS},
84         {"conversion", CONVERSION_P},
85         {"convert", CONVERT},
86         {"copy", COPY},
87         {"create", CREATE},
88         {"createdb", CREATEDB},
89         {"createuser", CREATEUSER},
90         {"cross", CROSS},
91         {"current_date", CURRENT_DATE},
92         {"current_time", CURRENT_TIME},
93         {"current_timestamp", CURRENT_TIMESTAMP},
94         {"current_user", CURRENT_USER},
95         {"cursor", CURSOR},
96         {"cycle", CYCLE},
97         {"database", DATABASE},
98         {"day", DAY_P},
99         {"deallocate", DEALLOCATE},
100         {"dec", DEC},
101         {"decimal", DECIMAL},
102         {"declare", DECLARE},
103         {"default", DEFAULT},
104         {"deferrable", DEFERRABLE},
105         {"deferred", DEFERRED},
106         {"definer", DEFINER},
107         {"delete", DELETE_P},
108         {"delimiter", DELIMITER},
109         {"delimiters", DELIMITERS},
110         {"desc", DESC},
111         {"distinct", DISTINCT},
112         {"do", DO},
113         {"domain", DOMAIN_P},
114         {"double", DOUBLE},
115         {"drop", DROP},
116         {"each", EACH},
117         {"else", ELSE},
118         {"encoding", ENCODING},
119         {"encrypted", ENCRYPTED},
120         {"end", END_TRANS},
121         {"escape", ESCAPE},
122         {"except", EXCEPT},
123         {"exclusive", EXCLUSIVE},
124         {"execute", EXECUTE},
125         {"exists", EXISTS},
126         {"explain", EXPLAIN},
127         {"external", EXTERNAL},
128         {"extract", EXTRACT},
129         {"false", FALSE_P},
130         {"fetch", FETCH},
131         {"float", FLOAT_P},
132         {"for", FOR},
133         {"force", FORCE},
134         {"foreign", FOREIGN},
135         {"forward", FORWARD},
136         {"freeze", FREEZE},
137         {"from", FROM},
138         {"full", FULL},
139         {"function", FUNCTION},
140         {"get", GET},
141         {"global", GLOBAL},
142         {"grant", GRANT},
143         {"group", GROUP_P},
144         {"handler", HANDLER},
145         {"having", HAVING},
146         {"hour", HOUR_P},
147         {"ilike", ILIKE},
148         {"immediate", IMMEDIATE},
149         {"immutable", IMMUTABLE},
150         {"implicit", IMPLICIT_P},
151         {"in", IN_P},
152         {"increment", INCREMENT},
153         {"index", INDEX},
154         {"inherits", INHERITS},
155         {"initially", INITIALLY},
156         {"inner", INNER_P},
157         {"inout", INOUT},
158         {"input", INPUT},
159         {"insensitive", INSENSITIVE},
160         {"insert", INSERT},
161         {"instead", INSTEAD},
162         {"int", INT},
163         {"integer", INTEGER},
164         {"intersect", INTERSECT},
165         {"interval", INTERVAL},
166         {"into", INTO},
167         {"invoker", INVOKER},
168         {"is", IS},
169         {"isnull", ISNULL},
170         {"isolation", ISOLATION},
171         {"join", JOIN},
172         {"key", KEY},
173         {"lancompiler", LANCOMPILER},
174         {"language", LANGUAGE},
175         {"last", LAST},
176         {"leading", LEADING},
177         {"left", LEFT},
178         {"level", LEVEL},
179         {"like", LIKE},
180         {"limit", LIMIT},
181         {"listen", LISTEN},
182         {"load", LOAD},
183         {"local", LOCAL},
184         {"localtime", LOCALTIME},
185         {"localtimestamp", LOCALTIMESTAMP},
186         {"location", LOCATION},
187         {"lock", LOCK_P},
188         {"match", MATCH},
189         {"maxvalue", MAXVALUE},
190         {"minute", MINUTE_P},
191         {"minvalue", MINVALUE},
192         {"mode", MODE},
193         {"month", MONTH_P},
194         {"move", MOVE},
195         {"names", NAMES},
196         {"national", NATIONAL},
197         {"natural", NATURAL},
198         {"nchar", NCHAR},
199         {"new", NEW},
200         {"next", NEXT},
201         {"no", NO},
202         {"nocreatedb", NOCREATEDB},
203         {"nocreateuser", NOCREATEUSER},
204         {"none", NONE},
205         {"not", NOT},
206         {"nothing", NOTHING},
207         {"notify", NOTIFY},
208         {"notnull", NOTNULL},
209         {"null", NULL_P},
210         {"nullif", NULLIF},
211         {"numeric", NUMERIC},
212         {"of", OF},
213         {"off", OFF},
214         {"offset", OFFSET},
215         {"oids", OIDS},
216         {"old", OLD},
217         {"on", ON},
218         {"only", ONLY},
219         {"operator", OPERATOR},
220         {"option", OPTION},
221         {"or", OR},
222         {"order", ORDER},
223         {"out", OUT_P},
224         {"outer", OUTER_P},
225         {"overlaps", OVERLAPS},
226         {"overlay", OVERLAY},
227         {"owner", OWNER},
228         {"partial", PARTIAL},
229         {"password", PASSWORD},
230         {"path", PATH_P},
231         {"pendant", PENDANT},
232         {"placing", PLACING},
233         {"position", POSITION},
234         {"precision", PRECISION},
235         {"prepare", PREPARE},
236         {"preserve", PRESERVE},
237         {"primary", PRIMARY},
238         {"prior", PRIOR},
239         {"privileges", PRIVILEGES},
240         {"procedural", PROCEDURAL},
241         {"procedure", PROCEDURE},
242         {"read", READ},
243         {"real", REAL},
244         {"recheck", RECHECK},
245         {"references", REFERENCES},
246         {"reindex", REINDEX},
247         {"relative", RELATIVE},
248         {"rename", RENAME},
249         {"replace", REPLACE},
250         {"reset", RESET},
251         {"restrict", RESTRICT},
252         {"returns", RETURNS},
253         {"revoke", REVOKE},
254         {"right", RIGHT},
255         {"rollback", ROLLBACK},
256         {"row", ROW},
257         {"rows", ROWS},
258         {"rule", RULE},
259         {"schema", SCHEMA},
260         {"scroll", SCROLL},
261         {"second", SECOND_P},
262         {"security", SECURITY},
263         {"select", SELECT},
264         {"sequence", SEQUENCE},
265         {"serializable", SERIALIZABLE},
266         {"session", SESSION},
267         {"session_user", SESSION_USER},
268         {"set", SET},
269         {"setof", SETOF},
270         {"share", SHARE},
271         {"show", SHOW},
272         {"similar", SIMILAR},
273         {"simple", SIMPLE},
274         {"smallint", SMALLINT},
275         {"some", SOME},
276         {"stable", STABLE},
277         {"start", START},
278         {"statement", STATEMENT},
279         {"statistics", STATISTICS},
280         {"stdin", STDIN},
281         {"stdout", STDOUT},
282         {"storage", STORAGE},
283         {"strict", STRICT},
284         {"substring", SUBSTRING},
285         {"sysid", SYSID},
286         {"table", TABLE},
287         {"temp", TEMP},
288         {"template", TEMPLATE},
289         {"temporary", TEMPORARY},
290         {"then", THEN},
291         {"time", TIME},
292         {"timestamp", TIMESTAMP},
293         {"to", TO},
294         {"toast", TOAST},
295         {"trailing", TRAILING},
296         {"transaction", TRANSACTION},
297         {"treat", TREAT},
298         {"trigger", TRIGGER},
299         {"trim", TRIM},
300         {"true", TRUE_P},
301         {"truncate", TRUNCATE},
302         {"trusted", TRUSTED},
303         {"type", TYPE_P},
304         {"unencrypted", UNENCRYPTED},
305         {"union", UNION},
306         {"unique", UNIQUE},
307         {"unknown", UNKNOWN},
308         {"unlisten", UNLISTEN},
309         {"until", UNTIL},
310         {"update", UPDATE},
311         {"usage", USAGE},
312         {"user", USER},
313         {"using", USING},
314         {"vacuum", VACUUM},
315         {"valid", VALID},
316         {"validator", VALIDATOR},
317         {"value", VALUE},
318         {"values", VALUES},
319         {"varchar", VARCHAR},
320         {"varying", VARYING},
321         {"verbose", VERBOSE},
322         {"version", VERSION},
323         {"view", VIEW},
324         {"volatile", VOLATILE},
325         {"when", WHEN},
326         {"where", WHERE},
327         {"with", WITH},
328         {"without", WITHOUT},
329         {"work", WORK},
330         {"write", WRITE},
331         {"year", YEAR_P},
332         {"zone", ZONE},
333 };
334
335 /*
336  * ScanKeywordLookup - see if a given word is a keyword
337  *
338  * Returns a pointer to the ScanKeyword table entry, or NULL if no match.
339  *
340  * The match is done case-insensitively.  Note that we deliberately use a
341  * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
342  * even if we are in a locale where tolower() would produce more or different
343  * translations.  This is to conform to the SQL99 spec, which says that
344  * keywords are to be matched in this way even though non-keyword identifiers
345  * receive a different case-normalization mapping.
346  */
347 const ScanKeyword *
348 ScanKeywordLookup(const char *text)
349 {
350         int                     len,
351                                 i;
352         char            word[NAMEDATALEN];
353         const ScanKeyword *low;
354         const ScanKeyword *high;
355
356         len = strlen(text);
357         /* We assume all keywords are shorter than NAMEDATALEN. */
358         if (len >= NAMEDATALEN)
359                 return NULL;
360
361         /*
362          * Apply an ASCII-only downcasing.      We must not use tolower() since it
363          * may produce the wrong translation in some locales (eg, Turkish),
364          * and we don't trust isupper() very much either.  In an ASCII-based
365          * encoding the tests against A and Z are sufficient, but we also
366          * check isupper() so that we will work correctly under EBCDIC.  The
367          * actual case conversion step should work for either ASCII or EBCDIC.
368          */
369         for (i = 0; i < len; i++)
370         {
371                 char            ch = text[i];
372
373                 if (ch >= 'A' && ch <= 'Z' && isupper((unsigned char) ch))
374                         ch += 'a' - 'A';
375                 word[i] = ch;
376         }
377         word[len] = '\0';
378
379         /*
380          * Now do a binary search using plain strcmp() comparison.
381          */
382         low = &ScanKeywords[0];
383         high = endof(ScanKeywords) - 1;
384         while (low <= high)
385         {
386                 const ScanKeyword *middle;
387                 int                     difference;
388
389                 middle = low + (high - low) / 2;
390                 difference = strcmp(middle->name, word);
391                 if (difference == 0)
392                         return middle;
393                 else if (difference < 0)
394                         low = middle + 1;
395                 else
396                         high = middle - 1;
397         }
398
399         return NULL;
400 }