/src/mysql-server/sql/sql_lex_hash.cc
Line | Count | Source |
1 | | /* |
2 | | Copyright (c) 2015, 2025, Oracle and/or its affiliates. |
3 | | |
4 | | This program is free software; you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License, version 2.0, |
6 | | as published by the Free Software Foundation. |
7 | | |
8 | | This program is designed to work with certain software (including |
9 | | but not limited to OpenSSL) that is licensed under separate terms, |
10 | | as designated in a particular file or component or in included license |
11 | | documentation. The authors of MySQL hereby grant you an additional |
12 | | permission to link the program and your derivative works with the |
13 | | separately licensed software that they have either included with |
14 | | the program or referenced in the documentation. |
15 | | |
16 | | This program is distributed in the hope that it will be useful, |
17 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | | GNU General Public License, version 2.0, for more details. |
20 | | |
21 | | You should have received a copy of the GNU General Public License |
22 | | along with this program; if not, write to the Free Software |
23 | | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
24 | | |
25 | | #include "sql/sql_lex_hash.h" |
26 | | |
27 | | #include <sys/types.h> |
28 | | |
29 | | #include "my_byteorder.h" |
30 | | #include "my_dbug.h" |
31 | | #include "my_inttypes.h" |
32 | | #include "sql/lex.h" |
33 | | #include "sql/lex_hash.h" |
34 | | #include "sql/lex_symbol.h" |
35 | | #include "template_utils.h" |
36 | | |
37 | | const Lex_hash Lex_hash::sql_keywords(sql_keywords_map, sql_keywords_max_len); |
38 | | const Lex_hash Lex_hash::sql_keywords_and_funcs(sql_keywords_and_funcs_map, |
39 | | sql_keywords_and_funcs_max_len); |
40 | | |
41 | | const Lex_hash Lex_hash::hint_keywords(hint_keywords_map, |
42 | | hint_keywords_max_len); |
43 | | |
44 | | /* |
45 | | The following data is based on the latin1 character set, and is only |
46 | | used when comparing keywords |
47 | | */ |
48 | | |
49 | | static const uchar to_upper_lex[] = { |
50 | | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
51 | | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, |
52 | | 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, |
53 | | 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, |
54 | | 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, |
55 | | 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, |
56 | | 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, |
57 | | 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, |
58 | | 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, |
59 | | 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, |
60 | | 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, |
61 | | 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, |
62 | | 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, |
63 | | 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, |
64 | | 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 192, |
65 | | 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, |
66 | | 208, 209, 210, 211, 212, 213, 214, 247, 216, 217, 218, 219, 220, 221, 222, |
67 | | 255}; |
68 | | |
69 | 88.6k | inline int lex_casecmp(const char *s, const char *t, uint len) { |
70 | 96.1k | while (len-- != 0 && to_upper_lex[(uchar)*s++] == to_upper_lex[(uchar)*t++]) |
71 | 7.49k | ; |
72 | 88.6k | return (int)len + 1; |
73 | 88.6k | } |
74 | | |
75 | 323k | const SYMBOL *Lex_hash::get_hash_symbol(const char *s, unsigned int len) const { |
76 | 323k | const char *cur_str = s; |
77 | | |
78 | 323k | if (len == 0) { |
79 | 57 | DBUG_PRINT("warning", |
80 | 57 | ("get_hash_symbol() received a request for a zero-length symbol," |
81 | 57 | " which is probably a mistake.")); |
82 | 57 | return nullptr; |
83 | 57 | } |
84 | | |
85 | 323k | if (len > entry_max_len) return nullptr; |
86 | | |
87 | 318k | uint32 cur_struct = uint4korr(hash_map + ((len - 1) * 4)); |
88 | | |
89 | 464k | for (;;) { |
90 | 464k | const auto first_char = (uchar)cur_struct; |
91 | | |
92 | 464k | if (first_char == 0) { |
93 | 110k | const auto ires = (uint16)(cur_struct >> 16); |
94 | 110k | if (ires == array_elements(symbols)) return nullptr; |
95 | 88.6k | const SYMBOL *res = symbols + ires; |
96 | 88.6k | const uint count = (uint)(cur_str - s); |
97 | 88.6k | return lex_casecmp(cur_str, res->name + count, len - count) ? nullptr |
98 | 88.6k | : res; |
99 | 110k | } |
100 | | |
101 | 353k | const auto cur_char = (uchar)to_upper_lex[(uchar)*cur_str]; |
102 | 353k | if (cur_char < first_char) return nullptr; |
103 | 241k | cur_struct >>= 8; |
104 | 241k | if (cur_char > (uchar)cur_struct) return nullptr; |
105 | | |
106 | 145k | cur_struct >>= 8; |
107 | 145k | cur_struct = uint4korr(hash_map + |
108 | 145k | (((uint16)cur_struct + cur_char - first_char) * 4)); |
109 | 145k | cur_str++; |
110 | 145k | } |
111 | 318k | } |