Header And Logo

PostgreSQL
| The world's most advanced open source database.

kwlookup.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * kwlookup.c
00004  *    lexical token lookup for key words in PostgreSQL
00005  *
00006  * NB - this file is also used by ECPG and several frontend programs in
00007  * src/bin/ including pg_dump and psql
00008  *
00009  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00010  * Portions Copyright (c) 1994, Regents of the University of California
00011  *
00012  *
00013  * IDENTIFICATION
00014  *    src/backend/parser/kwlookup.c
00015  *
00016  *-------------------------------------------------------------------------
00017  */
00018 
00019 /* use c.h so this can be built as either frontend or backend */
00020 #include "c.h"
00021 
00022 #include <ctype.h>
00023 
00024 #include "parser/keywords.h"
00025 
00026 /*
00027  * ScanKeywordLookup - see if a given word is a keyword
00028  *
00029  * Returns a pointer to the ScanKeyword table entry, or NULL if no match.
00030  *
00031  * The match is done case-insensitively.  Note that we deliberately use a
00032  * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
00033  * even if we are in a locale where tolower() would produce more or different
00034  * translations.  This is to conform to the SQL99 spec, which says that
00035  * keywords are to be matched in this way even though non-keyword identifiers
00036  * receive a different case-normalization mapping.
00037  */
00038 const ScanKeyword *
00039 ScanKeywordLookup(const char *text,
00040                   const ScanKeyword *keywords,
00041                   int num_keywords)
00042 {
00043     int         len,
00044                 i;
00045     char        word[NAMEDATALEN];
00046     const ScanKeyword *low;
00047     const ScanKeyword *high;
00048 
00049     len = strlen(text);
00050     /* We assume all keywords are shorter than NAMEDATALEN. */
00051     if (len >= NAMEDATALEN)
00052         return NULL;
00053 
00054     /*
00055      * Apply an ASCII-only downcasing.  We must not use tolower() since it may
00056      * produce the wrong translation in some locales (eg, Turkish).
00057      */
00058     for (i = 0; i < len; i++)
00059     {
00060         char        ch = text[i];
00061 
00062         if (ch >= 'A' && ch <= 'Z')
00063             ch += 'a' - 'A';
00064         word[i] = ch;
00065     }
00066     word[len] = '\0';
00067 
00068     /*
00069      * Now do a binary search using plain strcmp() comparison.
00070      */
00071     low = keywords;
00072     high = keywords + (num_keywords - 1);
00073     while (low <= high)
00074     {
00075         const ScanKeyword *middle;
00076         int         difference;
00077 
00078         middle = low + (high - low) / 2;
00079         difference = strcmp(middle->name, word);
00080         if (difference == 0)
00081             return middle;
00082         else if (difference < 0)
00083             low = middle + 1;
00084         else
00085             high = middle - 1;
00086     }
00087 
00088     return NULL;
00089 }