File: keywords.c

package info (click to toggle)
pgadmin3 1.20.0~beta2-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 73,704 kB
  • ctags: 18,591
  • sloc: cpp: 193,786; ansic: 18,736; sh: 5,154; pascal: 1,120; yacc: 927; makefile: 516; lex: 421; xml: 126; perl: 40
file content (152 lines) | stat: -rw-r--r-- 4,726 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*-------------------------------------------------------------------------
 *
 * keywords.c
 *	  lexical token lookup for reserved words in PostgreSQL
 *
 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.177 2006/10/07 21:51:02 petere Exp $
 *
 *-------------------------------------------------------------------------
 */

///////////////////////////////////////////////////////////////////////////
//
// pgAdmin note: This file is based on src/backend/parser/keywords.c and
//               src/backend/parser/kwlookup.c from PostgreSQL, but extended
//               to support EntepriseDB and Greenplum.
//
//               This file is under the BSD licence, per PostgreSQL.
///////////////////////////////////////////////////////////////////////////

#include "postgres.h"
#include "parser/keywords.h"

/*
 * List of (keyword-name, keyword-token-value) pairs.
 */
#define PG_KEYWORD(a,b,c) {a,c},
const ScanKeyword ScanKeywords[] = {
#include <parser/kwlist.h>
};
const int NumScanKeywords = lengthof(ScanKeywords);

/*
 * Additional pairs here. They need to live in a separate array since
 * the ScanKeywords array needs to be sorted!
 *
 * !!WARNING!!: This list must be sorted, because binary
 *              search is used to locate entries.
 */
#define PG_KEYWORD2(a,b) {a,b},
const ScanKeyword ScanKeywordsExtra[] = {
	PG_KEYWORD2("connect", RESERVED_KEYWORD)
	PG_KEYWORD2("convert", RESERVED_KEYWORD)
	PG_KEYWORD2("distributed", UNRESERVED_KEYWORD)
	PG_KEYWORD2("exec", RESERVED_KEYWORD)
	PG_KEYWORD2("log", UNRESERVED_KEYWORD)
	PG_KEYWORD2("long", RESERVED_KEYWORD)
	PG_KEYWORD2("minus", RESERVED_KEYWORD)
	PG_KEYWORD2("nocache", RESERVED_KEYWORD)
	PG_KEYWORD2("number", RESERVED_KEYWORD)
	PG_KEYWORD2("package", RESERVED_KEYWORD)
	PG_KEYWORD2("pls_integer", RESERVED_KEYWORD)
	PG_KEYWORD2("raw", RESERVED_KEYWORD)
	PG_KEYWORD2("return", RESERVED_KEYWORD)
	PG_KEYWORD2("smalldatetime", RESERVED_KEYWORD)
	PG_KEYWORD2("smallfloat", RESERVED_KEYWORD)
	PG_KEYWORD2("smallmoney", RESERVED_KEYWORD)
	PG_KEYWORD2("sysdate", RESERVED_KEYWORD)
	PG_KEYWORD2("systimestap", RESERVED_KEYWORD)
	PG_KEYWORD2("tinyint", RESERVED_KEYWORD)
	PG_KEYWORD2("tinytext", RESERVED_KEYWORD)
	PG_KEYWORD2("varchar2", RESERVED_KEYWORD)
};
const int NumScanKeywordsExtra = lengthof(ScanKeywordsExtra);

/*
 * ScanKeywordLookup - see if a given word is a keyword
 *
 * Returns a pointer to the ScanKeyword table entry, or NULL if no match.
 *
 * The match is done case-insensitively.  Note that we deliberately use a
 * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
 * even if we are in a locale where tolower() would produce more or different
 * translations.  This is to conform to the SQL99 spec, which says that
 * keywords are to be matched in this way even though non-keyword identifiers
 * receive a different case-normalization mapping.
 */
const ScanKeyword *
ScanKeywordLookup(const char *text)
{
    int			len,
                i;
    char		word[NAMEDATALEN];
    const ScanKeyword *low;
    const ScanKeyword *high;

    len = strlen(text);
    /* We assume all keywords are shorter than NAMEDATALEN. */
    if (len >= NAMEDATALEN)
        return NULL;

    /*
     * Apply an ASCII-only downcasing.	We must not use tolower() since it may
     * produce the wrong translation in some locales (eg, Turkish).
     */
    for (i = 0; i < len; i++)
    {
        char		ch = text[i];

        if (ch >= 'A' && ch <= 'Z')
            ch += 'a' - 'A';
        word[i] = ch;
    }
    word[len] = '\0';

    /*
     * Now do a binary search using plain strcmp() comparison.
     */
    low = &ScanKeywords[0];
    high = endof(ScanKeywords) - 1;
    while (low <= high)
    {
        const ScanKeyword *middle;
        int			difference;

        middle = low + (high - low) / 2;
        difference = strcmp(middle->name, word);
        if (difference == 0)
            return middle;
        else if (difference < 0)
            low = middle + 1;
        else
            high = middle - 1;
    }

	/*
	 * If not found, also do a binary search in the list of extra
	 * keywords.
	 */
    low = &ScanKeywordsExtra[0];
    high = endof(ScanKeywordsExtra) - 1;
    while (low <= high)
    {
        const ScanKeyword *middle;
        int			difference;

        middle = low + (high - low) / 2;
        difference = strcmp(middle->name, word);
        if (difference == 0)
            return middle;
        else if (difference < 0)
            low = middle + 1;
        else
            high = middle - 1;
    }

    return NULL;
}