1
by brian
clean slate |
1 |
/* Copyright (C) 2000-2006 MySQL AB
|
2 |
||
3 |
This program is free software; you can redistribute it and/or modify
|
|
4 |
it under the terms of the GNU General Public License as published by
|
|
5 |
the Free Software Foundation; version 2 of the License.
|
|
6 |
||
7 |
This program is distributed in the hope that it will be useful,
|
|
8 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
9 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
10 |
GNU General Public License for more details.
|
|
11 |
||
12 |
You should have received a copy of the GNU General Public License
|
|
13 |
along with this program; if not, write to the Free Software
|
|
14 |
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
15 |
||
16 |
||
17 |
/* Basic functions needed by many modules */
|
|
243.1.17
by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.) |
18 |
#include <drizzled/server_includes.h> |
19 |
#include <drizzled/sql_select.h> |
|
212.5.38
by Monty Taylor
Moved my_dir (and removed references to a lot of places) |
20 |
#include <mysys/my_dir.h> |
202.3.6
by Monty Taylor
First pass at gettexizing the error messages. |
21 |
#include <drizzled/drizzled_error_messages.h> |
1
by brian
clean slate |
22 |
|
23 |
#define FLAGSTR(S,F) ((S) & (F) ? #F " " : "")
|
|
24 |
||
25 |
/**
|
|
26 |
@defgroup Data_Dictionary Data Dictionary
|
|
27 |
@{
|
|
28 |
*/
|
|
29 |
TABLE *unused_tables; /* Used by mysql_test */ |
|
30 |
HASH open_cache; /* Used by mysql_test */ |
|
31 |
static HASH table_def_cache; |
|
32 |
static TABLE_SHARE *oldest_unused_share, end_of_unused_share; |
|
33 |
static pthread_mutex_t LOCK_table_share; |
|
34 |
static bool table_def_inited= 0; |
|
35 |
||
36 |
static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, |
|
37 |
const char *alias, |
|
38 |
char *cache_key, uint cache_key_length, |
|
39 |
MEM_ROOT *mem_root, uint flags); |
|
40 |
static void free_cache_entry(TABLE *entry); |
|
41 |
static void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, |
|
42 |
bool send_refresh); |
|
43 |
||
44 |
||
45 |
extern "C" uchar *table_cache_key(const uchar *record, size_t *length, |
|
146
by Brian Aker
my_bool cleanup. |
46 |
bool not_used __attribute__((unused))) |
1
by brian
clean slate |
47 |
{
|
48 |
TABLE *entry=(TABLE*) record; |
|
49 |
*length= entry->s->table_cache_key.length; |
|
50 |
return (uchar*) entry->s->table_cache_key.str; |
|
51 |
}
|
|
52 |
||
53 |
||
54 |
bool table_cache_init(void) |
|
55 |
{
|
|
56 |
return hash_init(&open_cache, &my_charset_bin, table_cache_size+16, |
|
57 |
0, 0, table_cache_key, |
|
202.3.7
by Monty Taylor
Gettext error compiles and passes test! |
58 |
(hash_free_key) free_cache_entry, 0); |
1
by brian
clean slate |
59 |
}
|
60 |
||
61 |
void table_cache_free(void) |
|
62 |
{
|
|
63 |
if (table_def_inited) |
|
64 |
{
|
|
55
by brian
Update for using real bool types. |
65 |
close_cached_tables(NULL, NULL, false, false, false); |
1
by brian
clean slate |
66 |
if (!open_cache.records) // Safety first |
67 |
hash_free(&open_cache); |
|
68 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
69 |
return; |
1
by brian
clean slate |
70 |
}
|
71 |
||
72 |
uint cached_open_tables(void) |
|
73 |
{
|
|
74 |
return open_cache.records; |
|
75 |
}
|
|
76 |
||
77 |
/*
|
|
78 |
Create a table cache key
|
|
79 |
||
80 |
SYNOPSIS
|
|
81 |
create_table_def_key()
|
|
82 |
thd Thread handler
|
|
83 |
key Create key here (must be of size MAX_DBKEY_LENGTH)
|
|
84 |
table_list Table definition
|
|
85 |
tmp_table Set if table is a tmp table
|
|
86 |
||
87 |
IMPLEMENTATION
|
|
88 |
The table cache_key is created from:
|
|
89 |
db_name + \0
|
|
90 |
table_name + \0
|
|
91 |
||
92 |
if the table is a tmp table, we add the following to make each tmp table
|
|
93 |
unique on the slave:
|
|
94 |
||
95 |
4 bytes for master thread id
|
|
96 |
4 bytes pseudo thread id
|
|
97 |
||
98 |
RETURN
|
|
99 |
Length of key
|
|
100 |
*/
|
|
101 |
||
102 |
uint create_table_def_key(THD *thd, char *key, TABLE_LIST *table_list, |
|
103 |
bool tmp_table) |
|
104 |
{
|
|
266.1.21
by Monty Taylor
Removed references to strmov and strnmov |
105 |
uint key_length= (uint) (stpcpy(stpcpy(key, table_list->db)+1, |
1
by brian
clean slate |
106 |
table_list->table_name)-key)+1; |
107 |
if (tmp_table) |
|
108 |
{
|
|
109 |
int4store(key + key_length, thd->server_id); |
|
110 |
int4store(key + key_length + 4, thd->variables.pseudo_thread_id); |
|
111 |
key_length+= TMP_TABLE_KEY_EXTRA; |
|
112 |
}
|
|
113 |
return key_length; |
|
114 |
}
|
|
115 |
||
116 |
||
117 |
||
118 |
/*****************************************************************************
|
|
119 |
Functions to handle table definition cach (TABLE_SHARE)
|
|
120 |
*****************************************************************************/
|
|
121 |
||
122 |
extern "C" uchar *table_def_key(const uchar *record, size_t *length, |
|
146
by Brian Aker
my_bool cleanup. |
123 |
bool not_used __attribute__((unused))) |
1
by brian
clean slate |
124 |
{
|
125 |
TABLE_SHARE *entry=(TABLE_SHARE*) record; |
|
126 |
*length= entry->table_cache_key.length; |
|
127 |
return (uchar*) entry->table_cache_key.str; |
|
128 |
}
|
|
129 |
||
130 |
||
131 |
static void table_def_free_entry(TABLE_SHARE *share) |
|
132 |
{
|
|
133 |
if (share->prev) |
|
134 |
{
|
|
135 |
/* remove from old_unused_share list */
|
|
136 |
pthread_mutex_lock(&LOCK_table_share); |
|
137 |
*share->prev= share->next; |
|
138 |
share->next->prev= share->prev; |
|
139 |
pthread_mutex_unlock(&LOCK_table_share); |
|
140 |
}
|
|
141 |
free_table_share(share); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
142 |
return; |
1
by brian
clean slate |
143 |
}
|
144 |
||
145 |
||
146 |
bool table_def_init(void) |
|
147 |
{
|
|
148 |
table_def_inited= 1; |
|
149 |
pthread_mutex_init(&LOCK_table_share, MY_MUTEX_INIT_FAST); |
|
150 |
oldest_unused_share= &end_of_unused_share; |
|
151 |
end_of_unused_share.prev= &oldest_unused_share; |
|
152 |
||
153 |
return hash_init(&table_def_cache, &my_charset_bin, table_def_size, |
|
154 |
0, 0, table_def_key, |
|
202.3.7
by Monty Taylor
Gettext error compiles and passes test! |
155 |
(hash_free_key) table_def_free_entry, 0); |
1
by brian
clean slate |
156 |
}
|
157 |
||
158 |
||
159 |
void table_def_free(void) |
|
160 |
{
|
|
161 |
if (table_def_inited) |
|
162 |
{
|
|
163 |
table_def_inited= 0; |
|
164 |
pthread_mutex_destroy(&LOCK_table_share); |
|
165 |
hash_free(&table_def_cache); |
|
166 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
167 |
return; |
1
by brian
clean slate |
168 |
}
|
169 |
||
170 |
||
171 |
uint cached_table_definitions(void) |
|
172 |
{
|
|
173 |
return table_def_cache.records; |
|
174 |
}
|
|
175 |
||
176 |
||
177 |
/*
|
|
178 |
Get TABLE_SHARE for a table.
|
|
179 |
||
180 |
get_table_share()
|
|
181 |
thd Thread handle
|
|
182 |
table_list Table that should be opened
|
|
183 |
key Table cache key
|
|
184 |
key_length Length of key
|
|
185 |
db_flags Flags to open_table_def():
|
|
186 |
OPEN_VIEW
|
|
187 |
error out: Error code from open_table_def()
|
|
188 |
||
189 |
IMPLEMENTATION
|
|
190 |
Get a table definition from the table definition cache.
|
|
191 |
If it doesn't exist, create a new from the table definition file.
|
|
192 |
||
193 |
NOTES
|
|
194 |
We must have wrlock on LOCK_open when we come here
|
|
195 |
(To be changed later)
|
|
196 |
||
197 |
RETURN
|
|
198 |
0 Error
|
|
199 |
# Share for table
|
|
200 |
*/
|
|
201 |
||
202 |
TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, char *key, |
|
203 |
uint key_length, uint db_flags, int *error) |
|
204 |
{
|
|
205 |
TABLE_SHARE *share; |
|
206 |
||
207 |
*error= 0; |
|
208 |
||
209 |
/* Read table definition from cache */
|
|
210 |
if ((share= (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key, |
|
211 |
key_length))) |
|
212 |
goto found; |
|
213 |
||
214 |
if (!(share= alloc_table_share(table_list, key, key_length))) |
|
215 |
{
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
216 |
return(0); |
1
by brian
clean slate |
217 |
}
|
218 |
||
219 |
/*
|
|
220 |
Lock mutex to be able to read table definition from file without
|
|
221 |
conflicts
|
|
222 |
*/
|
|
223 |
(void) pthread_mutex_lock(&share->mutex); |
|
224 |
||
225 |
/*
|
|
226 |
We assign a new table id under the protection of the LOCK_open and
|
|
227 |
the share's own mutex. We do this insted of creating a new mutex
|
|
228 |
and using it for the sole purpose of serializing accesses to a
|
|
229 |
static variable, we assign the table id here. We assign it to the
|
|
230 |
share before inserting it into the table_def_cache to be really
|
|
231 |
sure that it cannot be read from the cache without having a table
|
|
232 |
id assigned.
|
|
233 |
||
234 |
CAVEAT. This means that the table cannot be used for
|
|
235 |
binlogging/replication purposes, unless get_table_share() has been
|
|
236 |
called directly or indirectly.
|
|
237 |
*/
|
|
238 |
assign_new_table_id(share); |
|
239 |
||
240 |
if (my_hash_insert(&table_def_cache, (uchar*) share)) |
|
241 |
{
|
|
242 |
free_table_share(share); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
243 |
return(0); // return error |
1
by brian
clean slate |
244 |
}
|
245 |
if (open_table_def(thd, share, db_flags)) |
|
246 |
{
|
|
247 |
*error= share->error; |
|
248 |
(void) hash_delete(&table_def_cache, (uchar*) share); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
249 |
return(0); |
1
by brian
clean slate |
250 |
}
|
251 |
share->ref_count++; // Mark in use |
|
252 |
(void) pthread_mutex_unlock(&share->mutex); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
253 |
return(share); |
1
by brian
clean slate |
254 |
|
255 |
found: |
|
256 |
/*
|
|
257 |
We found an existing table definition. Return it if we didn't get
|
|
258 |
an error when reading the table definition from file.
|
|
259 |
*/
|
|
260 |
||
261 |
/* We must do a lock to ensure that the structure is initialized */
|
|
262 |
(void) pthread_mutex_lock(&share->mutex); |
|
263 |
if (share->error) |
|
264 |
{
|
|
265 |
/* Table definition contained an error */
|
|
266 |
open_table_error(share, share->error, share->open_errno, share->errarg); |
|
267 |
(void) pthread_mutex_unlock(&share->mutex); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
268 |
return(0); |
1
by brian
clean slate |
269 |
}
|
270 |
||
271 |
if (!share->ref_count++ && share->prev) |
|
272 |
{
|
|
273 |
/*
|
|
274 |
Share was not used before and it was in the old_unused_share list
|
|
275 |
Unlink share from this list
|
|
276 |
*/
|
|
277 |
pthread_mutex_lock(&LOCK_table_share); |
|
278 |
*share->prev= share->next; |
|
279 |
share->next->prev= share->prev; |
|
280 |
share->next= 0; |
|
281 |
share->prev= 0; |
|
282 |
pthread_mutex_unlock(&LOCK_table_share); |
|
283 |
}
|
|
284 |
(void) pthread_mutex_unlock(&share->mutex); |
|
285 |
||
286 |
/* Free cache if too big */
|
|
287 |
while (table_def_cache.records > table_def_size && |
|
288 |
oldest_unused_share->next) |
|
289 |
{
|
|
290 |
pthread_mutex_lock(&oldest_unused_share->mutex); |
|
291 |
VOID(hash_delete(&table_def_cache, (uchar*) oldest_unused_share)); |
|
292 |
}
|
|
293 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
294 |
return(share); |
1
by brian
clean slate |
295 |
}
|
296 |
||
297 |
||
298 |
/*
|
|
299 |
Get a table share. If it didn't exist, try creating it from engine
|
|
300 |
||
301 |
For arguments and return values, see get_table_from_share()
|
|
302 |
*/
|
|
303 |
||
304 |
static TABLE_SHARE |
|
305 |
*get_table_share_with_create(THD *thd, TABLE_LIST *table_list, |
|
306 |
char *key, uint key_length, |
|
307 |
uint db_flags, int *error) |
|
308 |
{
|
|
309 |
TABLE_SHARE *share; |
|
310 |
int tmp; |
|
311 |
||
312 |
share= get_table_share(thd, table_list, key, key_length, db_flags, error); |
|
313 |
/*
|
|
314 |
If share is not NULL, we found an existing share.
|
|
315 |
||
316 |
If share is NULL, and there is no error, we're inside
|
|
317 |
pre-locking, which silences 'ER_NO_SUCH_TABLE' errors
|
|
318 |
with the intention to silently drop non-existing tables
|
|
319 |
from the pre-locking list. In this case we still need to try
|
|
320 |
auto-discover before returning a NULL share.
|
|
321 |
||
322 |
If share is NULL and the error is ER_NO_SUCH_TABLE, this is
|
|
323 |
the same as above, only that the error was not silenced by
|
|
324 |
pre-locking. Once again, we need to try to auto-discover
|
|
325 |
the share.
|
|
326 |
||
327 |
Finally, if share is still NULL, it's a real error and we need
|
|
328 |
to abort.
|
|
329 |
||
330 |
@todo Rework alternative ways to deal with ER_NO_SUCH TABLE.
|
|
331 |
*/
|
|
332 |
if (share || (thd->is_error() && (thd->main_da.sql_errno() != ER_NO_SUCH_TABLE))) |
|
333 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
334 |
return(share); |
1
by brian
clean slate |
335 |
|
336 |
/* Table didn't exist. Check if some engine can provide it */
|
|
337 |
if ((tmp= ha_create_table_from_engine(thd, table_list->db, |
|
338 |
table_list->table_name)) < 0) |
|
339 |
{
|
|
340 |
/*
|
|
341 |
No such table in any engine.
|
|
342 |
Hide "Table doesn't exist" errors if the table belongs to a view.
|
|
343 |
The check for thd->is_error() is necessary to not push an
|
|
344 |
unwanted error in case of pre-locking, which silences
|
|
345 |
"no such table" errors.
|
|
346 |
@todo Rework the alternative ways to deal with ER_NO_SUCH TABLE.
|
|
347 |
*/
|
|
348 |
if (thd->is_error() && table_list->belong_to_view) |
|
349 |
{
|
|
350 |
thd->clear_error(); |
|
351 |
my_error(ER_VIEW_INVALID, MYF(0), "", ""); |
|
352 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
353 |
return(0); |
1
by brian
clean slate |
354 |
}
|
355 |
if (tmp) |
|
356 |
{
|
|
357 |
/* Give right error message */
|
|
358 |
thd->clear_error(); |
|
359 |
my_printf_error(ER_UNKNOWN_ERROR, |
|
360 |
"Failed to open '%-.64s', error while "
|
|
361 |
"unpacking from engine", |
|
362 |
MYF(0), table_list->table_name); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
363 |
return(0); |
1
by brian
clean slate |
364 |
}
|
365 |
/* Table existed in engine. Let's open it */
|
|
261.4.1
by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR. |
366 |
drizzle_reset_errors(thd, 1); // Clear warnings |
1
by brian
clean slate |
367 |
thd->clear_error(); // Clear error message |
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
368 |
return(get_table_share(thd, table_list, key, key_length, |
1
by brian
clean slate |
369 |
db_flags, error)); |
370 |
}
|
|
371 |
||
372 |
||
373 |
/*
|
|
374 |
Mark that we are not using table share anymore.
|
|
375 |
||
376 |
SYNOPSIS
|
|
377 |
release_table_share()
|
|
378 |
share Table share
|
|
379 |
release_type How the release should be done:
|
|
380 |
RELEASE_NORMAL
|
|
381 |
- Release without checking
|
|
382 |
RELEASE_WAIT_FOR_DROP
|
|
383 |
- Don't return until we get a signal that the
|
|
384 |
table is deleted or the thread is killed.
|
|
385 |
||
386 |
IMPLEMENTATION
|
|
387 |
If ref_count goes to zero and (we have done a refresh or if we have
|
|
388 |
already too many open table shares) then delete the definition.
|
|
389 |
||
390 |
If type == RELEASE_WAIT_FOR_DROP then don't return until we get a signal
|
|
391 |
that the table is deleted or the thread is killed.
|
|
392 |
*/
|
|
393 |
||
77.1.45
by Monty Taylor
Warning fixes. |
394 |
void release_table_share(TABLE_SHARE *share, |
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
395 |
enum release_type type __attribute__((unused))) |
1
by brian
clean slate |
396 |
{
|
397 |
bool to_be_deleted= 0; |
|
398 |
||
399 |
safe_mutex_assert_owner(&LOCK_open); |
|
400 |
||
401 |
pthread_mutex_lock(&share->mutex); |
|
402 |
if (!--share->ref_count) |
|
403 |
{
|
|
404 |
if (share->version != refresh_version) |
|
405 |
to_be_deleted=1; |
|
406 |
else
|
|
407 |
{
|
|
408 |
/* Link share last in used_table_share list */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
409 |
assert(share->next == 0); |
1
by brian
clean slate |
410 |
pthread_mutex_lock(&LOCK_table_share); |
411 |
share->prev= end_of_unused_share.prev; |
|
412 |
*end_of_unused_share.prev= share; |
|
413 |
end_of_unused_share.prev= &share->next; |
|
414 |
share->next= &end_of_unused_share; |
|
415 |
pthread_mutex_unlock(&LOCK_table_share); |
|
416 |
||
417 |
to_be_deleted= (table_def_cache.records > table_def_size); |
|
418 |
}
|
|
419 |
}
|
|
420 |
||
421 |
if (to_be_deleted) |
|
422 |
{
|
|
423 |
hash_delete(&table_def_cache, (uchar*) share); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
424 |
return; |
1
by brian
clean slate |
425 |
}
|
426 |
pthread_mutex_unlock(&share->mutex); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
427 |
return; |
1
by brian
clean slate |
428 |
}
|
429 |
||
430 |
||
431 |
/*
|
|
432 |
Check if table definition exits in cache
|
|
433 |
||
434 |
SYNOPSIS
|
|
435 |
get_cached_table_share()
|
|
436 |
db Database name
|
|
437 |
table_name Table name
|
|
438 |
||
439 |
RETURN
|
|
440 |
0 Not cached
|
|
441 |
# TABLE_SHARE for table
|
|
442 |
*/
|
|
443 |
||
444 |
TABLE_SHARE *get_cached_table_share(const char *db, const char *table_name) |
|
445 |
{
|
|
446 |
char key[NAME_LEN*2+2]; |
|
447 |
TABLE_LIST table_list; |
|
448 |
uint key_length; |
|
449 |
safe_mutex_assert_owner(&LOCK_open); |
|
450 |
||
451 |
table_list.db= (char*) db; |
|
452 |
table_list.table_name= (char*) table_name; |
|
453 |
key_length= create_table_def_key((THD*) 0, key, &table_list, 0); |
|
454 |
return (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key, key_length); |
|
455 |
}
|
|
456 |
||
457 |
||
458 |
/*
|
|
459 |
Close file handle, but leave the table in the table cache
|
|
460 |
||
461 |
SYNOPSIS
|
|
462 |
close_handle_and_leave_table_as_lock()
|
|
463 |
table Table handler
|
|
464 |
||
465 |
NOTES
|
|
466 |
By leaving the table in the table cache, it disallows any other thread
|
|
467 |
to open the table
|
|
468 |
||
469 |
thd->killed will be set if we run out of memory
|
|
470 |
||
471 |
If closing a MERGE child, the calling function has to take care for
|
|
472 |
closing the parent too, if necessary.
|
|
473 |
*/
|
|
474 |
||
475 |
||
476 |
void close_handle_and_leave_table_as_lock(TABLE *table) |
|
477 |
{
|
|
478 |
TABLE_SHARE *share, *old_share= table->s; |
|
479 |
char *key_buff; |
|
480 |
MEM_ROOT *mem_root= &table->mem_root; |
|
481 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
482 |
assert(table->db_stat); |
1
by brian
clean slate |
483 |
|
484 |
/*
|
|
485 |
Make a local copy of the table share and free the current one.
|
|
486 |
This has to be done to ensure that the table share is removed from
|
|
487 |
the table defintion cache as soon as the last instance is removed
|
|
488 |
*/
|
|
489 |
if (multi_alloc_root(mem_root, |
|
490 |
&share, sizeof(*share), |
|
491 |
&key_buff, old_share->table_cache_key.length, |
|
492 |
NULL)) |
|
493 |
{
|
|
212.6.6
by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove(). |
494 |
memset(share, 0, sizeof(*share)); |
1
by brian
clean slate |
495 |
share->set_table_cache_key(key_buff, old_share->table_cache_key.str, |
496 |
old_share->table_cache_key.length); |
|
497 |
share->tmp_table= INTERNAL_TMP_TABLE; // for intern_close_table() |
|
498 |
}
|
|
499 |
||
500 |
table->file->close(); |
|
501 |
table->db_stat= 0; // Mark file closed |
|
502 |
release_table_share(table->s, RELEASE_NORMAL); |
|
503 |
table->s= share; |
|
504 |
table->file->change_table_ptr(table, table->s); |
|
505 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
506 |
return; |
1
by brian
clean slate |
507 |
}
|
508 |
||
509 |
||
510 |
||
511 |
/*
|
|
512 |
Create a list for all open tables matching SQL expression
|
|
513 |
||
514 |
SYNOPSIS
|
|
515 |
list_open_tables()
|
|
516 |
thd Thread THD
|
|
517 |
wild SQL like expression
|
|
518 |
||
519 |
NOTES
|
|
520 |
One gets only a list of tables for which one has any kind of privilege.
|
|
521 |
db and table names are allocated in result struct, so one doesn't need
|
|
522 |
a lock on LOCK_open when traversing the return list.
|
|
523 |
||
524 |
RETURN VALUES
|
|
525 |
NULL Error (Probably OOM)
|
|
526 |
# Pointer to list of names of open tables.
|
|
527 |
*/
|
|
528 |
||
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
529 |
OPEN_TABLE_LIST *list_open_tables(THD *thd __attribute__((unused)), |
77.1.45
by Monty Taylor
Warning fixes. |
530 |
const char *db, const char *wild) |
1
by brian
clean slate |
531 |
{
|
532 |
int result = 0; |
|
533 |
OPEN_TABLE_LIST **start_list, *open_list; |
|
534 |
TABLE_LIST table_list; |
|
535 |
||
536 |
VOID(pthread_mutex_lock(&LOCK_open)); |
|
212.6.6
by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove(). |
537 |
memset(&table_list, 0, sizeof(table_list)); |
1
by brian
clean slate |
538 |
start_list= &open_list; |
539 |
open_list=0; |
|
540 |
||
541 |
for (uint idx=0 ; result == 0 && idx < open_cache.records; idx++) |
|
542 |
{
|
|
543 |
OPEN_TABLE_LIST *table; |
|
544 |
TABLE *entry=(TABLE*) hash_element(&open_cache,idx); |
|
545 |
TABLE_SHARE *share= entry->s; |
|
546 |
||
547 |
if (db && my_strcasecmp(system_charset_info, db, share->db.str)) |
|
548 |
continue; |
|
549 |
if (wild && wild_compare(share->table_name.str, wild, 0)) |
|
550 |
continue; |
|
551 |
||
552 |
/* Check if user has SELECT privilege for any column in the table */
|
|
553 |
table_list.db= share->db.str; |
|
554 |
table_list.table_name= share->table_name.str; |
|
555 |
||
556 |
/* need to check if we haven't already listed it */
|
|
557 |
for (table= open_list ; table ; table=table->next) |
|
558 |
{
|
|
559 |
if (!strcmp(table->table, share->table_name.str) && |
|
560 |
!strcmp(table->db, share->db.str)) |
|
561 |
{
|
|
562 |
if (entry->in_use) |
|
563 |
table->in_use++; |
|
564 |
if (entry->locked_by_name) |
|
565 |
table->locked++; |
|
566 |
break; |
|
567 |
}
|
|
568 |
}
|
|
569 |
if (table) |
|
570 |
continue; |
|
571 |
if (!(*start_list = (OPEN_TABLE_LIST *) |
|
572 |
sql_alloc(sizeof(**start_list)+share->table_cache_key.length))) |
|
573 |
{
|
|
574 |
open_list=0; // Out of memory |
|
575 |
break; |
|
576 |
}
|
|
266.1.21
by Monty Taylor
Removed references to strmov and strnmov |
577 |
stpcpy((*start_list)->table= |
578 |
stpcpy(((*start_list)->db= (char*) ((*start_list)+1)), |
|
1
by brian
clean slate |
579 |
share->db.str)+1, |
580 |
share->table_name.str); |
|
581 |
(*start_list)->in_use= entry->in_use ? 1 : 0; |
|
582 |
(*start_list)->locked= entry->locked_by_name ? 1 : 0; |
|
583 |
start_list= &(*start_list)->next; |
|
584 |
*start_list=0; |
|
585 |
}
|
|
586 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
587 |
return(open_list); |
1
by brian
clean slate |
588 |
}
|
589 |
||
590 |
/*****************************************************************************
|
|
591 |
* Functions to free open table cache
|
|
592 |
****************************************************************************/
|
|
593 |
||
594 |
||
595 |
void intern_close_table(TABLE *table) |
|
596 |
{ // Free all structures |
|
597 |
free_io_cache(table); |
|
598 |
if (table->file) // Not true if name lock |
|
599 |
VOID(closefrm(table, 1)); // close file |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
600 |
return; |
1
by brian
clean slate |
601 |
}
|
602 |
||
603 |
/*
|
|
604 |
Remove table from the open table cache
|
|
605 |
||
606 |
SYNOPSIS
|
|
607 |
free_cache_entry()
|
|
608 |
table Table to remove
|
|
609 |
||
610 |
NOTE
|
|
611 |
We need to have a lock on LOCK_open when calling this
|
|
612 |
*/
|
|
613 |
||
614 |
static void free_cache_entry(TABLE *table) |
|
615 |
{
|
|
616 |
intern_close_table(table); |
|
617 |
if (!table->in_use) |
|
618 |
{
|
|
619 |
table->next->prev=table->prev; /* remove from used chain */ |
|
620 |
table->prev->next=table->next; |
|
621 |
if (table == unused_tables) |
|
622 |
{
|
|
623 |
unused_tables=unused_tables->next; |
|
624 |
if (table == unused_tables) |
|
625 |
unused_tables=0; |
|
626 |
}
|
|
627 |
}
|
|
628 |
my_free((uchar*) table,MYF(0)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
629 |
return; |
1
by brian
clean slate |
630 |
}
|
631 |
||
632 |
/* Free resources allocated by filesort() and read_record() */
|
|
633 |
||
634 |
void free_io_cache(TABLE *table) |
|
635 |
{
|
|
636 |
if (table->sort.io_cache) |
|
637 |
{
|
|
638 |
close_cached_file(table->sort.io_cache); |
|
639 |
my_free((uchar*) table->sort.io_cache,MYF(0)); |
|
640 |
table->sort.io_cache=0; |
|
641 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
642 |
return; |
1
by brian
clean slate |
643 |
}
|
644 |
||
645 |
||
646 |
/*
|
|
647 |
Close all tables which aren't in use by any thread
|
|
648 |
||
649 |
@param thd Thread context
|
|
650 |
@param tables List of tables to remove from the cache
|
|
651 |
@param have_lock If LOCK_open is locked
|
|
652 |
@param wait_for_refresh Wait for a impending flush
|
|
653 |
@param wait_for_placeholders Wait for tables being reopened so that the GRL
|
|
654 |
won't proceed while write-locked tables are being reopened by other
|
|
655 |
threads.
|
|
656 |
||
55
by brian
Update for using real bool types. |
657 |
@remark THD can be NULL, but then wait_for_refresh must be false
|
1
by brian
clean slate |
658 |
and tables must be NULL.
|
659 |
*/
|
|
660 |
||
661 |
bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock, |
|
662 |
bool wait_for_refresh, bool wait_for_placeholders) |
|
663 |
{
|
|
664 |
bool result=0; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
665 |
assert(thd || (!wait_for_refresh && !tables)); |
1
by brian
clean slate |
666 |
|
667 |
if (!have_lock) |
|
668 |
VOID(pthread_mutex_lock(&LOCK_open)); |
|
669 |
if (!tables) |
|
670 |
{
|
|
671 |
refresh_version++; // Force close of open tables |
|
672 |
while (unused_tables) |
|
673 |
{
|
|
674 |
#ifdef EXTRA_DEBUG
|
|
675 |
if (hash_delete(&open_cache,(uchar*) unused_tables)) |
|
676 |
printf("Warning: Couldn't delete open table from hash\n"); |
|
677 |
#else
|
|
678 |
VOID(hash_delete(&open_cache,(uchar*) unused_tables)); |
|
679 |
#endif
|
|
680 |
}
|
|
681 |
/* Free table shares */
|
|
682 |
while (oldest_unused_share->next) |
|
683 |
{
|
|
684 |
pthread_mutex_lock(&oldest_unused_share->mutex); |
|
685 |
VOID(hash_delete(&table_def_cache, (uchar*) oldest_unused_share)); |
|
686 |
}
|
|
687 |
if (wait_for_refresh) |
|
688 |
{
|
|
689 |
/*
|
|
690 |
Other threads could wait in a loop in open_and_lock_tables(),
|
|
691 |
trying to lock one or more of our tables.
|
|
692 |
||
693 |
If they wait for the locks in thr_multi_lock(), their lock
|
|
694 |
request is aborted. They loop in open_and_lock_tables() and
|
|
695 |
enter open_table(). Here they notice the table is refreshed and
|
|
696 |
wait for COND_refresh. Then they loop again in
|
|
697 |
open_and_lock_tables() and this time open_table() succeeds. At
|
|
698 |
this moment, if we (the FLUSH TABLES thread) are scheduled and
|
|
699 |
on another FLUSH TABLES enter close_cached_tables(), they could
|
|
700 |
awake while we sleep below, waiting for others threads (us) to
|
|
701 |
close their open tables. If this happens, the other threads
|
|
702 |
would find the tables unlocked. They would get the locks, one
|
|
703 |
after the other, and could do their destructive work. This is an
|
|
704 |
issue if we have LOCK TABLES in effect.
|
|
705 |
||
706 |
The problem is that the other threads passed all checks in
|
|
707 |
open_table() before we refresh the table.
|
|
708 |
||
709 |
The fix for this problem is to set some_tables_deleted for all
|
|
710 |
threads with open tables. These threads can still get their
|
|
711 |
locks, but will immediately release them again after checking
|
|
712 |
this variable. They will then loop in open_and_lock_tables()
|
|
713 |
again. There they will wait until we update all tables version
|
|
714 |
below.
|
|
715 |
||
716 |
Setting some_tables_deleted is done by remove_table_from_cache()
|
|
717 |
in the other branch.
|
|
718 |
||
719 |
In other words (reviewer suggestion): You need this setting of
|
|
720 |
some_tables_deleted for the case when table was opened and all
|
|
721 |
related checks were passed before incrementing refresh_version
|
|
722 |
(which you already have) but attempt to lock the table happened
|
|
723 |
after the call to close_old_data_files() i.e. after removal of
|
|
724 |
current thread locks.
|
|
725 |
*/
|
|
726 |
for (uint idx=0 ; idx < open_cache.records ; idx++) |
|
727 |
{
|
|
728 |
TABLE *table=(TABLE*) hash_element(&open_cache,idx); |
|
729 |
if (table->in_use) |
|
730 |
table->in_use->some_tables_deleted= 1; |
|
731 |
}
|
|
732 |
}
|
|
733 |
}
|
|
734 |
else
|
|
735 |
{
|
|
736 |
bool found=0; |
|
737 |
for (TABLE_LIST *table= tables; table; table= table->next_local) |
|
738 |
{
|
|
739 |
if (remove_table_from_cache(thd, table->db, table->table_name, |
|
740 |
RTFC_OWNED_BY_THD_FLAG)) |
|
741 |
found=1; |
|
742 |
}
|
|
743 |
if (!found) |
|
744 |
wait_for_refresh=0; // Nothing to wait for |
|
745 |
}
|
|
746 |
||
747 |
if (wait_for_refresh) |
|
748 |
{
|
|
749 |
/*
|
|
750 |
If there is any table that has a lower refresh_version, wait until
|
|
751 |
this is closed (or this thread is killed) before returning
|
|
752 |
*/
|
|
753 |
thd->mysys_var->current_mutex= &LOCK_open; |
|
754 |
thd->mysys_var->current_cond= &COND_refresh; |
|
755 |
thd_proc_info(thd, "Flushing tables"); |
|
756 |
||
757 |
close_old_data_files(thd,thd->open_tables,1,1); |
|
758 |
mysql_ha_flush(thd); |
|
759 |
||
760 |
bool found=1; |
|
761 |
/* Wait until all threads has closed all the tables we had locked */
|
|
762 |
while (found && ! thd->killed) |
|
763 |
{
|
|
764 |
found=0; |
|
765 |
for (uint idx=0 ; idx < open_cache.records ; idx++) |
|
766 |
{
|
|
767 |
TABLE *table=(TABLE*) hash_element(&open_cache,idx); |
|
768 |
/* Avoid a self-deadlock. */
|
|
769 |
if (table->in_use == thd) |
|
770 |
continue; |
|
771 |
/*
|
|
772 |
Note that we wait here only for tables which are actually open, and
|
|
773 |
not for placeholders with TABLE::open_placeholder set. Waiting for
|
|
774 |
latter will cause deadlock in the following scenario, for example:
|
|
775 |
||
776 |
conn1: lock table t1 write;
|
|
777 |
conn2: lock table t2 write;
|
|
778 |
conn1: flush tables;
|
|
779 |
conn2: flush tables;
|
|
780 |
||
781 |
It also does not make sense to wait for those of placeholders that
|
|
782 |
are employed by CREATE TABLE as in this case table simply does not
|
|
783 |
exist yet.
|
|
784 |
*/
|
|
785 |
if (table->needs_reopen_or_name_lock() && (table->db_stat || |
|
786 |
(table->open_placeholder && wait_for_placeholders))) |
|
787 |
{
|
|
788 |
found=1; |
|
789 |
pthread_cond_wait(&COND_refresh,&LOCK_open); |
|
790 |
break; |
|
791 |
}
|
|
792 |
}
|
|
793 |
}
|
|
794 |
/*
|
|
795 |
No other thread has the locked tables open; reopen them and get the
|
|
796 |
old locks. This should always succeed (unless some external process
|
|
797 |
has removed the tables)
|
|
798 |
*/
|
|
799 |
thd->in_lock_tables=1; |
|
800 |
result=reopen_tables(thd,1,1); |
|
801 |
thd->in_lock_tables=0; |
|
802 |
/* Set version for table */
|
|
803 |
for (TABLE *table=thd->open_tables; table ; table= table->next) |
|
804 |
{
|
|
805 |
/*
|
|
806 |
Preserve the version (0) of write locked tables so that a impending
|
|
807 |
global read lock won't sneak in.
|
|
808 |
*/
|
|
809 |
if (table->reginfo.lock_type < TL_WRITE_ALLOW_WRITE) |
|
810 |
table->s->version= refresh_version; |
|
811 |
}
|
|
812 |
}
|
|
813 |
if (!have_lock) |
|
814 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
815 |
if (wait_for_refresh) |
|
816 |
{
|
|
817 |
pthread_mutex_lock(&thd->mysys_var->mutex); |
|
818 |
thd->mysys_var->current_mutex= 0; |
|
819 |
thd->mysys_var->current_cond= 0; |
|
820 |
thd_proc_info(thd, 0); |
|
821 |
pthread_mutex_unlock(&thd->mysys_var->mutex); |
|
822 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
823 |
return(result); |
1
by brian
clean slate |
824 |
}
|
825 |
||
826 |
||
827 |
/*
|
|
828 |
Close all tables which match specified connection string or
|
|
829 |
if specified string is NULL, then any table with a connection string.
|
|
830 |
*/
|
|
831 |
||
832 |
bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh, |
|
833 |
LEX_STRING *connection, bool have_lock) |
|
834 |
{
|
|
835 |
uint idx; |
|
836 |
TABLE_LIST tmp, *tables= NULL; |
|
55
by brian
Update for using real bool types. |
837 |
bool result= false; |
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
838 |
assert(thd); |
1
by brian
clean slate |
839 |
|
212.6.1
by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file. |
840 |
memset(&tmp, 0, sizeof(TABLE_LIST)); |
1
by brian
clean slate |
841 |
|
842 |
if (!have_lock) |
|
843 |
VOID(pthread_mutex_lock(&LOCK_open)); |
|
844 |
||
845 |
for (idx= 0; idx < table_def_cache.records; idx++) |
|
846 |
{
|
|
847 |
TABLE_SHARE *share= (TABLE_SHARE *) hash_element(&table_def_cache, idx); |
|
848 |
||
849 |
/* Ignore if table is not open or does not have a connect_string */
|
|
850 |
if (!share->connect_string.length || !share->ref_count) |
|
851 |
continue; |
|
852 |
||
853 |
/* Compare the connection string */
|
|
854 |
if (connection && |
|
855 |
(connection->length > share->connect_string.length || |
|
856 |
(connection->length < share->connect_string.length && |
|
857 |
(share->connect_string.str[connection->length] != '/' && |
|
858 |
share->connect_string.str[connection->length] != '\\')) || |
|
859 |
strncasecmp(connection->str, share->connect_string.str, |
|
860 |
connection->length))) |
|
861 |
continue; |
|
862 |
||
863 |
/* close_cached_tables() only uses these elements */
|
|
864 |
tmp.db= share->db.str; |
|
865 |
tmp.table_name= share->table_name.str; |
|
866 |
tmp.next_local= tables; |
|
867 |
||
868 |
tables= (TABLE_LIST *) memdup_root(thd->mem_root, (char*)&tmp, |
|
869 |
sizeof(TABLE_LIST)); |
|
870 |
}
|
|
871 |
||
872 |
if (tables) |
|
55
by brian
Update for using real bool types. |
873 |
result= close_cached_tables(thd, tables, true, false, false); |
1
by brian
clean slate |
874 |
|
875 |
if (!have_lock) |
|
876 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
877 |
||
878 |
if (if_wait_for_refresh) |
|
879 |
{
|
|
880 |
pthread_mutex_lock(&thd->mysys_var->mutex); |
|
881 |
thd->mysys_var->current_mutex= 0; |
|
882 |
thd->mysys_var->current_cond= 0; |
|
883 |
thd->proc_info=0; |
|
884 |
pthread_mutex_unlock(&thd->mysys_var->mutex); |
|
885 |
}
|
|
886 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
887 |
return(result); |
1
by brian
clean slate |
888 |
}
|
889 |
||
890 |
||
891 |
/**
|
|
892 |
Mark all temporary tables which were used by the current statement or
|
|
893 |
substatement as free for reuse, but only if the query_id can be cleared.
|
|
894 |
||
895 |
@param thd thread context
|
|
896 |
||
897 |
@remark For temp tables associated with a open SQL HANDLER the query_id
|
|
898 |
is not reset until the HANDLER is closed.
|
|
899 |
*/
|
|
900 |
||
901 |
static void mark_temp_tables_as_free_for_reuse(THD *thd) |
|
902 |
{
|
|
903 |
for (TABLE *table= thd->temporary_tables ; table ; table= table->next) |
|
904 |
{
|
|
905 |
if ((table->query_id == thd->query_id) && ! table->open_by_handler) |
|
906 |
{
|
|
907 |
table->query_id= 0; |
|
908 |
table->file->ha_reset(); |
|
909 |
}
|
|
910 |
}
|
|
911 |
}
|
|
912 |
||
913 |
||
914 |
/*
|
|
915 |
Mark all tables in the list which were used by current substatement
|
|
916 |
as free for reuse.
|
|
917 |
||
918 |
SYNOPSIS
|
|
919 |
mark_used_tables_as_free_for_reuse()
|
|
920 |
thd - thread context
|
|
921 |
table - head of the list of tables
|
|
922 |
||
923 |
DESCRIPTION
|
|
924 |
Marks all tables in the list which were used by current substatement
|
|
925 |
(they are marked by its query_id) as free for reuse.
|
|
926 |
||
927 |
NOTE
|
|
928 |
The reason we reset query_id is that it's not enough to just test
|
|
929 |
if table->query_id != thd->query_id to know if a table is in use.
|
|
930 |
||
931 |
For example
|
|
932 |
SELECT f1_that_uses_t1() FROM t1;
|
|
933 |
In f1_that_uses_t1() we will see one instance of t1 where query_id is
|
|
934 |
set to query_id of original query.
|
|
935 |
*/
|
|
936 |
||
937 |
static void mark_used_tables_as_free_for_reuse(THD *thd, TABLE *table) |
|
938 |
{
|
|
939 |
for (; table ; table= table->next) |
|
940 |
{
|
|
941 |
if (table->query_id == thd->query_id) |
|
942 |
{
|
|
943 |
table->query_id= 0; |
|
944 |
table->file->ha_reset(); |
|
945 |
}
|
|
946 |
}
|
|
947 |
}
|
|
948 |
||
949 |
||
950 |
/**
|
|
951 |
Auxiliary function to close all tables in the open_tables list.
|
|
952 |
||
953 |
@param thd Thread context.
|
|
954 |
||
955 |
@remark It should not ordinarily be called directly.
|
|
956 |
*/
|
|
957 |
||
958 |
static void close_open_tables(THD *thd) |
|
959 |
{
|
|
960 |
bool found_old_table= 0; |
|
961 |
||
962 |
safe_mutex_assert_not_owner(&LOCK_open); |
|
963 |
||
964 |
VOID(pthread_mutex_lock(&LOCK_open)); |
|
965 |
||
966 |
while (thd->open_tables) |
|
967 |
found_old_table|= close_thread_table(thd, &thd->open_tables); |
|
968 |
thd->some_tables_deleted= 0; |
|
969 |
||
970 |
/* Free tables to hold down open files */
|
|
971 |
while (open_cache.records > table_cache_size && unused_tables) |
|
972 |
VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ |
|
973 |
if (found_old_table) |
|
974 |
{
|
|
975 |
/* Tell threads waiting for refresh that something has happened */
|
|
976 |
broadcast_refresh(); |
|
977 |
}
|
|
978 |
||
979 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
980 |
}
|
|
981 |
||
982 |
||
983 |
/*
|
|
984 |
Close all tables used by the current substatement, or all tables
|
|
985 |
used by this thread if we are on the upper level.
|
|
986 |
||
987 |
SYNOPSIS
|
|
988 |
close_thread_tables()
|
|
989 |
thd Thread handler
|
|
990 |
||
991 |
IMPLEMENTATION
|
|
992 |
Unlocks tables and frees derived tables.
|
|
993 |
Put all normal tables used by thread in free list.
|
|
994 |
||
995 |
It will only close/mark as free for reuse tables opened by this
|
|
996 |
substatement, it will also check if we are closing tables after
|
|
997 |
execution of complete query (i.e. we are on upper level) and will
|
|
998 |
leave prelocked mode if needed.
|
|
999 |
*/
|
|
1000 |
||
1001 |
void close_thread_tables(THD *thd) |
|
1002 |
{
|
|
1003 |
TABLE *table; |
|
1004 |
||
1005 |
/*
|
|
1006 |
We are assuming here that thd->derived_tables contains ONLY derived
|
|
1007 |
tables for this substatement. i.e. instead of approach which uses
|
|
1008 |
query_id matching for determining which of the derived tables belong
|
|
1009 |
to this substatement we rely on the ability of substatements to
|
|
1010 |
save/restore thd->derived_tables during their execution.
|
|
1011 |
||
1012 |
TODO: Probably even better approach is to simply associate list of
|
|
1013 |
derived tables with (sub-)statement instead of thread and destroy
|
|
1014 |
them at the end of its execution.
|
|
1015 |
*/
|
|
1016 |
if (thd->derived_tables) |
|
1017 |
{
|
|
1018 |
TABLE *next; |
|
1019 |
/*
|
|
1020 |
Close all derived tables generated in queries like
|
|
1021 |
SELECT * FROM (SELECT * FROM t1)
|
|
1022 |
*/
|
|
1023 |
for (table= thd->derived_tables ; table ; table= next) |
|
1024 |
{
|
|
1025 |
next= table->next; |
|
1026 |
free_tmp_table(thd, table); |
|
1027 |
}
|
|
1028 |
thd->derived_tables= 0; |
|
1029 |
}
|
|
1030 |
||
1031 |
/*
|
|
1032 |
Mark all temporary tables used by this statement as free for reuse.
|
|
1033 |
*/
|
|
1034 |
mark_temp_tables_as_free_for_reuse(thd); |
|
1035 |
/*
|
|
1036 |
Let us commit transaction for statement. Since in 5.0 we only have
|
|
1037 |
one statement transaction and don't allow several nested statement
|
|
1038 |
transactions this call will do nothing if we are inside of stored
|
|
1039 |
function or trigger (i.e. statement transaction is already active and
|
|
1040 |
does not belong to statement for which we do close_thread_tables()).
|
|
1041 |
TODO: This should be fixed in later releases.
|
|
1042 |
*/
|
|
1043 |
if (!(thd->state_flags & Open_tables_state::BACKUPS_AVAIL)) |
|
1044 |
{
|
|
55
by brian
Update for using real bool types. |
1045 |
thd->main_da.can_overwrite_status= true; |
1
by brian
clean slate |
1046 |
ha_autocommit_or_rollback(thd, thd->is_error()); |
55
by brian
Update for using real bool types. |
1047 |
thd->main_da.can_overwrite_status= false; |
1
by brian
clean slate |
1048 |
thd->transaction.stmt.reset(); |
1049 |
}
|
|
1050 |
||
1051 |
if (thd->locked_tables) |
|
1052 |
{
|
|
1053 |
||
1054 |
/* Ensure we are calling ha_reset() for all used tables */
|
|
1055 |
mark_used_tables_as_free_for_reuse(thd, thd->open_tables); |
|
1056 |
||
1057 |
/*
|
|
1058 |
We are under simple LOCK TABLES so should not do anything else.
|
|
1059 |
*/
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1060 |
return; |
1
by brian
clean slate |
1061 |
}
|
1062 |
||
1063 |
if (thd->lock) |
|
1064 |
{
|
|
1065 |
/*
|
|
1066 |
For RBR we flush the pending event just before we unlock all the
|
|
1067 |
tables. This means that we are at the end of a topmost
|
|
1068 |
statement, so we ensure that the STMT_END_F flag is set on the
|
|
1069 |
pending event. For statements that are *inside* stored
|
|
1070 |
functions, the pending event will not be flushed: that will be
|
|
1071 |
handled either before writing a query log event (inside
|
|
1072 |
binlog_query()) or when preparing a pending event.
|
|
1073 |
*/
|
|
55
by brian
Update for using real bool types. |
1074 |
thd->binlog_flush_pending_rows_event(true); |
1
by brian
clean slate |
1075 |
mysql_unlock_tables(thd, thd->lock); |
1076 |
thd->lock=0; |
|
1077 |
}
|
|
1078 |
/*
|
|
1079 |
Note that we need to hold LOCK_open while changing the
|
|
1080 |
open_tables list. Another thread may work on it.
|
|
1081 |
(See: remove_table_from_cache(), mysql_wait_completed_table())
|
|
1082 |
Closing a MERGE child before the parent would be fatal if the
|
|
1083 |
other thread tries to abort the MERGE lock in between.
|
|
1084 |
*/
|
|
1085 |
if (thd->open_tables) |
|
1086 |
close_open_tables(thd); |
|
1087 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1088 |
return; |
1
by brian
clean slate |
1089 |
}
|
1090 |
||
1091 |
||
1092 |
/* move one table to free list */
|
|
1093 |
||
1094 |
bool close_thread_table(THD *thd, TABLE **table_ptr) |
|
1095 |
{
|
|
1096 |
bool found_old_table= 0; |
|
1097 |
TABLE *table= *table_ptr; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1098 |
|
1099 |
assert(table->key_read == 0); |
|
1100 |
assert(!table->file || table->file->inited == handler::NONE); |
|
1
by brian
clean slate |
1101 |
|
1102 |
*table_ptr=table->next; |
|
1103 |
||
1104 |
if (table->needs_reopen_or_name_lock() || |
|
1105 |
thd->version != refresh_version || !table->db_stat) |
|
1106 |
{
|
|
1107 |
VOID(hash_delete(&open_cache,(uchar*) table)); |
|
1108 |
found_old_table=1; |
|
1109 |
}
|
|
1110 |
else
|
|
1111 |
{
|
|
1112 |
/*
|
|
1113 |
Open placeholders have TABLE::db_stat set to 0, so they should be
|
|
1114 |
handled by the first alternative.
|
|
1115 |
*/
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1116 |
assert(!table->open_placeholder); |
1
by brian
clean slate |
1117 |
|
1118 |
/* Free memory and reset for next loop */
|
|
1119 |
table->file->ha_reset(); |
|
1120 |
table->in_use=0; |
|
1121 |
if (unused_tables) |
|
1122 |
{
|
|
1123 |
table->next=unused_tables; /* Link in last */ |
|
1124 |
table->prev=unused_tables->prev; |
|
1125 |
unused_tables->prev=table; |
|
1126 |
table->prev->next=table; |
|
1127 |
}
|
|
1128 |
else
|
|
1129 |
unused_tables=table->next=table->prev=table; |
|
1130 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1131 |
return(found_old_table); |
1
by brian
clean slate |
1132 |
}
|
1133 |
||
1134 |
||
1135 |
/* close_temporary_tables' internal, 4 is due to uint4korr definition */
|
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
1136 |
static inline uint tmpkeyval(THD *thd __attribute__((unused)), |
77.1.45
by Monty Taylor
Warning fixes. |
1137 |
TABLE *table) |
1
by brian
clean slate |
1138 |
{
|
1139 |
return uint4korr(table->s->table_cache_key.str + table->s->table_cache_key.length - 4); |
|
1140 |
}
|
|
1141 |
||
1142 |
||
1143 |
/*
|
|
1144 |
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
|
|
1145 |
creates one DROP TEMPORARY TABLE binlog event for each pseudo-thread
|
|
1146 |
*/
|
|
1147 |
||
1148 |
void close_temporary_tables(THD *thd) |
|
1149 |
{
|
|
1150 |
TABLE *table; |
|
1151 |
TABLE *next= NULL; |
|
1152 |
TABLE *prev_table; |
|
1153 |
/* Assume thd->options has OPTION_QUOTE_SHOW_CREATE */
|
|
55
by brian
Update for using real bool types. |
1154 |
bool was_quote_show= true; |
1
by brian
clean slate |
1155 |
|
1156 |
if (!thd->temporary_tables) |
|
1157 |
return; |
|
1158 |
||
1159 |
if (!mysql_bin_log.is_open() || thd->current_stmt_binlog_row_based) |
|
1160 |
{
|
|
1161 |
TABLE *tmp_next; |
|
1162 |
for (table= thd->temporary_tables; table; table= tmp_next) |
|
1163 |
{
|
|
1164 |
tmp_next= table->next; |
|
1165 |
close_temporary(table, 1, 1); |
|
1166 |
}
|
|
1167 |
thd->temporary_tables= 0; |
|
1168 |
return; |
|
1169 |
}
|
|
1170 |
||
1171 |
/* Better add "if exists", in case a RESET MASTER has been done */
|
|
1172 |
const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "; |
|
1173 |
uint stub_len= sizeof(stub) - 1; |
|
1174 |
char buf[256]; |
|
1175 |
String s_query= String(buf, sizeof(buf), system_charset_info); |
|
55
by brian
Update for using real bool types. |
1176 |
bool found_user_tables= false; |
1
by brian
clean slate |
1177 |
|
1178 |
memcpy(buf, stub, stub_len); |
|
1179 |
||
1180 |
/*
|
|
1181 |
Insertion sort of temp tables by pseudo_thread_id to build ordered list
|
|
1182 |
of sublists of equal pseudo_thread_id
|
|
1183 |
*/
|
|
1184 |
||
1185 |
for (prev_table= thd->temporary_tables, table= prev_table->next; |
|
1186 |
table; |
|
1187 |
prev_table= table, table= table->next) |
|
1188 |
{
|
|
1189 |
TABLE *prev_sorted /* same as for prev_table */, *sorted; |
|
1190 |
if (is_user_table(table)) |
|
1191 |
{
|
|
1192 |
if (!found_user_tables) |
|
1193 |
found_user_tables= true; |
|
1194 |
for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table; |
|
1195 |
prev_sorted= sorted, sorted= sorted->next) |
|
1196 |
{
|
|
1197 |
if (!is_user_table(sorted) || |
|
1198 |
tmpkeyval(thd, sorted) > tmpkeyval(thd, table)) |
|
1199 |
{
|
|
1200 |
/* move into the sorted part of the list from the unsorted */
|
|
1201 |
prev_table->next= table->next; |
|
1202 |
table->next= sorted; |
|
1203 |
if (prev_sorted) |
|
1204 |
{
|
|
1205 |
prev_sorted->next= table; |
|
1206 |
}
|
|
1207 |
else
|
|
1208 |
{
|
|
1209 |
thd->temporary_tables= table; |
|
1210 |
}
|
|
1211 |
table= prev_table; |
|
1212 |
break; |
|
1213 |
}
|
|
1214 |
}
|
|
1215 |
}
|
|
1216 |
}
|
|
1217 |
||
1218 |
/* We always quote db,table names though it is slight overkill */
|
|
1219 |
if (found_user_tables && |
|
1220 |
!(was_quote_show= test(thd->options & OPTION_QUOTE_SHOW_CREATE))) |
|
1221 |
{
|
|
1222 |
thd->options |= OPTION_QUOTE_SHOW_CREATE; |
|
1223 |
}
|
|
1224 |
||
1225 |
/* scan sorted tmps to generate sequence of DROP */
|
|
1226 |
for (table= thd->temporary_tables; table; table= next) |
|
1227 |
{
|
|
1228 |
if (is_user_table(table)) |
|
1229 |
{
|
|
1230 |
my_thread_id save_pseudo_thread_id= thd->variables.pseudo_thread_id; |
|
1231 |
/* Set pseudo_thread_id to be that of the processed table */
|
|
1232 |
thd->variables.pseudo_thread_id= tmpkeyval(thd, table); |
|
1233 |
/*
|
|
1234 |
Loop forward through all tables within the sublist of
|
|
1235 |
common pseudo_thread_id to create single DROP query.
|
|
1236 |
*/
|
|
1237 |
for (s_query.length(stub_len); |
|
1238 |
table && is_user_table(table) && |
|
1239 |
tmpkeyval(thd, table) == thd->variables.pseudo_thread_id; |
|
1240 |
table= next) |
|
1241 |
{
|
|
1242 |
/*
|
|
1243 |
We are going to add 4 ` around the db/table names and possible more
|
|
1244 |
due to special characters in the names
|
|
1245 |
*/
|
|
1246 |
append_identifier(thd, &s_query, table->s->db.str, strlen(table->s->db.str)); |
|
1247 |
s_query.append('.'); |
|
1248 |
append_identifier(thd, &s_query, table->s->table_name.str, |
|
1249 |
strlen(table->s->table_name.str)); |
|
1250 |
s_query.append(','); |
|
1251 |
next= table->next; |
|
1252 |
close_temporary(table, 1, 1); |
|
1253 |
}
|
|
1254 |
thd->clear_error(); |
|
264.2.6
by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code. |
1255 |
const CHARSET_INFO * const cs_save= thd->variables.character_set_client; |
1
by brian
clean slate |
1256 |
thd->variables.character_set_client= system_charset_info; |
1257 |
Query_log_event qinfo(thd, s_query.ptr(), |
|
1258 |
s_query.length() - 1 /* to remove trailing ',' */, |
|
55
by brian
Update for using real bool types. |
1259 |
0, false); |
1
by brian
clean slate |
1260 |
thd->variables.character_set_client= cs_save; |
1261 |
/*
|
|
1262 |
Imagine the thread had created a temp table, then was doing a
|
|
1263 |
SELECT, and the SELECT was killed. Then it's not clever to
|
|
1264 |
mark the statement above as "killed", because it's not really
|
|
1265 |
a statement updating data, and there are 99.99% chances it
|
|
1266 |
will succeed on slave. If a real update (one updating a
|
|
1267 |
persistent table) was killed on the master, then this real
|
|
1268 |
update will be logged with error_code=killed, rightfully
|
|
1269 |
causing the slave to stop.
|
|
1270 |
*/
|
|
1271 |
qinfo.error_code= 0; |
|
1272 |
mysql_bin_log.write(&qinfo); |
|
1273 |
thd->variables.pseudo_thread_id= save_pseudo_thread_id; |
|
1274 |
}
|
|
1275 |
else
|
|
1276 |
{
|
|
1277 |
next= table->next; |
|
1278 |
close_temporary(table, 1, 1); |
|
1279 |
}
|
|
1280 |
}
|
|
1281 |
if (!was_quote_show) |
|
1282 |
thd->options&= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */ |
|
1283 |
thd->temporary_tables=0; |
|
1284 |
}
|
|
1285 |
||
1286 |
/*
|
|
1287 |
Find table in list.
|
|
1288 |
||
1289 |
SYNOPSIS
|
|
1290 |
find_table_in_list()
|
|
1291 |
table Pointer to table list
|
|
1292 |
offset Offset to which list in table structure to use
|
|
1293 |
db_name Data base name
|
|
1294 |
table_name Table name
|
|
1295 |
||
1296 |
NOTES:
|
|
1297 |
This is called by find_table_in_local_list() and
|
|
1298 |
find_table_in_global_list().
|
|
1299 |
||
1300 |
RETURN VALUES
|
|
1301 |
NULL Table not found
|
|
1302 |
# Pointer to found table.
|
|
1303 |
*/
|
|
1304 |
||
1305 |
TABLE_LIST *find_table_in_list(TABLE_LIST *table, |
|
1306 |
TABLE_LIST *TABLE_LIST::*link, |
|
1307 |
const char *db_name, |
|
1308 |
const char *table_name) |
|
1309 |
{
|
|
1310 |
for (; table; table= table->*link ) |
|
1311 |
{
|
|
1312 |
if ((table->table == 0 || table->table->s->tmp_table == NO_TMP_TABLE) && |
|
1313 |
strcmp(table->db, db_name) == 0 && |
|
1314 |
strcmp(table->table_name, table_name) == 0) |
|
1315 |
break; |
|
1316 |
}
|
|
1317 |
return table; |
|
1318 |
}
|
|
1319 |
||
1320 |
||
1321 |
/*
|
|
1322 |
Test that table is unique (It's only exists once in the table list)
|
|
1323 |
||
1324 |
SYNOPSIS
|
|
1325 |
unique_table()
|
|
1326 |
thd thread handle
|
|
1327 |
table table which should be checked
|
|
1328 |
table_list list of tables
|
|
1329 |
check_alias whether to check tables' aliases
|
|
1330 |
||
1331 |
NOTE: to exclude derived tables from check we use following mechanism:
|
|
1332 |
a) during derived table processing set THD::derived_tables_processing
|
|
1333 |
b) JOIN::prepare set SELECT::exclude_from_table_unique_test if
|
|
1334 |
THD::derived_tables_processing set. (we can't use JOIN::execute
|
|
1335 |
because for PS we perform only JOIN::prepare, but we can't set this
|
|
1336 |
flag in JOIN::prepare if we are not sure that we are in derived table
|
|
1337 |
processing loop, because multi-update call fix_fields() for some its
|
|
1338 |
items (which mean JOIN::prepare for subqueries) before unique_table
|
|
1339 |
call to detect which tables should be locked for write).
|
|
1340 |
c) unique_table skip all tables which belong to SELECT with
|
|
1341 |
SELECT::exclude_from_table_unique_test set.
|
|
1342 |
Also SELECT::exclude_from_table_unique_test used to exclude from check
|
|
1343 |
tables of main SELECT of multi-delete and multi-update
|
|
1344 |
||
1345 |
We also skip tables with TABLE_LIST::prelocking_placeholder set,
|
|
1346 |
because we want to allow SELECTs from them, and their modification
|
|
1347 |
will rise the error anyway.
|
|
1348 |
||
1349 |
TODO: when we will have table/view change detection we can do this check
|
|
1350 |
only once for PS/SP
|
|
1351 |
||
1352 |
RETURN
|
|
1353 |
found duplicate
|
|
1354 |
0 if table is unique
|
|
1355 |
*/
|
|
1356 |
||
1357 |
TABLE_LIST* unique_table(THD *thd, TABLE_LIST *table, TABLE_LIST *table_list, |
|
1358 |
bool check_alias) |
|
1359 |
{
|
|
1360 |
TABLE_LIST *res; |
|
1361 |
const char *d_name, *t_name, *t_alias; |
|
1362 |
||
1363 |
/*
|
|
1364 |
If this function called for query which update table (INSERT/UPDATE/...)
|
|
1365 |
then we have in table->table pointer to TABLE object which we are
|
|
1366 |
updating even if it is VIEW so we need TABLE_LIST of this TABLE object
|
|
1367 |
to get right names (even if lower_case_table_names used).
|
|
1368 |
||
1369 |
If this function called for CREATE command that we have not opened table
|
|
1370 |
(table->table equal to 0) and right names is in current TABLE_LIST
|
|
1371 |
object.
|
|
1372 |
*/
|
|
1373 |
if (table->table) |
|
1374 |
{
|
|
1375 |
/* temporary table is always unique */
|
|
1376 |
if (table->table && table->table->s->tmp_table != NO_TMP_TABLE) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1377 |
return(0); |
1
by brian
clean slate |
1378 |
table= table->find_underlying_table(table->table); |
1379 |
/*
|
|
1380 |
as far as we have table->table we have to find real TABLE_LIST of
|
|
1381 |
it in underlying tables
|
|
1382 |
*/
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1383 |
assert(table); |
1
by brian
clean slate |
1384 |
}
|
1385 |
d_name= table->db; |
|
1386 |
t_name= table->table_name; |
|
1387 |
t_alias= table->alias; |
|
1388 |
||
1389 |
for (;;) |
|
1390 |
{
|
|
1391 |
if (((! (res= find_table_in_global_list(table_list, d_name, t_name))) && |
|
1392 |
(! (res= mysql_lock_have_duplicate(thd, table, table_list)))) || |
|
1393 |
((!res->table || res->table != table->table) && |
|
1394 |
(!check_alias || !(lower_case_table_names ? |
|
1395 |
my_strcasecmp(files_charset_info, t_alias, res->alias) : |
|
1396 |
strcmp(t_alias, res->alias))) && |
|
1397 |
res->select_lex && !res->select_lex->exclude_from_table_unique_test)) |
|
1398 |
break; |
|
1399 |
/*
|
|
1400 |
If we found entry of this table or table of SELECT which already
|
|
1401 |
processed in derived table or top select of multi-update/multi-delete
|
|
1402 |
(exclude_from_table_unique_test) or prelocking placeholder.
|
|
1403 |
*/
|
|
1404 |
table_list= res->next_global; |
|
1405 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1406 |
return(res); |
1
by brian
clean slate |
1407 |
}
|
1408 |
||
1409 |
||
1410 |
/*
|
|
1411 |
Issue correct error message in case we found 2 duplicate tables which
|
|
1412 |
prevent some update operation
|
|
1413 |
||
1414 |
SYNOPSIS
|
|
1415 |
update_non_unique_table_error()
|
|
1416 |
update table which we try to update
|
|
1417 |
operation name of update operation
|
|
1418 |
duplicate duplicate table which we found
|
|
1419 |
||
1420 |
NOTE:
|
|
1421 |
here we hide view underlying tables if we have them
|
|
1422 |
*/
|
|
1423 |
||
1424 |
void update_non_unique_table_error(TABLE_LIST *update, |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
1425 |
const char *operation __attribute__((unused)), |
1426 |
TABLE_LIST *duplicate __attribute__((unused))) |
|
1
by brian
clean slate |
1427 |
{
|
1428 |
my_error(ER_UPDATE_TABLE_USED, MYF(0), update->alias); |
|
1429 |
}
|
|
1430 |
||
1431 |
||
1432 |
TABLE *find_temporary_table(THD *thd, const char *db, const char *table_name) |
|
1433 |
{
|
|
1434 |
TABLE_LIST table_list; |
|
1435 |
||
1436 |
table_list.db= (char*) db; |
|
1437 |
table_list.table_name= (char*) table_name; |
|
1438 |
return find_temporary_table(thd, &table_list); |
|
1439 |
}
|
|
1440 |
||
1441 |
||
1442 |
TABLE *find_temporary_table(THD *thd, TABLE_LIST *table_list) |
|
1443 |
{
|
|
1444 |
char key[MAX_DBKEY_LENGTH]; |
|
1445 |
uint key_length; |
|
1446 |
TABLE *table; |
|
1447 |
||
1448 |
key_length= create_table_def_key(thd, key, table_list, 1); |
|
1449 |
for (table=thd->temporary_tables ; table ; table= table->next) |
|
1450 |
{
|
|
1451 |
if (table->s->table_cache_key.length == key_length && |
|
1452 |
!memcmp(table->s->table_cache_key.str, key, key_length)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1453 |
return(table); |
1
by brian
clean slate |
1454 |
}
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1455 |
return(0); // Not a temporary table |
1
by brian
clean slate |
1456 |
}
|
1457 |
||
1458 |
||
1459 |
/**
|
|
1460 |
Drop a temporary table.
|
|
1461 |
||
1462 |
Try to locate the table in the list of thd->temporary_tables.
|
|
1463 |
If the table is found:
|
|
1464 |
- if the table is being used by some outer statement, fail.
|
|
1465 |
- if the table is in thd->locked_tables, unlock it and
|
|
1466 |
remove it from the list of locked tables. Currently only transactional
|
|
1467 |
temporary tables are present in the locked_tables list.
|
|
1468 |
- Close the temporary table, remove its .FRM
|
|
1469 |
- remove the table from the list of temporary tables
|
|
1470 |
||
1471 |
This function is used to drop user temporary tables, as well as
|
|
1472 |
internal tables created in CREATE TEMPORARY TABLE ... SELECT
|
|
1473 |
or ALTER TABLE. Even though part of the work done by this function
|
|
1474 |
is redundant when the table is internal, as long as we
|
|
1475 |
link both internal and user temporary tables into the same
|
|
1476 |
thd->temporary_tables list, it's impossible to tell here whether
|
|
1477 |
we're dealing with an internal or a user temporary table.
|
|
1478 |
||
1479 |
@retval 0 the table was found and dropped successfully.
|
|
1480 |
@retval 1 the table was not found in the list of temporary tables
|
|
1481 |
of this thread
|
|
1482 |
@retval -1 the table is in use by a outer query
|
|
1483 |
*/
|
|
1484 |
||
1485 |
int drop_temporary_table(THD *thd, TABLE_LIST *table_list) |
|
1486 |
{
|
|
1487 |
TABLE *table; |
|
1488 |
||
1489 |
if (!(table= find_temporary_table(thd, table_list))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1490 |
return(1); |
1
by brian
clean slate |
1491 |
|
1492 |
/* Table might be in use by some outer statement. */
|
|
1493 |
if (table->query_id && table->query_id != thd->query_id) |
|
1494 |
{
|
|
1495 |
my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1496 |
return(-1); |
1
by brian
clean slate |
1497 |
}
|
1498 |
||
1499 |
/*
|
|
1500 |
If LOCK TABLES list is not empty and contains this table,
|
|
1501 |
unlock the table and remove the table from this list.
|
|
1502 |
*/
|
|
55
by brian
Update for using real bool types. |
1503 |
mysql_lock_remove(thd, thd->locked_tables, table, false); |
1
by brian
clean slate |
1504 |
close_temporary_table(thd, table, 1, 1); |
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1505 |
return(0); |
1
by brian
clean slate |
1506 |
}
|
1507 |
||
1508 |
/*
|
|
1509 |
unlink from thd->temporary tables and close temporary table
|
|
1510 |
*/
|
|
1511 |
||
1512 |
void close_temporary_table(THD *thd, TABLE *table, |
|
1513 |
bool free_share, bool delete_table) |
|
1514 |
{
|
|
1515 |
if (table->prev) |
|
1516 |
{
|
|
1517 |
table->prev->next= table->next; |
|
1518 |
if (table->prev->next) |
|
1519 |
table->next->prev= table->prev; |
|
1520 |
}
|
|
1521 |
else
|
|
1522 |
{
|
|
1523 |
/* removing the item from the list */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1524 |
assert(table == thd->temporary_tables); |
1
by brian
clean slate |
1525 |
/*
|
1526 |
slave must reset its temporary list pointer to zero to exclude
|
|
1527 |
passing non-zero value to end_slave via rli->save_temporary_tables
|
|
1528 |
when no temp tables opened, see an invariant below.
|
|
1529 |
*/
|
|
1530 |
thd->temporary_tables= table->next; |
|
1531 |
if (thd->temporary_tables) |
|
1532 |
table->next->prev= 0; |
|
1533 |
}
|
|
1534 |
if (thd->slave_thread) |
|
1535 |
{
|
|
1536 |
/* natural invariant of temporary_tables */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1537 |
assert(slave_open_temp_tables || !thd->temporary_tables); |
1
by brian
clean slate |
1538 |
slave_open_temp_tables--; |
1539 |
}
|
|
1540 |
close_temporary(table, free_share, delete_table); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1541 |
return; |
1
by brian
clean slate |
1542 |
}
|
1543 |
||
1544 |
||
1545 |
/*
|
|
1546 |
Close and delete a temporary table
|
|
1547 |
||
1548 |
NOTE
|
|
1549 |
This dosn't unlink table from thd->temporary
|
|
1550 |
If this is needed, use close_temporary_table()
|
|
1551 |
*/
|
|
1552 |
||
1553 |
void close_temporary(TABLE *table, bool free_share, bool delete_table) |
|
1554 |
{
|
|
1555 |
handlerton *table_type= table->s->db_type(); |
|
1556 |
||
1557 |
free_io_cache(table); |
|
1558 |
closefrm(table, 0); |
|
1559 |
/*
|
|
1560 |
Check that temporary table has not been created with
|
|
1561 |
frm_only because it has then not been created in any storage engine
|
|
1562 |
*/
|
|
1563 |
if (delete_table) |
|
1564 |
rm_temporary_table(table_type, table->s->path.str, |
|
1565 |
table->s->tmp_table == TMP_TABLE_FRM_FILE_ONLY); |
|
1566 |
if (free_share) |
|
1567 |
{
|
|
1568 |
free_table_share(table->s); |
|
1569 |
my_free((char*) table,MYF(0)); |
|
1570 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1571 |
return; |
1
by brian
clean slate |
1572 |
}
|
1573 |
||
1574 |
||
1575 |
/*
|
|
1576 |
Used by ALTER TABLE when the table is a temporary one. It changes something
|
|
1577 |
only if the ALTER contained a RENAME clause (otherwise, table_name is the old
|
|
1578 |
name).
|
|
1579 |
Prepares a table cache key, which is the concatenation of db, table_name and
|
|
1580 |
thd->slave_proxy_id, separated by '\0'.
|
|
1581 |
*/
|
|
1582 |
||
1583 |
bool rename_temporary_table(THD* thd, TABLE *table, const char *db, |
|
1584 |
const char *table_name) |
|
1585 |
{
|
|
1586 |
char *key; |
|
1587 |
uint key_length; |
|
1588 |
TABLE_SHARE *share= table->s; |
|
1589 |
TABLE_LIST table_list; |
|
1590 |
||
1591 |
if (!(key=(char*) alloc_root(&share->mem_root, MAX_DBKEY_LENGTH))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1592 |
return(1); /* purecov: inspected */ |
1
by brian
clean slate |
1593 |
|
1594 |
table_list.db= (char*) db; |
|
1595 |
table_list.table_name= (char*) table_name; |
|
1596 |
key_length= create_table_def_key(thd, key, &table_list, 1); |
|
1597 |
share->set_table_cache_key(key, key_length); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1598 |
return(0); |
1
by brian
clean slate |
1599 |
}
|
1600 |
||
1601 |
||
1602 |
/* move table first in unused links */
|
|
1603 |
||
1604 |
static void relink_unused(TABLE *table) |
|
1605 |
{
|
|
1606 |
if (table != unused_tables) |
|
1607 |
{
|
|
1608 |
table->prev->next=table->next; /* Remove from unused list */ |
|
1609 |
table->next->prev=table->prev; |
|
1610 |
table->next=unused_tables; /* Link in unused tables */ |
|
1611 |
table->prev=unused_tables->prev; |
|
1612 |
unused_tables->prev->next=table; |
|
1613 |
unused_tables->prev=table; |
|
1614 |
unused_tables=table; |
|
1615 |
}
|
|
1616 |
}
|
|
1617 |
||
1618 |
||
1619 |
/**
|
|
1620 |
Remove all instances of table from thread's open list and
|
|
1621 |
table cache.
|
|
1622 |
||
1623 |
@param thd Thread context
|
|
1624 |
@param find Table to remove
|
|
55
by brian
Update for using real bool types. |
1625 |
@param unlock true - free all locks on tables removed that are
|
1
by brian
clean slate |
1626 |
done with LOCK TABLES
|
55
by brian
Update for using real bool types. |
1627 |
false - otherwise
|
1
by brian
clean slate |
1628 |
|
55
by brian
Update for using real bool types. |
1629 |
@note When unlock parameter is false or current thread doesn't have
|
1
by brian
clean slate |
1630 |
any tables locked with LOCK TABLES, tables are assumed to be
|
1631 |
not locked (for example already unlocked).
|
|
1632 |
*/
|
|
1633 |
||
1634 |
void unlink_open_table(THD *thd, TABLE *find, bool unlock) |
|
1635 |
{
|
|
1636 |
char key[MAX_DBKEY_LENGTH]; |
|
1637 |
uint key_length= find->s->table_cache_key.length; |
|
1638 |
TABLE *list, **prev; |
|
1639 |
||
1640 |
safe_mutex_assert_owner(&LOCK_open); |
|
1641 |
||
1642 |
memcpy(key, find->s->table_cache_key.str, key_length); |
|
1643 |
/*
|
|
1644 |
Note that we need to hold LOCK_open while changing the
|
|
1645 |
open_tables list. Another thread may work on it.
|
|
1646 |
(See: remove_table_from_cache(), mysql_wait_completed_table())
|
|
1647 |
Closing a MERGE child before the parent would be fatal if the
|
|
1648 |
other thread tries to abort the MERGE lock in between.
|
|
1649 |
*/
|
|
1650 |
for (prev= &thd->open_tables; *prev; ) |
|
1651 |
{
|
|
1652 |
list= *prev; |
|
1653 |
||
1654 |
if (list->s->table_cache_key.length == key_length && |
|
1655 |
!memcmp(list->s->table_cache_key.str, key, key_length)) |
|
1656 |
{
|
|
1657 |
if (unlock && thd->locked_tables) |
|
55
by brian
Update for using real bool types. |
1658 |
mysql_lock_remove(thd, thd->locked_tables, list, true); |
1
by brian
clean slate |
1659 |
|
1660 |
/* Remove table from open_tables list. */
|
|
1661 |
*prev= list->next; |
|
1662 |
/* Close table. */
|
|
1663 |
VOID(hash_delete(&open_cache,(uchar*) list)); // Close table |
|
1664 |
}
|
|
1665 |
else
|
|
1666 |
{
|
|
1667 |
/* Step to next entry in open_tables list. */
|
|
1668 |
prev= &list->next; |
|
1669 |
}
|
|
1670 |
}
|
|
1671 |
||
1672 |
// Notify any 'refresh' threads
|
|
1673 |
broadcast_refresh(); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1674 |
return; |
1
by brian
clean slate |
1675 |
}
|
1676 |
||
1677 |
||
1678 |
/**
|
|
1679 |
Auxiliary routine which closes and drops open table.
|
|
1680 |
||
1681 |
@param thd Thread handle
|
|
1682 |
@param table TABLE object for table to be dropped
|
|
1683 |
@param db_name Name of database for this table
|
|
1684 |
@param table_name Name of this table
|
|
1685 |
||
1686 |
@note This routine assumes that table to be closed is open only
|
|
1687 |
by calling thread so we needn't wait until other threads
|
|
1688 |
will close the table. Also unless called under implicit or
|
|
1689 |
explicit LOCK TABLES mode it assumes that table to be
|
|
1690 |
dropped is already unlocked. In the former case it will
|
|
1691 |
also remove lock on the table. But one should not rely on
|
|
1692 |
this behaviour as it may change in future.
|
|
1693 |
Currently, however, this function is never called for a
|
|
1694 |
table that was locked with LOCK TABLES.
|
|
1695 |
*/
|
|
1696 |
||
1697 |
void drop_open_table(THD *thd, TABLE *table, const char *db_name, |
|
1698 |
const char *table_name) |
|
1699 |
{
|
|
1700 |
if (table->s->tmp_table) |
|
1701 |
close_temporary_table(thd, table, 1, 1); |
|
1702 |
else
|
|
1703 |
{
|
|
1704 |
handlerton *table_type= table->s->db_type(); |
|
1705 |
VOID(pthread_mutex_lock(&LOCK_open)); |
|
1706 |
/*
|
|
1707 |
unlink_open_table() also tells threads waiting for refresh or close
|
|
1708 |
that something has happened.
|
|
1709 |
*/
|
|
55
by brian
Update for using real bool types. |
1710 |
unlink_open_table(thd, table, false); |
1
by brian
clean slate |
1711 |
quick_rm_table(table_type, db_name, table_name, 0); |
1712 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
1713 |
}
|
|
1714 |
}
|
|
1715 |
||
1716 |
||
1717 |
/*
|
|
1718 |
Wait for condition but allow the user to send a kill to mysqld
|
|
1719 |
||
1720 |
SYNOPSIS
|
|
1721 |
wait_for_condition()
|
|
1722 |
thd Thread handler
|
|
1723 |
mutex mutex that is currently hold that is associated with condition
|
|
1724 |
Will be unlocked on return
|
|
1725 |
cond Condition to wait for
|
|
1726 |
*/
|
|
1727 |
||
1728 |
void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond) |
|
1729 |
{
|
|
1730 |
/* Wait until the current table is up to date */
|
|
1731 |
const char *proc_info; |
|
1732 |
thd->mysys_var->current_mutex= mutex; |
|
1733 |
thd->mysys_var->current_cond= cond; |
|
1734 |
proc_info=thd->proc_info; |
|
1735 |
thd_proc_info(thd, "Waiting for table"); |
|
1736 |
if (!thd->killed) |
|
1737 |
(void) pthread_cond_wait(cond, mutex); |
|
1738 |
||
1739 |
/*
|
|
1740 |
We must unlock mutex first to avoid deadlock becasue conditions are
|
|
1741 |
sent to this thread by doing locks in the following order:
|
|
1742 |
lock(mysys_var->mutex)
|
|
1743 |
lock(mysys_var->current_mutex)
|
|
1744 |
||
1745 |
One by effect of this that one can only use wait_for_condition with
|
|
1746 |
condition variables that are guranteed to not disapper (freed) even if this
|
|
1747 |
mutex is unlocked
|
|
1748 |
*/
|
|
1749 |
||
1750 |
pthread_mutex_unlock(mutex); |
|
1751 |
pthread_mutex_lock(&thd->mysys_var->mutex); |
|
1752 |
thd->mysys_var->current_mutex= 0; |
|
1753 |
thd->mysys_var->current_cond= 0; |
|
1754 |
thd_proc_info(thd, proc_info); |
|
1755 |
pthread_mutex_unlock(&thd->mysys_var->mutex); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1756 |
return; |
1
by brian
clean slate |
1757 |
}
|
1758 |
||
1759 |
||
1760 |
/**
|
|
1761 |
Exclusively name-lock a table that is already write-locked by the
|
|
1762 |
current thread.
|
|
1763 |
||
1764 |
@param thd current thread context
|
|
1765 |
@param tables table list containing one table to open.
|
|
1766 |
||
55
by brian
Update for using real bool types. |
1767 |
@return false on success, true otherwise.
|
1
by brian
clean slate |
1768 |
*/
|
1769 |
||
1770 |
bool name_lock_locked_table(THD *thd, TABLE_LIST *tables) |
|
1771 |
{
|
|
1772 |
/* Under LOCK TABLES we must only accept write locked tables. */
|
|
1773 |
tables->table= find_locked_table(thd, tables->db, tables->table_name); |
|
1774 |
||
1775 |
if (!tables->table) |
|
1776 |
my_error(ER_TABLE_NOT_LOCKED, MYF(0), tables->alias); |
|
1777 |
else if (tables->table->reginfo.lock_type < TL_WRITE_LOW_PRIORITY) |
|
1778 |
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->alias); |
|
1779 |
else
|
|
1780 |
{
|
|
1781 |
/*
|
|
1782 |
Ensures that table is opened only by this thread and that no
|
|
1783 |
other statement will open this table.
|
|
1784 |
*/
|
|
1785 |
wait_while_table_is_used(thd, tables->table, HA_EXTRA_FORCE_REOPEN); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1786 |
return(false); |
1
by brian
clean slate |
1787 |
}
|
1788 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1789 |
return(true); |
1
by brian
clean slate |
1790 |
}
|
1791 |
||
1792 |
||
1793 |
/*
|
|
1794 |
Open table which is already name-locked by this thread.
|
|
1795 |
||
1796 |
SYNOPSIS
|
|
1797 |
reopen_name_locked_table()
|
|
1798 |
thd Thread handle
|
|
1799 |
table_list TABLE_LIST object for table to be open, TABLE_LIST::table
|
|
1800 |
member should point to TABLE object which was used for
|
|
1801 |
name-locking.
|
|
55
by brian
Update for using real bool types. |
1802 |
link_in true - if TABLE object for table to be opened should be
|
1
by brian
clean slate |
1803 |
linked into THD::open_tables list.
|
55
by brian
Update for using real bool types. |
1804 |
false - placeholder used for name-locking is already in
|
1
by brian
clean slate |
1805 |
this list so we only need to preserve TABLE::next
|
1806 |
pointer.
|
|
1807 |
||
1808 |
NOTE
|
|
1809 |
This function assumes that its caller already acquired LOCK_open mutex.
|
|
1810 |
||
1811 |
RETURN VALUE
|
|
55
by brian
Update for using real bool types. |
1812 |
false - Success
|
1813 |
true - Error
|
|
1
by brian
clean slate |
1814 |
*/
|
1815 |
||
1816 |
bool reopen_name_locked_table(THD* thd, TABLE_LIST* table_list, bool link_in) |
|
1817 |
{
|
|
1818 |
TABLE *table= table_list->table; |
|
1819 |
TABLE_SHARE *share; |
|
1820 |
char *table_name= table_list->table_name; |
|
1821 |
TABLE orig_table; |
|
1822 |
||
1823 |
safe_mutex_assert_owner(&LOCK_open); |
|
1824 |
||
1825 |
if (thd->killed || !table) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1826 |
return(true); |
1
by brian
clean slate |
1827 |
|
1828 |
orig_table= *table; |
|
1829 |
||
1830 |
if (open_unireg_entry(thd, table, table_list, table_name, |
|
1831 |
table->s->table_cache_key.str, |
|
1832 |
table->s->table_cache_key.length, thd->mem_root, 0)) |
|
1833 |
{
|
|
1834 |
intern_close_table(table); |
|
1835 |
/*
|
|
1836 |
If there was an error during opening of table (for example if it
|
|
1837 |
does not exist) '*table' object can be wiped out. To be able
|
|
1838 |
properly release name-lock in this case we should restore this
|
|
1839 |
object to its original state.
|
|
1840 |
*/
|
|
1841 |
*table= orig_table; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1842 |
return(true); |
1
by brian
clean slate |
1843 |
}
|
1844 |
||
1845 |
share= table->s; |
|
1846 |
/*
|
|
1847 |
We want to prevent other connections from opening this table until end
|
|
1848 |
of statement as it is likely that modifications of table's metadata are
|
|
1849 |
not yet finished (for example CREATE TRIGGER have to change .TRG file,
|
|
1850 |
or we might want to drop table if CREATE TABLE ... SELECT fails).
|
|
1851 |
This also allows us to assume that no other connection will sneak in
|
|
1852 |
before we will get table-level lock on this table.
|
|
1853 |
*/
|
|
1854 |
share->version=0; |
|
1855 |
table->in_use = thd; |
|
1856 |
||
1857 |
if (link_in) |
|
1858 |
{
|
|
1859 |
table->next= thd->open_tables; |
|
1860 |
thd->open_tables= table; |
|
1861 |
}
|
|
1862 |
else
|
|
1863 |
{
|
|
1864 |
/*
|
|
1865 |
TABLE object should be already in THD::open_tables list so we just
|
|
1866 |
need to set TABLE::next correctly.
|
|
1867 |
*/
|
|
1868 |
table->next= orig_table.next; |
|
1869 |
}
|
|
1870 |
||
1871 |
table->tablenr=thd->current_tablenr++; |
|
1872 |
table->used_fields=0; |
|
1873 |
table->const_table=0; |
|
274
by Brian Aker
my_bool conversion in Table |
1874 |
table->null_row= false; |
1875 |
table->maybe_null= false; |
|
1876 |
table->force_index= false; |
|
1
by brian
clean slate |
1877 |
table->status=STATUS_NO_RECORD; |
274
by Brian Aker
my_bool conversion in Table |
1878 |
return false; |
1
by brian
clean slate |
1879 |
}
|
1880 |
||
1881 |
||
1882 |
/**
|
|
1883 |
Create and insert into table cache placeholder for table
|
|
1884 |
which will prevent its opening (or creation) (a.k.a lock
|
|
1885 |
table name).
|
|
1886 |
||
1887 |
@param thd Thread context
|
|
1888 |
@param key Table cache key for name to be locked
|
|
1889 |
@param key_length Table cache key length
|
|
1890 |
||
1891 |
@return Pointer to TABLE object used for name locking or 0 in
|
|
1892 |
case of failure.
|
|
1893 |
*/
|
|
1894 |
||
1895 |
TABLE *table_cache_insert_placeholder(THD *thd, const char *key, |
|
1896 |
uint key_length) |
|
1897 |
{
|
|
1898 |
TABLE *table; |
|
1899 |
TABLE_SHARE *share; |
|
1900 |
char *key_buff; |
|
1901 |
||
1902 |
safe_mutex_assert_owner(&LOCK_open); |
|
1903 |
||
1904 |
/*
|
|
1905 |
Create a table entry with the right key and with an old refresh version
|
|
1906 |
Note that we must use my_multi_malloc() here as this is freed by the
|
|
1907 |
table cache
|
|
1908 |
*/
|
|
1909 |
if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), |
|
1910 |
&table, sizeof(*table), |
|
1911 |
&share, sizeof(*share), |
|
1912 |
&key_buff, key_length, |
|
1913 |
NULL)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1914 |
return(NULL); |
1
by brian
clean slate |
1915 |
|
1916 |
table->s= share; |
|
1917 |
share->set_table_cache_key(key_buff, key, key_length); |
|
1918 |
share->tmp_table= INTERNAL_TMP_TABLE; // for intern_close_table |
|
1919 |
table->in_use= thd; |
|
1920 |
table->locked_by_name=1; |
|
1921 |
||
1922 |
if (my_hash_insert(&open_cache, (uchar*)table)) |
|
1923 |
{
|
|
1924 |
my_free((uchar*) table, MYF(0)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1925 |
return(NULL); |
1
by brian
clean slate |
1926 |
}
|
1927 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1928 |
return(table); |
1
by brian
clean slate |
1929 |
}
|
1930 |
||
1931 |
||
1932 |
/**
|
|
1933 |
Obtain an exclusive name lock on the table if it is not cached
|
|
1934 |
in the table cache.
|
|
1935 |
||
1936 |
@param thd Thread context
|
|
1937 |
@param db Name of database
|
|
1938 |
@param table_name Name of table
|
|
1939 |
@param[out] table Out parameter which is either:
|
|
1940 |
- set to NULL if table cache contains record for
|
|
1941 |
the table or
|
|
1942 |
- set to point to the TABLE instance used for
|
|
1943 |
name-locking.
|
|
1944 |
||
1945 |
@note This function takes into account all records for table in table
|
|
1946 |
cache, even placeholders used for name-locking. This means that
|
|
1947 |
'table' parameter can be set to NULL for some situations when
|
|
1948 |
table does not really exist.
|
|
1949 |
||
55
by brian
Update for using real bool types. |
1950 |
@retval true Error occured (OOM)
|
1951 |
@retval false Success. 'table' parameter set according to above rules.
|
|
1
by brian
clean slate |
1952 |
*/
|
1953 |
||
1954 |
bool lock_table_name_if_not_cached(THD *thd, const char *db, |
|
1955 |
const char *table_name, TABLE **table) |
|
1956 |
{
|
|
1957 |
char key[MAX_DBKEY_LENGTH]; |
|
1958 |
uint key_length; |
|
1959 |
||
266.1.21
by Monty Taylor
Removed references to strmov and strnmov |
1960 |
key_length= (uint)(stpcpy(stpcpy(key, db) + 1, table_name) - key) + 1; |
1
by brian
clean slate |
1961 |
VOID(pthread_mutex_lock(&LOCK_open)); |
1962 |
||
1963 |
if (hash_search(&open_cache, (uchar *)key, key_length)) |
|
1964 |
{
|
|
1965 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
1966 |
*table= 0; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1967 |
return(false); |
1
by brian
clean slate |
1968 |
}
|
1969 |
if (!(*table= table_cache_insert_placeholder(thd, key, key_length))) |
|
1970 |
{
|
|
1971 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1972 |
return(true); |
1
by brian
clean slate |
1973 |
}
|
1974 |
(*table)->open_placeholder= 1; |
|
1975 |
(*table)->next= thd->open_tables; |
|
1976 |
thd->open_tables= *table; |
|
1977 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
1978 |
return(false); |
1
by brian
clean slate |
1979 |
}
|
1980 |
||
1981 |
||
1982 |
/**
|
|
1983 |
Check that table exists in table definition cache, on disk
|
|
1984 |
or in some storage engine.
|
|
1985 |
||
1986 |
@param thd Thread context
|
|
1987 |
@param table Table list element
|
|
55
by brian
Update for using real bool types. |
1988 |
@param[out] exists Out parameter which is set to true if table
|
1989 |
exists and to false otherwise.
|
|
1
by brian
clean slate |
1990 |
|
1991 |
@note This function assumes that caller owns LOCK_open mutex.
|
|
1992 |
It also assumes that the fact that there are no name-locks
|
|
1993 |
on the table was checked beforehand.
|
|
1994 |
||
1995 |
@note If there is no .FRM file for the table but it exists in one
|
|
1996 |
of engines (e.g. it was created on another node of NDB cluster)
|
|
1997 |
this function will fetch and create proper .FRM file for it.
|
|
1998 |
||
55
by brian
Update for using real bool types. |
1999 |
@retval true Some error occured
|
2000 |
@retval false No error. 'exists' out parameter set accordingly.
|
|
1
by brian
clean slate |
2001 |
*/
|
2002 |
||
2003 |
bool check_if_table_exists(THD *thd, TABLE_LIST *table, bool *exists) |
|
2004 |
{
|
|
2005 |
char path[FN_REFLEN]; |
|
2006 |
int rc; |
|
2007 |
||
2008 |
safe_mutex_assert_owner(&LOCK_open); |
|
2009 |
||
55
by brian
Update for using real bool types. |
2010 |
*exists= true; |
1
by brian
clean slate |
2011 |
|
2012 |
if (get_cached_table_share(table->db, table->table_name)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2013 |
return(false); |
1
by brian
clean slate |
2014 |
|
2015 |
build_table_filename(path, sizeof(path) - 1, table->db, table->table_name, |
|
2016 |
reg_ext, 0); |
|
2017 |
||
2018 |
if (!access(path, F_OK)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2019 |
return(false); |
1
by brian
clean slate |
2020 |
|
2021 |
/* .FRM file doesn't exist. Check if some engine can provide it. */
|
|
2022 |
||
2023 |
rc= ha_create_table_from_engine(thd, table->db, table->table_name); |
|
2024 |
||
2025 |
if (rc < 0) |
|
2026 |
{
|
|
2027 |
/* Table does not exists in engines as well. */
|
|
55
by brian
Update for using real bool types. |
2028 |
*exists= false; |
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2029 |
return(false); |
1
by brian
clean slate |
2030 |
}
|
2031 |
else if (!rc) |
|
2032 |
{
|
|
2033 |
/* Table exists in some engine and .FRM for it was created. */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2034 |
return(false); |
1
by brian
clean slate |
2035 |
}
|
2036 |
else /* (rc > 0) */ |
|
2037 |
{
|
|
2038 |
my_printf_error(ER_UNKNOWN_ERROR, "Failed to open '%-.64s', error while " |
|
2039 |
"unpacking from engine", MYF(0), table->table_name); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2040 |
return(true); |
1
by brian
clean slate |
2041 |
}
|
2042 |
}
|
|
2043 |
||
2044 |
||
2045 |
/*
|
|
2046 |
Open a table.
|
|
2047 |
||
2048 |
SYNOPSIS
|
|
2049 |
open_table()
|
|
2050 |
thd Thread context.
|
|
2051 |
table_list Open first table in list.
|
|
2052 |
refresh INOUT Pointer to memory that will be set to 1 if
|
|
2053 |
we need to close all tables and reopen them.
|
|
2054 |
If this is a NULL pointer, then the table is not
|
|
2055 |
put in the thread-open-list.
|
|
2056 |
flags Bitmap of flags to modify how open works:
|
|
2057 |
MYSQL_LOCK_IGNORE_FLUSH - Open table even if
|
|
2058 |
someone has done a flush or namelock on it.
|
|
2059 |
No version number checking is done.
|
|
2060 |
MYSQL_OPEN_TEMPORARY_ONLY - Open only temporary
|
|
2061 |
table not the base table or view.
|
|
2062 |
||
2063 |
IMPLEMENTATION
|
|
2064 |
Uses a cache of open tables to find a table not in use.
|
|
2065 |
||
2066 |
If table list element for the table to be opened has "create" flag
|
|
2067 |
set and table does not exist, this function will automatically insert
|
|
2068 |
a placeholder for exclusive name lock into the open tables cache and
|
|
2069 |
will return the TABLE instance that corresponds to this placeholder.
|
|
2070 |
||
2071 |
RETURN
|
|
2072 |
NULL Open failed. If refresh is set then one should close
|
|
2073 |
all other tables and retry the open.
|
|
2074 |
# Success. Pointer to TABLE object for open table.
|
|
2075 |
*/
|
|
2076 |
||
2077 |
||
2078 |
TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, |
|
2079 |
bool *refresh, uint flags) |
|
2080 |
{
|
|
2081 |
register TABLE *table; |
|
2082 |
char key[MAX_DBKEY_LENGTH]; |
|
2083 |
unsigned int key_length; |
|
2084 |
char *alias= table_list->alias; |
|
2085 |
HASH_SEARCH_STATE state; |
|
2086 |
||
2087 |
/* Parsing of partitioning information from .frm needs thd->lex set up. */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2088 |
assert(thd->lex->is_lex_started); |
1
by brian
clean slate |
2089 |
|
2090 |
/* find a unused table in the open table cache */
|
|
2091 |
if (refresh) |
|
2092 |
*refresh=0; |
|
2093 |
||
2094 |
/* an open table operation needs a lot of the stack space */
|
|
2095 |
if (check_stack_overrun(thd, STACK_MIN_SIZE_FOR_OPEN, (uchar *)&alias)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2096 |
return(0); |
1
by brian
clean slate |
2097 |
|
2098 |
if (thd->killed) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2099 |
return(0); |
1
by brian
clean slate |
2100 |
|
2101 |
key_length= (create_table_def_key(thd, key, table_list, 1) - |
|
2102 |
TMP_TABLE_KEY_EXTRA); |
|
2103 |
||
2104 |
/*
|
|
2105 |
Unless requested otherwise, try to resolve this table in the list
|
|
2106 |
of temporary tables of this thread. In MySQL temporary tables
|
|
2107 |
are always thread-local and "shadow" possible base tables with the
|
|
2108 |
same name. This block implements the behaviour.
|
|
2109 |
TODO: move this block into a separate function.
|
|
2110 |
*/
|
|
2111 |
{
|
|
2112 |
for (table= thd->temporary_tables; table ; table=table->next) |
|
2113 |
{
|
|
2114 |
if (table->s->table_cache_key.length == key_length + |
|
2115 |
TMP_TABLE_KEY_EXTRA && |
|
2116 |
!memcmp(table->s->table_cache_key.str, key, |
|
2117 |
key_length + TMP_TABLE_KEY_EXTRA)) |
|
2118 |
{
|
|
2119 |
/*
|
|
2120 |
We're trying to use the same temporary table twice in a query.
|
|
2121 |
Right now we don't support this because a temporary table
|
|
2122 |
is always represented by only one TABLE object in THD, and
|
|
2123 |
it can not be cloned. Emit an error for an unsupported behaviour.
|
|
2124 |
*/
|
|
2125 |
if (table->query_id) |
|
2126 |
{
|
|
2127 |
my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2128 |
return(0); |
1
by brian
clean slate |
2129 |
}
|
2130 |
table->query_id= thd->query_id; |
|
55
by brian
Update for using real bool types. |
2131 |
thd->thread_specific_used= true; |
1
by brian
clean slate |
2132 |
goto reset; |
2133 |
}
|
|
2134 |
}
|
|
2135 |
}
|
|
2136 |
||
2137 |
if (flags & MYSQL_OPEN_TEMPORARY_ONLY) |
|
2138 |
{
|
|
2139 |
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->table_name); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2140 |
return(0); |
1
by brian
clean slate |
2141 |
}
|
2142 |
||
2143 |
/*
|
|
2144 |
The table is not temporary - if we're in pre-locked or LOCK TABLES
|
|
2145 |
mode, let's try to find the requested table in the list of pre-opened
|
|
2146 |
and locked tables. If the table is not there, return an error - we can't
|
|
2147 |
open not pre-opened tables in pre-locked/LOCK TABLES mode.
|
|
2148 |
TODO: move this block into a separate function.
|
|
2149 |
*/
|
|
2150 |
if (thd->locked_tables) |
|
2151 |
{ // Using table locks |
|
2152 |
TABLE *best_table= 0; |
|
2153 |
int best_distance= INT_MIN; |
|
2154 |
bool check_if_used= false; |
|
2155 |
for (table=thd->open_tables; table ; table=table->next) |
|
2156 |
{
|
|
2157 |
if (table->s->table_cache_key.length == key_length && |
|
2158 |
!memcmp(table->s->table_cache_key.str, key, key_length)) |
|
2159 |
{
|
|
2160 |
if (check_if_used && table->query_id && |
|
2161 |
table->query_id != thd->query_id) |
|
2162 |
{
|
|
2163 |
/*
|
|
2164 |
If we are in stored function or trigger we should ensure that
|
|
2165 |
we won't change table that is already used by calling statement.
|
|
2166 |
So if we are opening table for writing, we should check that it
|
|
2167 |
is not already open by some calling stamement.
|
|
2168 |
*/
|
|
2169 |
my_error(ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG, MYF(0), |
|
2170 |
table->s->table_name.str); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2171 |
return(0); |
1
by brian
clean slate |
2172 |
}
|
2173 |
/*
|
|
2174 |
When looking for a usable TABLE, ignore MERGE children, as they
|
|
2175 |
belong to their parent and cannot be used explicitly.
|
|
2176 |
*/
|
|
2177 |
if (!my_strcasecmp(system_charset_info, table->alias, alias) && |
|
2178 |
table->query_id != thd->query_id) /* skip tables already used */ |
|
2179 |
{
|
|
2180 |
int distance= ((int) table->reginfo.lock_type - |
|
2181 |
(int) table_list->lock_type); |
|
2182 |
/*
|
|
2183 |
Find a table that either has the exact lock type requested,
|
|
2184 |
or has the best suitable lock. In case there is no locked
|
|
2185 |
table that has an equal or higher lock than requested,
|
|
2186 |
we us the closest matching lock to be able to produce an error
|
|
2187 |
message about wrong lock mode on the table. The best_table
|
|
2188 |
is changed if bd < 0 <= d or bd < d < 0 or 0 <= d < bd.
|
|
2189 |
||
2190 |
distance < 0 - No suitable lock found
|
|
2191 |
distance > 0 - we have lock mode higher then we require
|
|
2192 |
distance == 0 - we have lock mode exactly which we need
|
|
2193 |
*/
|
|
2194 |
if ((best_distance < 0 && distance > best_distance) || (distance >= 0 && distance < best_distance)) |
|
2195 |
{
|
|
2196 |
best_distance= distance; |
|
2197 |
best_table= table; |
|
2198 |
if (best_distance == 0 && !check_if_used) |
|
2199 |
{
|
|
2200 |
/*
|
|
2201 |
If we have found perfect match and we don't need to check that
|
|
2202 |
table is not used by one of calling statements (assuming that
|
|
2203 |
we are inside of function or trigger) we can finish iterating
|
|
2204 |
through open tables list.
|
|
2205 |
*/
|
|
2206 |
break; |
|
2207 |
}
|
|
2208 |
}
|
|
2209 |
}
|
|
2210 |
}
|
|
2211 |
}
|
|
2212 |
if (best_table) |
|
2213 |
{
|
|
2214 |
table= best_table; |
|
2215 |
table->query_id= thd->query_id; |
|
2216 |
goto reset; |
|
2217 |
}
|
|
2218 |
/*
|
|
2219 |
No table in the locked tables list. In case of explicit LOCK TABLES
|
|
2220 |
this can happen if a user did not include the able into the list.
|
|
2221 |
In case of pre-locked mode locked tables list is generated automatically,
|
|
2222 |
so we may only end up here if the table did not exist when
|
|
2223 |
locked tables list was created.
|
|
2224 |
*/
|
|
2225 |
my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2226 |
return(0); |
1
by brian
clean slate |
2227 |
}
|
2228 |
||
2229 |
/*
|
|
2230 |
Non pre-locked/LOCK TABLES mode, and the table is not temporary:
|
|
2231 |
this is the normal use case.
|
|
2232 |
Now we should:
|
|
2233 |
- try to find the table in the table cache.
|
|
2234 |
- if one of the discovered TABLE instances is name-locked
|
|
2235 |
(table->s->version == 0) or some thread has started FLUSH TABLES
|
|
2236 |
(refresh_version > table->s->version), back off -- we have to wait
|
|
2237 |
until no one holds a name lock on the table.
|
|
2238 |
- if there is no such TABLE in the name cache, read the table definition
|
|
2239 |
and insert it into the cache.
|
|
2240 |
We perform all of the above under LOCK_open which currently protects
|
|
2241 |
the open cache (also known as table cache) and table definitions stored
|
|
2242 |
on disk.
|
|
2243 |
*/
|
|
2244 |
||
2245 |
VOID(pthread_mutex_lock(&LOCK_open)); |
|
2246 |
||
2247 |
/*
|
|
2248 |
If it's the first table from a list of tables used in a query,
|
|
2249 |
remember refresh_version (the version of open_cache state).
|
|
2250 |
If the version changes while we're opening the remaining tables,
|
|
2251 |
we will have to back off, close all the tables opened-so-far,
|
|
2252 |
and try to reopen them.
|
|
2253 |
Note: refresh_version is currently changed only during FLUSH TABLES.
|
|
2254 |
*/
|
|
2255 |
if (!thd->open_tables) |
|
2256 |
thd->version=refresh_version; |
|
2257 |
else if ((thd->version != refresh_version) && |
|
2258 |
! (flags & MYSQL_LOCK_IGNORE_FLUSH)) |
|
2259 |
{
|
|
2260 |
/* Someone did a refresh while thread was opening tables */
|
|
2261 |
if (refresh) |
|
2262 |
*refresh=1; |
|
2263 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2264 |
return(0); |
1
by brian
clean slate |
2265 |
}
|
2266 |
||
2267 |
/*
|
|
2268 |
In order for the back off and re-start process to work properly,
|
|
2269 |
handler tables having old versions (due to FLUSH TABLES or pending
|
|
2270 |
name-lock) MUST be closed. This is specially important if a name-lock
|
|
2271 |
is pending for any table of the handler_tables list, otherwise a
|
|
2272 |
deadlock may occur.
|
|
2273 |
*/
|
|
2274 |
if (thd->handler_tables) |
|
2275 |
mysql_ha_flush(thd); |
|
2276 |
||
2277 |
/*
|
|
2278 |
Actually try to find the table in the open_cache.
|
|
2279 |
The cache may contain several "TABLE" instances for the same
|
|
2280 |
physical table. The instances that are currently "in use" by
|
|
2281 |
some thread have their "in_use" member != NULL.
|
|
2282 |
There is no good reason for having more than one entry in the
|
|
2283 |
hash for the same physical table, except that we use this as
|
|
2284 |
an implicit "pending locks queue" - see
|
|
2285 |
wait_for_locked_table_names for details.
|
|
2286 |
*/
|
|
2287 |
for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length, |
|
2288 |
&state); |
|
2289 |
table && table->in_use ; |
|
2290 |
table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, |
|
2291 |
&state)) |
|
2292 |
{
|
|
2293 |
/*
|
|
2294 |
Here we flush tables marked for flush.
|
|
2295 |
Normally, table->s->version contains the value of
|
|
2296 |
refresh_version from the moment when this table was
|
|
2297 |
(re-)opened and added to the cache.
|
|
2298 |
If since then we did (or just started) FLUSH TABLES
|
|
2299 |
statement, refresh_version has been increased.
|
|
2300 |
For "name-locked" TABLE instances, table->s->version is set
|
|
2301 |
to 0 (see lock_table_name for details).
|
|
2302 |
In case there is a pending FLUSH TABLES or a name lock, we
|
|
2303 |
need to back off and re-start opening tables.
|
|
2304 |
If we do not back off now, we may dead lock in case of lock
|
|
2305 |
order mismatch with some other thread:
|
|
2306 |
c1: name lock t1; -- sort of exclusive lock
|
|
2307 |
c2: open t2; -- sort of shared lock
|
|
2308 |
c1: name lock t2; -- blocks
|
|
2309 |
c2: open t1; -- blocks
|
|
2310 |
*/
|
|
2311 |
if (table->needs_reopen_or_name_lock()) |
|
2312 |
{
|
|
2313 |
if (flags & MYSQL_LOCK_IGNORE_FLUSH) |
|
2314 |
{
|
|
2315 |
/* Force close at once after usage */
|
|
2316 |
thd->version= table->s->version; |
|
2317 |
continue; |
|
2318 |
}
|
|
2319 |
||
2320 |
/* Avoid self-deadlocks by detecting self-dependencies. */
|
|
2321 |
if (table->open_placeholder && table->in_use == thd) |
|
2322 |
{
|
|
2323 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
2324 |
my_error(ER_UPDATE_TABLE_USED, MYF(0), table->s->table_name.str); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2325 |
return(0); |
1
by brian
clean slate |
2326 |
}
|
2327 |
||
2328 |
/*
|
|
2329 |
Back off, part 1: mark the table as "unused" for the
|
|
2330 |
purpose of name-locking by setting table->db_stat to 0. Do
|
|
2331 |
that only for the tables in this thread that have an old
|
|
2332 |
table->s->version (this is an optimization (?)).
|
|
2333 |
table->db_stat == 0 signals wait_for_locked_table_names
|
|
2334 |
that the tables in question are not used any more. See
|
|
2335 |
table_is_used call for details.
|
|
2336 |
||
2337 |
Notice that HANDLER tables were already taken care of by
|
|
2338 |
the earlier call to mysql_ha_flush() in this same critical
|
|
2339 |
section.
|
|
2340 |
*/
|
|
2341 |
close_old_data_files(thd,thd->open_tables,0,0); |
|
2342 |
/*
|
|
2343 |
Back-off part 2: try to avoid "busy waiting" on the table:
|
|
2344 |
if the table is in use by some other thread, we suspend
|
|
2345 |
and wait till the operation is complete: when any
|
|
2346 |
operation that juggles with table->s->version completes,
|
|
2347 |
it broadcasts COND_refresh condition variable.
|
|
2348 |
If 'old' table we met is in use by current thread we return
|
|
2349 |
without waiting since in this situation it's this thread
|
|
2350 |
which is responsible for broadcasting on COND_refresh
|
|
2351 |
(and this was done already in close_old_data_files()).
|
|
2352 |
Good example of such situation is when we have statement
|
|
2353 |
that needs two instances of table and FLUSH TABLES comes
|
|
2354 |
after we open first instance but before we open second
|
|
2355 |
instance.
|
|
2356 |
*/
|
|
2357 |
if (table->in_use != thd) |
|
2358 |
{
|
|
2359 |
/* wait_for_conditionwill unlock LOCK_open for us */
|
|
2360 |
wait_for_condition(thd, &LOCK_open, &COND_refresh); |
|
2361 |
}
|
|
2362 |
else
|
|
2363 |
{
|
|
2364 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
2365 |
}
|
|
2366 |
/*
|
|
2367 |
There is a refresh in progress for this table.
|
|
2368 |
Signal the caller that it has to try again.
|
|
2369 |
*/
|
|
2370 |
if (refresh) |
|
2371 |
*refresh=1; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2372 |
return(0); |
1
by brian
clean slate |
2373 |
}
|
2374 |
}
|
|
2375 |
if (table) |
|
2376 |
{
|
|
2377 |
/* Unlink the table from "unused_tables" list. */
|
|
2378 |
if (table == unused_tables) |
|
2379 |
{ // First unused |
|
2380 |
unused_tables=unused_tables->next; // Remove from link |
|
2381 |
if (table == unused_tables) |
|
2382 |
unused_tables=0; |
|
2383 |
}
|
|
2384 |
table->prev->next=table->next; /* Remove from unused list */ |
|
2385 |
table->next->prev=table->prev; |
|
2386 |
table->in_use= thd; |
|
2387 |
}
|
|
2388 |
else
|
|
2389 |
{
|
|
2390 |
/* Insert a new TABLE instance into the open cache */
|
|
2391 |
int error; |
|
2392 |
/* Free cache if too big */
|
|
2393 |
while (open_cache.records > table_cache_size && unused_tables) |
|
2394 |
VOID(hash_delete(&open_cache,(uchar*) unused_tables)); /* purecov: tested */ |
|
2395 |
||
2396 |
if (table_list->create) |
|
2397 |
{
|
|
2398 |
bool exists; |
|
2399 |
||
2400 |
if (check_if_table_exists(thd, table_list, &exists)) |
|
2401 |
{
|
|
2402 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2403 |
return(NULL); |
1
by brian
clean slate |
2404 |
}
|
2405 |
||
2406 |
if (!exists) |
|
2407 |
{
|
|
2408 |
/*
|
|
2409 |
Table to be created, so we need to create placeholder in table-cache.
|
|
2410 |
*/
|
|
2411 |
if (!(table= table_cache_insert_placeholder(thd, key, key_length))) |
|
2412 |
{
|
|
2413 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2414 |
return(NULL); |
1
by brian
clean slate |
2415 |
}
|
2416 |
/*
|
|
2417 |
Link placeholder to the open tables list so it will be automatically
|
|
2418 |
removed once tables are closed. Also mark it so it won't be ignored
|
|
2419 |
by other trying to take name-lock.
|
|
2420 |
*/
|
|
2421 |
table->open_placeholder= 1; |
|
2422 |
table->next= thd->open_tables; |
|
2423 |
thd->open_tables= table; |
|
2424 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2425 |
return(table); |
1
by brian
clean slate |
2426 |
}
|
2427 |
/* Table exists. Let us try to open it. */
|
|
2428 |
}
|
|
2429 |
||
2430 |
/* make a new table */
|
|
2431 |
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME)))) |
|
2432 |
{
|
|
2433 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2434 |
return(NULL); |
1
by brian
clean slate |
2435 |
}
|
2436 |
||
2437 |
error= open_unireg_entry(thd, table, table_list, alias, key, key_length, |
|
2438 |
mem_root, (flags & OPEN_VIEW_NO_PARSE)); |
|
2439 |
/* Combine the follow two */
|
|
2440 |
if (error > 0) |
|
2441 |
{
|
|
2442 |
my_free((uchar*)table, MYF(0)); |
|
2443 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2444 |
return(NULL); |
1
by brian
clean slate |
2445 |
}
|
2446 |
if (error < 0) |
|
2447 |
{
|
|
2448 |
my_free((uchar*)table, MYF(0)); |
|
2449 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2450 |
return(0); // VIEW |
1
by brian
clean slate |
2451 |
}
|
2452 |
VOID(my_hash_insert(&open_cache,(uchar*) table)); |
|
2453 |
}
|
|
2454 |
||
2455 |
VOID(pthread_mutex_unlock(&LOCK_open)); |
|
2456 |
if (refresh) |
|
2457 |
{
|
|
2458 |
table->next=thd->open_tables; /* Link into simple list */ |
|
2459 |
thd->open_tables=table; |
|
2460 |
}
|
|
2461 |
table->reginfo.lock_type=TL_READ; /* Assume read */ |
|
2462 |
||
2463 |
reset: |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2464 |
assert(table->s->ref_count > 0 || table->s->tmp_table != NO_TMP_TABLE); |
1
by brian
clean slate |
2465 |
|
2466 |
if (thd->lex->need_correct_ident()) |
|
2467 |
table->alias_name_used= my_strcasecmp(table_alias_charset, |
|
2468 |
table->s->table_name.str, alias); |
|
2469 |
/* Fix alias if table name changes */
|
|
2470 |
if (strcmp(table->alias, alias)) |
|
2471 |
{
|
|
2472 |
uint length=(uint) strlen(alias)+1; |
|
2473 |
table->alias= (char*) my_realloc((char*) table->alias, length, |
|
2474 |
MYF(MY_WME)); |
|
212.6.7
by Mats Kindahl
Minor compile issue fixed. |
2475 |
memcpy((void*) table->alias, alias, length); |
1
by brian
clean slate |
2476 |
}
|
2477 |
/* These variables are also set in reopen_table() */
|
|
2478 |
table->tablenr=thd->current_tablenr++; |
|
2479 |
table->used_fields=0; |
|
2480 |
table->const_table=0; |
|
274
by Brian Aker
my_bool conversion in Table |
2481 |
table->null_row= false; |
2482 |
table->maybe_null= false; |
|
2483 |
table->force_index= false; |
|
1
by brian
clean slate |
2484 |
table->status=STATUS_NO_RECORD; |
2485 |
table->insert_values= 0; |
|
2486 |
/* Catch wrong handling of the auto_increment_field_not_null. */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2487 |
assert(!table->auto_increment_field_not_null); |
55
by brian
Update for using real bool types. |
2488 |
table->auto_increment_field_not_null= false; |
1
by brian
clean slate |
2489 |
if (table->timestamp_field) |
2490 |
table->timestamp_field_type= table->timestamp_field->get_auto_set_type(); |
|
2491 |
table->pos_in_table_list= table_list; |
|
2492 |
table->clear_column_bitmaps(); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2493 |
assert(table->key_read == 0); |
2494 |
return(table); |
|
1
by brian
clean slate |
2495 |
}
|
2496 |
||
2497 |
||
2498 |
TABLE *find_locked_table(THD *thd, const char *db,const char *table_name) |
|
2499 |
{
|
|
2500 |
char key[MAX_DBKEY_LENGTH]; |
|
266.1.21
by Monty Taylor
Removed references to strmov and strnmov |
2501 |
uint key_length=(uint) (stpcpy(stpcpy(key,db)+1,table_name)-key)+1; |
1
by brian
clean slate |
2502 |
|
2503 |
for (TABLE *table=thd->open_tables; table ; table=table->next) |
|
2504 |
{
|
|
2505 |
if (table->s->table_cache_key.length == key_length && |
|
2506 |
!memcmp(table->s->table_cache_key.str, key, key_length)) |
|
2507 |
return table; |
|
2508 |
}
|
|
2509 |
return(0); |
|
2510 |
}
|
|
2511 |
||
2512 |
||
2513 |
/*
|
|
2514 |
Reopen an table because the definition has changed.
|
|
2515 |
||
2516 |
SYNOPSIS
|
|
2517 |
reopen_table()
|
|
2518 |
table Table object
|
|
2519 |
||
2520 |
NOTES
|
|
2521 |
The data file for the table is already closed and the share is released
|
|
2522 |
The table has a 'dummy' share that mainly contains database and table name.
|
|
2523 |
||
2524 |
RETURN
|
|
2525 |
0 ok
|
|
2526 |
1 error. The old table object is not changed.
|
|
2527 |
*/
|
|
2528 |
||
2529 |
bool reopen_table(TABLE *table) |
|
2530 |
{
|
|
2531 |
TABLE tmp; |
|
2532 |
bool error= 1; |
|
2533 |
Field **field; |
|
2534 |
uint key,part; |
|
2535 |
TABLE_LIST table_list; |
|
2536 |
THD *thd= table->in_use; |
|
2537 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2538 |
assert(table->s->ref_count == 0); |
2539 |
assert(!table->sort.io_cache); |
|
1
by brian
clean slate |
2540 |
|
2541 |
#ifdef EXTRA_DEBUG
|
|
2542 |
if (table->db_stat) |
|
2543 |
sql_print_error("Table %s had a open data handler in reopen_table", |
|
2544 |
table->alias); |
|
2545 |
#endif
|
|
212.6.1
by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file. |
2546 |
memset(&table_list, 0, sizeof(TABLE_LIST)); |
1
by brian
clean slate |
2547 |
table_list.db= table->s->db.str; |
2548 |
table_list.table_name= table->s->table_name.str; |
|
2549 |
table_list.table= table; |
|
2550 |
||
2551 |
if (wait_for_locked_table_names(thd, &table_list)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2552 |
return(1); // Thread was killed |
1
by brian
clean slate |
2553 |
|
2554 |
if (open_unireg_entry(thd, &tmp, &table_list, |
|
2555 |
table->alias, |
|
2556 |
table->s->table_cache_key.str, |
|
2557 |
table->s->table_cache_key.length, |
|
2558 |
thd->mem_root, 0)) |
|
2559 |
goto end; |
|
2560 |
||
2561 |
/* This list copies variables set by open_table */
|
|
2562 |
tmp.tablenr= table->tablenr; |
|
2563 |
tmp.used_fields= table->used_fields; |
|
2564 |
tmp.const_table= table->const_table; |
|
2565 |
tmp.null_row= table->null_row; |
|
2566 |
tmp.maybe_null= table->maybe_null; |
|
2567 |
tmp.status= table->status; |
|
2568 |
||
2569 |
tmp.s->table_map_id= table->s->table_map_id; |
|
2570 |
||
2571 |
/* Get state */
|
|
2572 |
tmp.in_use= thd; |
|
2573 |
tmp.reginfo.lock_type=table->reginfo.lock_type; |
|
2574 |
||
2575 |
/* Replace table in open list */
|
|
2576 |
tmp.next= table->next; |
|
2577 |
tmp.prev= table->prev; |
|
2578 |
||
2579 |
if (table->file) |
|
2580 |
VOID(closefrm(table, 1)); // close file, free everything |
|
2581 |
||
2582 |
*table= tmp; |
|
2583 |
table->default_column_bitmaps(); |
|
2584 |
table->file->change_table_ptr(table, table->s); |
|
2585 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2586 |
assert(table->alias != 0); |
1
by brian
clean slate |
2587 |
for (field=table->field ; *field ; field++) |
2588 |
{
|
|
2589 |
(*field)->table= (*field)->orig_table= table; |
|
2590 |
(*field)->table_name= &table->alias; |
|
2591 |
}
|
|
2592 |
for (key=0 ; key < table->s->keys ; key++) |
|
2593 |
{
|
|
2594 |
for (part=0 ; part < table->key_info[key].usable_key_parts ; part++) |
|
2595 |
table->key_info[key].key_part[part].field->table= table; |
|
2596 |
}
|
|
2597 |
/*
|
|
2598 |
Do not attach MERGE children here. The children might be reopened
|
|
2599 |
after the parent. Attach children after reopening all tables that
|
|
2600 |
require reopen. See for example reopen_tables().
|
|
2601 |
*/
|
|
2602 |
||
2603 |
broadcast_refresh(); |
|
2604 |
error=0; |
|
2605 |
||
2606 |
end: |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2607 |
return(error); |
1
by brian
clean slate |
2608 |
}
|
2609 |
||
2610 |
||
2611 |
/**
|
|
2612 |
Close all instances of a table open by this thread and replace
|
|
2613 |
them with exclusive name-locks.
|
|
2614 |
||
2615 |
@param thd Thread context
|
|
2616 |
@param db Database name for the table to be closed
|
|
2617 |
@param table_name Name of the table to be closed
|
|
2618 |
||
2619 |
@note This function assumes that if we are not under LOCK TABLES,
|
|
2620 |
then there is only one table open and locked. This means that
|
|
2621 |
the function probably has to be adjusted before it can be used
|
|
2622 |
anywhere outside ALTER TABLE.
|
|
2623 |
||
2624 |
@note Must not use TABLE_SHARE::table_name/db of the table being closed,
|
|
2625 |
the strings are used in a loop even after the share may be freed.
|
|
2626 |
*/
|
|
2627 |
||
2628 |
void close_data_files_and_morph_locks(THD *thd, const char *db, |
|
2629 |
const char *table_name) |
|
2630 |
{
|
|
2631 |
TABLE *table; |
|
2632 |
||
2633 |
safe_mutex_assert_owner(&LOCK_open); |
|
2634 |
||
2635 |
if (thd->lock) |
|
2636 |
{
|
|
2637 |
/*
|
|
2638 |
If we are not under LOCK TABLES we should have only one table
|
|
2639 |
open and locked so it makes sense to remove the lock at once.
|
|
2640 |
*/
|
|
2641 |
mysql_unlock_tables(thd, thd->lock); |
|
2642 |
thd->lock= 0; |
|
2643 |
}
|
|
2644 |
||
2645 |
/*
|
|
2646 |
Note that open table list may contain a name-lock placeholder
|
|
2647 |
for target table name if we process ALTER TABLE ... RENAME.
|
|
2648 |
So loop below makes sense even if we are not under LOCK TABLES.
|
|
2649 |
*/
|
|
2650 |
for (table=thd->open_tables; table ; table=table->next) |
|
2651 |
{
|
|
2652 |
if (!strcmp(table->s->table_name.str, table_name) && |
|
2653 |
!strcmp(table->s->db.str, db)) |
|
2654 |
{
|
|
2655 |
if (thd->locked_tables) |
|
2656 |
{
|
|
55
by brian
Update for using real bool types. |
2657 |
mysql_lock_remove(thd, thd->locked_tables, table, true); |
1
by brian
clean slate |
2658 |
}
|
2659 |
table->open_placeholder= 1; |
|
2660 |
close_handle_and_leave_table_as_lock(table); |
|
2661 |
}
|
|
2662 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2663 |
return; |
1
by brian
clean slate |
2664 |
}
|
2665 |
||
2666 |
||
2667 |
/**
|
|
2668 |
Reopen all tables with closed data files.
|
|
2669 |
||
2670 |
@param thd Thread context
|
|
2671 |
@param get_locks Should we get locks after reopening tables ?
|
|
2672 |
@param mark_share_as_old Mark share as old to protect from a impending
|
|
2673 |
global read lock.
|
|
2674 |
||
2675 |
@note Since this function can't properly handle prelocking and
|
|
2676 |
create placeholders it should be used in very special
|
|
2677 |
situations like FLUSH TABLES or ALTER TABLE. In general
|
|
2678 |
case one should just repeat open_tables()/lock_tables()
|
|
2679 |
combination when one needs tables to be reopened (for
|
|
2680 |
example see open_and_lock_tables()).
|
|
2681 |
||
2682 |
@note One should have lock on LOCK_open when calling this.
|
|
2683 |
||
55
by brian
Update for using real bool types. |
2684 |
@return false in case of success, true - otherwise.
|
1
by brian
clean slate |
2685 |
*/
|
2686 |
||
2687 |
bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old) |
|
2688 |
{
|
|
2689 |
TABLE *table,*next,**prev; |
|
2690 |
TABLE **tables,**tables_ptr; // For locks |
|
2691 |
bool error=0, not_used; |
|
2692 |
const uint flags= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN | |
|
2693 |
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK | |
|
2694 |
MYSQL_LOCK_IGNORE_FLUSH; |
|
2695 |
||
2696 |
if (!thd->open_tables) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2697 |
return(0); |
1
by brian
clean slate |
2698 |
|
2699 |
safe_mutex_assert_owner(&LOCK_open); |
|
2700 |
if (get_locks) |
|
2701 |
{
|
|
2702 |
/*
|
|
2703 |
The ptr is checked later
|
|
2704 |
Do not handle locks of MERGE children.
|
|
2705 |
*/
|
|
2706 |
uint opens=0; |
|
2707 |
for (table= thd->open_tables; table ; table=table->next) |
|
2708 |
opens++; |
|
2709 |
tables= (TABLE**) my_alloca(sizeof(TABLE*)*opens); |
|
2710 |
}
|
|
2711 |
else
|
|
2712 |
tables= &thd->open_tables; |
|
2713 |
tables_ptr =tables; |
|
2714 |
||
2715 |
prev= &thd->open_tables; |
|
2716 |
for (table=thd->open_tables; table ; table=next) |
|
2717 |
{
|
|
2718 |
uint db_stat=table->db_stat; |
|
2719 |
next=table->next; |
|
2720 |
if (!tables || (!db_stat && reopen_table(table))) |
|
2721 |
{
|
|
2722 |
my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->alias); |
|
2723 |
VOID(hash_delete(&open_cache,(uchar*) table)); |
|
2724 |
error=1; |
|
2725 |
}
|
|
2726 |
else
|
|
2727 |
{
|
|
2728 |
*prev= table; |
|
2729 |
prev= &table->next; |
|
2730 |
/* Do not handle locks of MERGE children. */
|
|
2731 |
if (get_locks && !db_stat) |
|
2732 |
*tables_ptr++= table; // need new lock on this |
|
2733 |
if (mark_share_as_old) |
|
2734 |
{
|
|
2735 |
table->s->version=0; |
|
2736 |
table->open_placeholder= 0; |
|
2737 |
}
|
|
2738 |
}
|
|
2739 |
}
|
|
2740 |
*prev=0; |
|
2741 |
if (tables != tables_ptr) // Should we get back old locks |
|
2742 |
{
|
|
2743 |
MYSQL_LOCK *lock; |
|
2744 |
/*
|
|
2745 |
We should always get these locks. Anyway, we must not go into
|
|
2746 |
wait_for_tables() as it tries to acquire LOCK_open, which is
|
|
2747 |
already locked.
|
|
2748 |
*/
|
|
2749 |
thd->some_tables_deleted=0; |
|
2750 |
if ((lock= mysql_lock_tables(thd, tables, (uint) (tables_ptr - tables), |
|
2751 |
flags, ¬_used))) |
|
2752 |
{
|
|
2753 |
thd->locked_tables=mysql_lock_merge(thd->locked_tables,lock); |
|
2754 |
}
|
|
2755 |
else
|
|
2756 |
{
|
|
2757 |
/*
|
|
2758 |
This case should only happen if there is a bug in the reopen logic.
|
|
2759 |
Need to issue error message to have a reply for the application.
|
|
2760 |
Not exactly what happened though, but close enough.
|
|
2761 |
*/
|
|
2762 |
my_error(ER_LOCK_DEADLOCK, MYF(0)); |
|
2763 |
error=1; |
|
2764 |
}
|
|
2765 |
}
|
|
2766 |
if (get_locks && tables) |
|
2767 |
{
|
|
2768 |
my_afree((uchar*) tables); |
|
2769 |
}
|
|
2770 |
broadcast_refresh(); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2771 |
return(error); |
1
by brian
clean slate |
2772 |
}
|
2773 |
||
2774 |
||
2775 |
/**
|
|
2776 |
Close handlers for tables in list, but leave the TABLE structure
|
|
2777 |
intact so that we can re-open these quickly.
|
|
2778 |
||
2779 |
@param thd Thread context
|
|
2780 |
@param table Head of the list of TABLE objects
|
|
55
by brian
Update for using real bool types. |
2781 |
@param morph_locks true - remove locks which we have on tables being closed
|
1
by brian
clean slate |
2782 |
but ensure that no DML or DDL will sneak in before
|
2783 |
we will re-open the table (i.e. temporarily morph
|
|
2784 |
our table-level locks into name-locks).
|
|
55
by brian
Update for using real bool types. |
2785 |
false - otherwise
|
1
by brian
clean slate |
2786 |
@param send_refresh Should we awake waiters even if we didn't close any tables?
|
2787 |
*/
|
|
2788 |
||
2789 |
static void close_old_data_files(THD *thd, TABLE *table, bool morph_locks, |
|
2790 |
bool send_refresh) |
|
2791 |
{
|
|
2792 |
bool found= send_refresh; |
|
2793 |
||
2794 |
for (; table ; table=table->next) |
|
2795 |
{
|
|
2796 |
/*
|
|
2797 |
Reopen marked for flush.
|
|
2798 |
*/
|
|
2799 |
if (table->needs_reopen_or_name_lock()) |
|
2800 |
{
|
|
2801 |
found=1; |
|
2802 |
if (table->db_stat) |
|
2803 |
{
|
|
2804 |
if (morph_locks) |
|
2805 |
{
|
|
2806 |
TABLE *ulcktbl= table; |
|
2807 |
if (ulcktbl->lock_count) |
|
2808 |
{
|
|
2809 |
/*
|
|
2810 |
Wake up threads waiting for table-level lock on this table
|
|
2811 |
so they won't sneak in when we will temporarily remove our
|
|
2812 |
lock on it. This will also give them a chance to close their
|
|
2813 |
instances of this table.
|
|
2814 |
*/
|
|
55
by brian
Update for using real bool types. |
2815 |
mysql_lock_abort(thd, ulcktbl, true); |
2816 |
mysql_lock_remove(thd, thd->locked_tables, ulcktbl, true); |
|
1
by brian
clean slate |
2817 |
ulcktbl->lock_count= 0; |
2818 |
}
|
|
2819 |
if ((ulcktbl != table) && ulcktbl->db_stat) |
|
2820 |
{
|
|
2821 |
/*
|
|
2822 |
Close the parent too. Note that parent can come later in
|
|
2823 |
the list of tables. It will then be noticed as closed and
|
|
2824 |
as a placeholder. When this happens, do not clear the
|
|
2825 |
placeholder flag. See the branch below ("***").
|
|
2826 |
*/
|
|
2827 |
ulcktbl->open_placeholder= 1; |
|
2828 |
close_handle_and_leave_table_as_lock(ulcktbl); |
|
2829 |
}
|
|
2830 |
/*
|
|
2831 |
We want to protect the table from concurrent DDL operations
|
|
2832 |
(like RENAME TABLE) until we will re-open and re-lock it.
|
|
2833 |
*/
|
|
2834 |
table->open_placeholder= 1; |
|
2835 |
}
|
|
2836 |
close_handle_and_leave_table_as_lock(table); |
|
2837 |
}
|
|
2838 |
else if (table->open_placeholder && !morph_locks) |
|
2839 |
{
|
|
2840 |
/*
|
|
2841 |
We come here only in close-for-back-off scenario. So we have to
|
|
2842 |
"close" create placeholder here to avoid deadlocks (for example,
|
|
2843 |
in case of concurrent execution of CREATE TABLE t1 SELECT * FROM t2
|
|
2844 |
and RENAME TABLE t2 TO t1). In close-for-re-open scenario we will
|
|
2845 |
probably want to let it stay.
|
|
2846 |
||
2847 |
Note "***": We must not enter this branch if the placeholder
|
|
2848 |
flag has been set because of a former close through a child.
|
|
2849 |
See above the comment that refers to this note.
|
|
2850 |
*/
|
|
2851 |
table->open_placeholder= 0; |
|
2852 |
}
|
|
2853 |
}
|
|
2854 |
}
|
|
2855 |
if (found) |
|
2856 |
broadcast_refresh(); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2857 |
return; |
1
by brian
clean slate |
2858 |
}
|
2859 |
||
2860 |
||
2861 |
/*
|
|
2862 |
Wait until all threads has closed the tables in the list
|
|
2863 |
We have also to wait if there is thread that has a lock on this table even
|
|
2864 |
if the table is closed
|
|
2865 |
*/
|
|
2866 |
||
2867 |
bool table_is_used(TABLE *table, bool wait_for_name_lock) |
|
2868 |
{
|
|
2869 |
do
|
|
2870 |
{
|
|
2871 |
char *key= table->s->table_cache_key.str; |
|
2872 |
uint key_length= table->s->table_cache_key.length; |
|
2873 |
||
2874 |
HASH_SEARCH_STATE state; |
|
2875 |
for (TABLE *search= (TABLE*) hash_first(&open_cache, (uchar*) key, |
|
2876 |
key_length, &state); |
|
2877 |
search ; |
|
2878 |
search= (TABLE*) hash_next(&open_cache, (uchar*) key, |
|
2879 |
key_length, &state)) |
|
2880 |
{
|
|
2881 |
if (search->in_use == table->in_use) |
|
2882 |
continue; // Name locked by this thread |
|
2883 |
/*
|
|
2884 |
We can't use the table under any of the following conditions:
|
|
2885 |
- There is an name lock on it (Table is to be deleted or altered)
|
|
2886 |
- If we are in flush table and we didn't execute the flush
|
|
2887 |
- If the table engine is open and it's an old version
|
|
2888 |
(We must wait until all engines are shut down to use the table)
|
|
2889 |
*/
|
|
2890 |
if ( (search->locked_by_name && wait_for_name_lock) || |
|
2891 |
(search->is_name_opened() && search->needs_reopen_or_name_lock())) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2892 |
return(1); |
1
by brian
clean slate |
2893 |
}
|
2894 |
} while ((table=table->next)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2895 |
return(0); |
1
by brian
clean slate |
2896 |
}
|
2897 |
||
2898 |
||
2899 |
/* Wait until all used tables are refreshed */
|
|
2900 |
||
2901 |
bool wait_for_tables(THD *thd) |
|
2902 |
{
|
|
2903 |
bool result; |
|
2904 |
||
2905 |
thd_proc_info(thd, "Waiting for tables"); |
|
2906 |
pthread_mutex_lock(&LOCK_open); |
|
2907 |
while (!thd->killed) |
|
2908 |
{
|
|
2909 |
thd->some_tables_deleted=0; |
|
2910 |
close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0); |
|
2911 |
mysql_ha_flush(thd); |
|
2912 |
if (!table_is_used(thd->open_tables,1)) |
|
2913 |
break; |
|
2914 |
(void) pthread_cond_wait(&COND_refresh,&LOCK_open); |
|
2915 |
}
|
|
2916 |
if (thd->killed) |
|
2917 |
result= 1; // aborted |
|
2918 |
else
|
|
2919 |
{
|
|
2920 |
/* Now we can open all tables without any interference */
|
|
2921 |
thd_proc_info(thd, "Reopen tables"); |
|
2922 |
thd->version= refresh_version; |
|
2923 |
result=reopen_tables(thd,0,0); |
|
2924 |
}
|
|
2925 |
pthread_mutex_unlock(&LOCK_open); |
|
2926 |
thd_proc_info(thd, 0); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
2927 |
return(result); |
1
by brian
clean slate |
2928 |
}
|
2929 |
||
2930 |
||
2931 |
/*
|
|
2932 |
drop tables from locked list
|
|
2933 |
||
2934 |
SYNOPSIS
|
|
2935 |
drop_locked_tables()
|
|
2936 |
thd Thread thandler
|
|
2937 |
db Database
|
|
2938 |
table_name Table name
|
|
2939 |
||
2940 |
INFORMATION
|
|
2941 |
This is only called on drop tables
|
|
2942 |
||
2943 |
The TABLE object for the dropped table is unlocked but still kept around
|
|
2944 |
as a name lock, which means that the table will be available for other
|
|
2945 |
thread as soon as we call unlock_table_names().
|
|
2946 |
If there is multiple copies of the table locked, all copies except
|
|
2947 |
the first, which acts as a name lock, is removed.
|
|
2948 |
||
2949 |
RETURN
|
|
2950 |
# If table existed, return table
|
|
2951 |
0 Table was not locked
|
|
2952 |
*/
|
|
2953 |
||
2954 |
||
2955 |
TABLE *drop_locked_tables(THD *thd,const char *db, const char *table_name) |
|
2956 |
{
|
|
2957 |
TABLE *table,*next,**prev, *found= 0; |
|
2958 |
prev= &thd->open_tables; |
|
2959 |
||
2960 |
/*
|
|
2961 |
Note that we need to hold LOCK_open while changing the
|
|
2962 |
open_tables list. Another thread may work on it.
|
|
2963 |
(See: remove_table_from_cache(), mysql_wait_completed_table())
|
|
2964 |
Closing a MERGE child before the parent would be fatal if the
|
|
2965 |
other thread tries to abort the MERGE lock in between.
|
|
2966 |
*/
|
|
2967 |
for (table= thd->open_tables; table ; table=next) |
|
2968 |
{
|
|
2969 |
next=table->next; |
|
2970 |
if (!strcmp(table->s->table_name.str, table_name) && |
|
2971 |
!strcmp(table->s->db.str, db)) |
|
2972 |
{
|
|
55
by brian
Update for using real bool types. |
2973 |
mysql_lock_remove(thd, thd->locked_tables, table, true); |
1
by brian
clean slate |
2974 |
|
2975 |
if (!found) |
|
2976 |
{
|
|
2977 |
found= table; |
|
2978 |
/* Close engine table, but keep object around as a name lock */
|
|
2979 |
if (table->db_stat) |
|
2980 |
{
|
|
2981 |
table->db_stat= 0; |
|
2982 |
table->file->close(); |
|
2983 |
}
|
|
2984 |
}
|
|
2985 |
else
|
|
2986 |
{
|
|
2987 |
/* We already have a name lock, remove copy */
|
|
2988 |
VOID(hash_delete(&open_cache,(uchar*) table)); |
|
2989 |
}
|
|
2990 |
}
|
|
2991 |
else
|
|
2992 |
{
|
|
2993 |
*prev=table; |
|
2994 |
prev= &table->next; |
|
2995 |
}
|
|
2996 |
}
|
|
2997 |
*prev=0; |
|
2998 |
if (found) |
|
2999 |
broadcast_refresh(); |
|
3000 |
if (thd->locked_tables && thd->locked_tables->table_count == 0) |
|
3001 |
{
|
|
3002 |
my_free((uchar*) thd->locked_tables,MYF(0)); |
|
3003 |
thd->locked_tables=0; |
|
3004 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3005 |
return(found); |
1
by brian
clean slate |
3006 |
}
|
3007 |
||
3008 |
||
3009 |
/*
|
|
3010 |
If we have the table open, which only happens when a LOCK TABLE has been
|
|
3011 |
done on the table, change the lock type to a lock that will abort all
|
|
3012 |
other threads trying to get the lock.
|
|
3013 |
*/
|
|
3014 |
||
3015 |
void abort_locked_tables(THD *thd,const char *db, const char *table_name) |
|
3016 |
{
|
|
3017 |
TABLE *table; |
|
3018 |
for (table= thd->open_tables; table ; table= table->next) |
|
3019 |
{
|
|
3020 |
if (!strcmp(table->s->table_name.str, table_name) && |
|
3021 |
!strcmp(table->s->db.str, db)) |
|
3022 |
{
|
|
3023 |
/* If MERGE child, forward lock handling to parent. */
|
|
55
by brian
Update for using real bool types. |
3024 |
mysql_lock_abort(thd, table, true); |
1
by brian
clean slate |
3025 |
break; |
3026 |
}
|
|
3027 |
}
|
|
3028 |
}
|
|
3029 |
||
3030 |
||
3031 |
/*
|
|
3032 |
Function to assign a new table map id to a table share.
|
|
3033 |
||
3034 |
PARAMETERS
|
|
3035 |
||
3036 |
share - Pointer to table share structure
|
|
3037 |
||
3038 |
DESCRIPTION
|
|
3039 |
||
3040 |
We are intentionally not checking that share->mutex is locked
|
|
3041 |
since this function should only be called when opening a table
|
|
3042 |
share and before it is entered into the table_def_cache (meaning
|
|
3043 |
that it cannot be fetched by another thread, even accidentally).
|
|
3044 |
||
3045 |
PRE-CONDITION(S)
|
|
3046 |
||
3047 |
share is non-NULL
|
|
3048 |
The LOCK_open mutex is locked
|
|
3049 |
||
3050 |
POST-CONDITION(S)
|
|
3051 |
||
3052 |
share->table_map_id is given a value that with a high certainty is
|
|
3053 |
not used by any other table (the only case where a table id can be
|
|
3054 |
reused is on wrap-around, which means more than 4 billion table
|
|
3055 |
share opens have been executed while one table was open all the
|
|
3056 |
time).
|
|
3057 |
||
3058 |
share->table_map_id is not ~0UL.
|
|
3059 |
*/
|
|
3060 |
void assign_new_table_id(TABLE_SHARE *share) |
|
3061 |
{
|
|
3062 |
static ulong last_table_id= ~0UL; |
|
3063 |
||
3064 |
/* Preconditions */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3065 |
assert(share != NULL); |
1
by brian
clean slate |
3066 |
safe_mutex_assert_owner(&LOCK_open); |
3067 |
||
3068 |
ulong tid= ++last_table_id; /* get next id */ |
|
3069 |
/*
|
|
3070 |
There is one reserved number that cannot be used. Remember to
|
|
3071 |
change this when 6-byte global table id's are introduced.
|
|
3072 |
*/
|
|
3073 |
if (unlikely(tid == ~0UL)) |
|
3074 |
tid= ++last_table_id; |
|
3075 |
share->table_map_id= tid; |
|
3076 |
||
3077 |
/* Post conditions */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3078 |
assert(share->table_map_id != ~0UL); |
1
by brian
clean slate |
3079 |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3080 |
return; |
1
by brian
clean slate |
3081 |
}
|
3082 |
||
3083 |
/*
|
|
3084 |
Load a table definition from file and open unireg table
|
|
3085 |
||
3086 |
SYNOPSIS
|
|
3087 |
open_unireg_entry()
|
|
3088 |
thd Thread handle
|
|
3089 |
entry Store open table definition here
|
|
3090 |
table_list TABLE_LIST with db, table_name & belong_to_view
|
|
3091 |
alias Alias name
|
|
3092 |
cache_key Key for share_cache
|
|
3093 |
cache_key_length length of cache_key
|
|
3094 |
mem_root temporary mem_root for parsing
|
|
3095 |
flags the OPEN_VIEW_NO_PARSE flag to be passed to
|
|
3096 |
openfrm()/open_new_frm()
|
|
3097 |
||
3098 |
NOTES
|
|
3099 |
Extra argument for open is taken from thd->open_options
|
|
3100 |
One must have a lock on LOCK_open when calling this function
|
|
3101 |
||
3102 |
RETURN
|
|
3103 |
0 ok
|
|
3104 |
# Error
|
|
3105 |
*/
|
|
3106 |
||
3107 |
static int open_unireg_entry(THD *thd, TABLE *entry, TABLE_LIST *table_list, |
|
3108 |
const char *alias, |
|
3109 |
char *cache_key, uint cache_key_length, |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
3110 |
MEM_ROOT *mem_root __attribute__((unused)), |
3111 |
uint flags __attribute__((unused))) |
|
1
by brian
clean slate |
3112 |
{
|
3113 |
int error; |
|
3114 |
TABLE_SHARE *share; |
|
3115 |
uint discover_retry_count= 0; |
|
3116 |
||
3117 |
safe_mutex_assert_owner(&LOCK_open); |
|
3118 |
retry: |
|
3119 |
if (!(share= get_table_share_with_create(thd, table_list, cache_key, |
|
3120 |
cache_key_length, |
|
3121 |
OPEN_VIEW | |
|
3122 |
table_list->i_s_requested_object, |
|
3123 |
&error))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3124 |
return(1); |
1
by brian
clean slate |
3125 |
|
3126 |
while ((error= open_table_from_share(thd, share, alias, |
|
3127 |
(uint) (HA_OPEN_KEYFILE | |
|
3128 |
HA_OPEN_RNDFILE | |
|
3129 |
HA_GET_INDEX | |
|
3130 |
HA_TRY_READ_ONLY), |
|
3131 |
(READ_KEYINFO | COMPUTE_TYPES | |
|
3132 |
EXTRA_RECORD), |
|
3133 |
thd->open_options, entry, OTM_OPEN))) |
|
3134 |
{
|
|
3135 |
if (error == 7) // Table def changed |
|
3136 |
{
|
|
3137 |
share->version= 0; // Mark share as old |
|
3138 |
if (discover_retry_count++) // Retry once |
|
3139 |
goto err; |
|
3140 |
||
3141 |
/*
|
|
3142 |
TODO:
|
|
3143 |
Here we should wait until all threads has released the table.
|
|
3144 |
For now we do one retry. This may cause a deadlock if there
|
|
3145 |
is other threads waiting for other tables used by this thread.
|
|
3146 |
|
|
3147 |
Proper fix would be to if the second retry failed:
|
|
3148 |
- Mark that table def changed
|
|
3149 |
- Return from open table
|
|
3150 |
- Close all tables used by this thread
|
|
3151 |
- Start waiting that the share is released
|
|
3152 |
- Retry by opening all tables again
|
|
3153 |
*/
|
|
3154 |
if (ha_create_table_from_engine(thd, table_list->db, |
|
3155 |
table_list->table_name)) |
|
3156 |
goto err; |
|
3157 |
/*
|
|
3158 |
TO BE FIXED
|
|
3159 |
To avoid deadlock, only wait for release if no one else is
|
|
3160 |
using the share.
|
|
3161 |
*/
|
|
3162 |
if (share->ref_count != 1) |
|
3163 |
goto err; |
|
3164 |
/* Free share and wait until it's released by all threads */
|
|
3165 |
release_table_share(share, RELEASE_WAIT_FOR_DROP); |
|
3166 |
if (!thd->killed) |
|
3167 |
{
|
|
261.4.1
by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR. |
3168 |
drizzle_reset_errors(thd, 1); // Clear warnings |
1
by brian
clean slate |
3169 |
thd->clear_error(); // Clear error message |
3170 |
goto retry; |
|
3171 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3172 |
return(1); |
1
by brian
clean slate |
3173 |
}
|
3174 |
if (!entry->s || !entry->s->crashed) |
|
3175 |
goto err; |
|
3176 |
// Code below is for repairing a crashed file
|
|
55
by brian
Update for using real bool types. |
3177 |
if ((error= lock_table_name(thd, table_list, true))) |
1
by brian
clean slate |
3178 |
{
|
3179 |
if (error < 0) |
|
3180 |
goto err; |
|
3181 |
if (wait_for_locked_table_names(thd, table_list)) |
|
3182 |
{
|
|
3183 |
unlock_table_name(thd, table_list); |
|
3184 |
goto err; |
|
3185 |
}
|
|
3186 |
}
|
|
3187 |
pthread_mutex_unlock(&LOCK_open); |
|
3188 |
thd->clear_error(); // Clear error message |
|
3189 |
error= 0; |
|
3190 |
if (open_table_from_share(thd, share, alias, |
|
3191 |
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | |
|
3192 |
HA_GET_INDEX | |
|
3193 |
HA_TRY_READ_ONLY), |
|
3194 |
READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD, |
|
3195 |
ha_open_options | HA_OPEN_FOR_REPAIR, |
|
3196 |
entry, OTM_OPEN) || ! entry->file || |
|
3197 |
(entry->file->is_crashed() && entry->file->ha_check_and_repair(thd))) |
|
3198 |
{
|
|
3199 |
/* Give right error message */
|
|
3200 |
thd->clear_error(); |
|
3201 |
my_error(ER_NOT_KEYFILE, MYF(0), share->table_name.str, my_errno); |
|
3202 |
sql_print_error("Couldn't repair table: %s.%s", share->db.str, |
|
3203 |
share->table_name.str); |
|
3204 |
if (entry->file) |
|
3205 |
closefrm(entry, 0); |
|
3206 |
error=1; |
|
3207 |
}
|
|
3208 |
else
|
|
3209 |
thd->clear_error(); // Clear error message |
|
3210 |
pthread_mutex_lock(&LOCK_open); |
|
3211 |
unlock_table_name(thd, table_list); |
|
3212 |
||
3213 |
if (error) |
|
3214 |
goto err; |
|
3215 |
break; |
|
3216 |
}
|
|
3217 |
||
3218 |
/*
|
|
3219 |
If we are here, there was no fatal error (but error may be still
|
|
3220 |
unitialized).
|
|
3221 |
*/
|
|
3222 |
if (unlikely(entry->file->implicit_emptied)) |
|
3223 |
{
|
|
3224 |
entry->file->implicit_emptied= 0; |
|
3225 |
if (mysql_bin_log.is_open()) |
|
3226 |
{
|
|
3227 |
char *query, *end; |
|
3228 |
uint query_buf_size= 20 + share->db.length + share->table_name.length +1; |
|
3229 |
if ((query= (char*) my_malloc(query_buf_size,MYF(MY_WME)))) |
|
3230 |
{
|
|
3231 |
/* this DELETE FROM is needed even with row-based binlogging */
|
|
266.1.21
by Monty Taylor
Removed references to strmov and strnmov |
3232 |
end = strxmov(stpcpy(query, "DELETE FROM `"), |
1
by brian
clean slate |
3233 |
share->db.str,"`.`",share->table_name.str,"`", NullS); |
3234 |
thd->binlog_query(THD::STMT_QUERY_TYPE, |
|
55
by brian
Update for using real bool types. |
3235 |
query, (ulong)(end-query), false, false); |
1
by brian
clean slate |
3236 |
my_free(query, MYF(0)); |
3237 |
}
|
|
3238 |
else
|
|
3239 |
{
|
|
3240 |
/*
|
|
3241 |
As replication is maybe going to be corrupted, we need to warn the
|
|
3242 |
DBA on top of warning the client (which will automatically be done
|
|
3243 |
because of MYF(MY_WME) in my_malloc() above).
|
|
3244 |
*/
|
|
3245 |
sql_print_error("When opening HEAP table, could not allocate memory " |
|
3246 |
"to write 'DELETE FROM `%s`.`%s`' to the binary log", |
|
3247 |
table_list->db, table_list->table_name); |
|
3248 |
closefrm(entry, 0); |
|
3249 |
goto err; |
|
3250 |
}
|
|
3251 |
}
|
|
3252 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3253 |
return(0); |
1
by brian
clean slate |
3254 |
|
3255 |
err: |
|
3256 |
release_table_share(share, RELEASE_NORMAL); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3257 |
return(1); |
1
by brian
clean slate |
3258 |
}
|
3259 |
||
3260 |
||
3261 |
/*
|
|
3262 |
Open all tables in list
|
|
3263 |
||
3264 |
SYNOPSIS
|
|
3265 |
open_tables()
|
|
3266 |
thd - thread handler
|
|
3267 |
start - list of tables in/out
|
|
3268 |
counter - number of opened tables will be return using this parameter
|
|
3269 |
flags - bitmap of flags to modify how the tables will be open:
|
|
3270 |
MYSQL_LOCK_IGNORE_FLUSH - open table even if someone has
|
|
3271 |
done a flush or namelock on it.
|
|
3272 |
||
3273 |
NOTE
|
|
3274 |
Unless we are already in prelocked mode, this function will also precache
|
|
3275 |
all SP/SFs explicitly or implicitly (via views and triggers) used by the
|
|
3276 |
query and add tables needed for their execution to table list. If resulting
|
|
3277 |
tables list will be non empty it will mark query as requiring precaching.
|
|
3278 |
Prelocked mode will be enabled for such query during lock_tables() call.
|
|
3279 |
||
3280 |
If query for which we are opening tables is already marked as requiring
|
|
3281 |
prelocking it won't do such precaching and will simply reuse table list
|
|
3282 |
which is already built.
|
|
3283 |
||
3284 |
RETURN
|
|
3285 |
0 - OK
|
|
3286 |
-1 - error
|
|
3287 |
*/
|
|
3288 |
||
3289 |
int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) |
|
3290 |
{
|
|
3291 |
TABLE_LIST *tables= NULL; |
|
3292 |
bool refresh; |
|
3293 |
int result=0; |
|
3294 |
MEM_ROOT new_frm_mem; |
|
3295 |
/* Also used for indicating that prelocking is need */
|
|
3296 |
bool safe_to_ignore_table; |
|
3297 |
||
3298 |
/*
|
|
3299 |
temporary mem_root for new .frm parsing.
|
|
3300 |
TODO: variables for size
|
|
3301 |
*/
|
|
3302 |
init_sql_alloc(&new_frm_mem, 8024, 8024); |
|
3303 |
||
3304 |
thd->current_tablenr= 0; |
|
3305 |
restart: |
|
3306 |
*counter= 0; |
|
3307 |
thd_proc_info(thd, "Opening tables"); |
|
3308 |
||
3309 |
/*
|
|
3310 |
For every table in the list of tables to open, try to find or open
|
|
3311 |
a table.
|
|
3312 |
*/
|
|
3313 |
for (tables= *start; tables ;tables= tables->next_global) |
|
3314 |
{
|
|
55
by brian
Update for using real bool types. |
3315 |
safe_to_ignore_table= false; |
1
by brian
clean slate |
3316 |
|
3317 |
/*
|
|
3318 |
Ignore placeholders for derived tables. After derived tables
|
|
3319 |
processing, link to created temporary table will be put here.
|
|
3320 |
If this is derived table for view then we still want to process
|
|
3321 |
routines used by this view.
|
|
3322 |
*/
|
|
3323 |
if (tables->derived) |
|
3324 |
{
|
|
3325 |
continue; |
|
3326 |
}
|
|
3327 |
/*
|
|
3328 |
If this TABLE_LIST object is a placeholder for an information_schema
|
|
3329 |
table, create a temporary table to represent the information_schema
|
|
3330 |
table in the query. Do not fill it yet - will be filled during
|
|
3331 |
execution.
|
|
3332 |
*/
|
|
3333 |
if (tables->schema_table) |
|
3334 |
{
|
|
3335 |
if (!mysql_schema_table(thd, thd->lex, tables)) |
|
3336 |
continue; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3337 |
return(-1); |
1
by brian
clean slate |
3338 |
}
|
3339 |
(*counter)++; |
|
3340 |
||
3341 |
/*
|
|
3342 |
Not a placeholder: must be a base table or a view, and the table is
|
|
3343 |
not opened yet. Try to open the table.
|
|
3344 |
*/
|
|
3345 |
if (!tables->table) |
|
3346 |
tables->table= open_table(thd, tables, &new_frm_mem, &refresh, flags); |
|
3347 |
||
3348 |
if (!tables->table) |
|
3349 |
{
|
|
3350 |
free_root(&new_frm_mem, MYF(MY_KEEP_PREALLOC)); |
|
3351 |
||
3352 |
if (refresh) // Refresh in progress |
|
3353 |
{
|
|
3354 |
/*
|
|
3355 |
We have met name-locked or old version of table. Now we have
|
|
3356 |
to close all tables which are not up to date. We also have to
|
|
3357 |
throw away set of prelocked tables (and thus close tables from
|
|
3358 |
this set that were open by now) since it possible that one of
|
|
3359 |
tables which determined its content was changed.
|
|
3360 |
||
3361 |
Instead of implementing complex/non-robust logic mentioned
|
|
3362 |
above we simply close and then reopen all tables.
|
|
3363 |
||
3364 |
In order to prepare for recalculation of set of prelocked tables
|
|
3365 |
we pretend that we have finished calculation which we were doing
|
|
3366 |
currently.
|
|
3367 |
*/
|
|
3368 |
close_tables_for_reopen(thd, start); |
|
3369 |
goto restart; |
|
3370 |
}
|
|
3371 |
||
3372 |
if (safe_to_ignore_table) |
|
3373 |
continue; |
|
3374 |
||
3375 |
result= -1; // Fatal error |
|
3376 |
break; |
|
3377 |
}
|
|
3378 |
if (tables->lock_type != TL_UNLOCK && ! thd->locked_tables) |
|
3379 |
{
|
|
3380 |
if (tables->lock_type == TL_WRITE_DEFAULT) |
|
3381 |
tables->table->reginfo.lock_type= thd->update_lock_default; |
|
3382 |
else if (tables->table->s->tmp_table == NO_TMP_TABLE) |
|
3383 |
tables->table->reginfo.lock_type= tables->lock_type; |
|
3384 |
}
|
|
3385 |
}
|
|
3386 |
||
3387 |
thd_proc_info(thd, 0); |
|
3388 |
free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block |
|
3389 |
||
3390 |
if (result && tables) |
|
3391 |
{
|
|
3392 |
/*
|
|
3393 |
Some functions determine success as (tables->table != NULL).
|
|
3394 |
tables->table is in thd->open_tables. It won't go lost. If the
|
|
3395 |
error happens on a MERGE child, clear the parents TABLE reference.
|
|
3396 |
*/
|
|
3397 |
if (tables->parent_l) |
|
3398 |
tables->parent_l->table= NULL; |
|
3399 |
tables->table= NULL; |
|
3400 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3401 |
return(result); |
1
by brian
clean slate |
3402 |
}
|
3403 |
||
3404 |
||
3405 |
/*
|
|
3406 |
Check that lock is ok for tables; Call start stmt if ok
|
|
3407 |
||
3408 |
SYNOPSIS
|
|
3409 |
check_lock_and_start_stmt()
|
|
3410 |
thd Thread handle
|
|
3411 |
table_list Table to check
|
|
3412 |
lock_type Lock used for table
|
|
3413 |
||
3414 |
RETURN VALUES
|
|
3415 |
0 ok
|
|
3416 |
1 error
|
|
3417 |
*/
|
|
3418 |
||
3419 |
static bool check_lock_and_start_stmt(THD *thd, TABLE *table, |
|
3420 |
thr_lock_type lock_type) |
|
3421 |
{
|
|
3422 |
int error; |
|
3423 |
||
3424 |
if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ && |
|
3425 |
(int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ) |
|
3426 |
{
|
|
3427 |
my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),table->alias); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3428 |
return(1); |
1
by brian
clean slate |
3429 |
}
|
3430 |
if ((error=table->file->start_stmt(thd, lock_type))) |
|
3431 |
{
|
|
3432 |
table->file->print_error(error,MYF(0)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3433 |
return(1); |
1
by brian
clean slate |
3434 |
}
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3435 |
return(0); |
1
by brian
clean slate |
3436 |
}
|
3437 |
||
3438 |
||
3439 |
/**
|
|
3440 |
@brief Open and lock one table
|
|
3441 |
||
3442 |
@param[in] thd thread handle
|
|
3443 |
@param[in] table_l table to open is first table in this list
|
|
3444 |
@param[in] lock_type lock to use for table
|
|
3445 |
||
3446 |
@return table
|
|
3447 |
@retval != NULL OK, opened table returned
|
|
3448 |
@retval NULL Error
|
|
3449 |
||
3450 |
@note
|
|
3451 |
If ok, the following are also set:
|
|
3452 |
table_list->lock_type lock_type
|
|
3453 |
table_list->table table
|
|
3454 |
||
3455 |
@note
|
|
3456 |
If table_l is a list, not a single table, the list is temporarily
|
|
3457 |
broken.
|
|
3458 |
||
3459 |
@detail
|
|
3460 |
This function is meant as a replacement for open_ltable() when
|
|
3461 |
MERGE tables can be opened. open_ltable() cannot open MERGE tables.
|
|
3462 |
||
3463 |
There may be more differences between open_n_lock_single_table() and
|
|
3464 |
open_ltable(). One known difference is that open_ltable() does
|
|
3465 |
neither call decide_logging_format() nor handle some other logging
|
|
3466 |
and locking issues because it does not call lock_tables().
|
|
3467 |
*/
|
|
3468 |
||
3469 |
TABLE *open_n_lock_single_table(THD *thd, TABLE_LIST *table_l, |
|
3470 |
thr_lock_type lock_type) |
|
3471 |
{
|
|
3472 |
TABLE_LIST *save_next_global; |
|
3473 |
||
3474 |
/* Remember old 'next' pointer. */
|
|
3475 |
save_next_global= table_l->next_global; |
|
3476 |
/* Break list. */
|
|
3477 |
table_l->next_global= NULL; |
|
3478 |
||
3479 |
/* Set requested lock type. */
|
|
3480 |
table_l->lock_type= lock_type; |
|
3481 |
/* Allow to open real tables only. */
|
|
3482 |
table_l->required_type= FRMTYPE_TABLE; |
|
3483 |
||
3484 |
/* Open the table. */
|
|
3485 |
if (simple_open_n_lock_tables(thd, table_l)) |
|
3486 |
table_l->table= NULL; /* Just to be sure. */ |
|
3487 |
||
3488 |
/* Restore list. */
|
|
3489 |
table_l->next_global= save_next_global; |
|
3490 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3491 |
return(table_l->table); |
1
by brian
clean slate |
3492 |
}
|
3493 |
||
3494 |
||
3495 |
/*
|
|
3496 |
Open and lock one table
|
|
3497 |
||
3498 |
SYNOPSIS
|
|
3499 |
open_ltable()
|
|
3500 |
thd Thread handler
|
|
3501 |
table_list Table to open is first table in this list
|
|
3502 |
lock_type Lock to use for open
|
|
3503 |
lock_flags Flags passed to mysql_lock_table
|
|
3504 |
||
3505 |
NOTE
|
|
3506 |
This function don't do anything like SP/SF/views/triggers analysis done
|
|
3507 |
in open_tables(). It is intended for opening of only one concrete table.
|
|
3508 |
And used only in special contexts.
|
|
3509 |
||
3510 |
RETURN VALUES
|
|
3511 |
table Opened table
|
|
3512 |
0 Error
|
|
3513 |
|
|
3514 |
If ok, the following are also set:
|
|
3515 |
table_list->lock_type lock_type
|
|
3516 |
table_list->table table
|
|
3517 |
*/
|
|
3518 |
||
3519 |
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type, |
|
3520 |
uint lock_flags) |
|
3521 |
{
|
|
3522 |
TABLE *table; |
|
3523 |
bool refresh; |
|
3524 |
||
3525 |
thd_proc_info(thd, "Opening table"); |
|
3526 |
thd->current_tablenr= 0; |
|
3527 |
/* open_ltable can be used only for BASIC TABLEs */
|
|
3528 |
table_list->required_type= FRMTYPE_TABLE; |
|
3529 |
while (!(table= open_table(thd, table_list, thd->mem_root, &refresh, 0)) && |
|
3530 |
refresh) |
|
3531 |
;
|
|
3532 |
||
3533 |
if (table) |
|
3534 |
{
|
|
3535 |
table_list->lock_type= lock_type; |
|
3536 |
table_list->table= table; |
|
3537 |
if (thd->locked_tables) |
|
3538 |
{
|
|
3539 |
if (check_lock_and_start_stmt(thd, table, lock_type)) |
|
3540 |
table= 0; |
|
3541 |
}
|
|
3542 |
else
|
|
3543 |
{
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3544 |
assert(thd->lock == 0); // You must lock everything at once |
1
by brian
clean slate |
3545 |
if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK) |
3546 |
if (! (thd->lock= mysql_lock_tables(thd, &table_list->table, 1, |
|
3547 |
lock_flags, &refresh))) |
|
3548 |
table= 0; |
|
3549 |
}
|
|
3550 |
}
|
|
3551 |
||
3552 |
thd_proc_info(thd, 0); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3553 |
return(table); |
1
by brian
clean slate |
3554 |
}
|
3555 |
||
3556 |
||
3557 |
/*
|
|
3558 |
Open all tables in list, locks them and optionally process derived tables.
|
|
3559 |
||
3560 |
SYNOPSIS
|
|
3561 |
open_and_lock_tables_derived()
|
|
3562 |
thd - thread handler
|
|
3563 |
tables - list of tables for open&locking
|
|
3564 |
derived - if to handle derived tables
|
|
3565 |
||
3566 |
RETURN
|
|
55
by brian
Update for using real bool types. |
3567 |
false - ok
|
3568 |
true - error
|
|
1
by brian
clean slate |
3569 |
|
3570 |
NOTE
|
|
3571 |
The lock will automaticaly be freed by close_thread_tables()
|
|
3572 |
||
3573 |
NOTE
|
|
3574 |
There are two convenience functions:
|
|
3575 |
- simple_open_n_lock_tables(thd, tables) without derived handling
|
|
3576 |
- open_and_lock_tables(thd, tables) with derived handling
|
|
3577 |
Both inline functions call open_and_lock_tables_derived() with
|
|
3578 |
the third argument set appropriately.
|
|
3579 |
*/
|
|
3580 |
||
3581 |
int open_and_lock_tables_derived(THD *thd, TABLE_LIST *tables, bool derived) |
|
3582 |
{
|
|
3583 |
uint counter; |
|
3584 |
bool need_reopen; |
|
3585 |
||
3586 |
for ( ; ; ) |
|
3587 |
{
|
|
3588 |
if (open_tables(thd, &tables, &counter, 0)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3589 |
return(-1); |
1
by brian
clean slate |
3590 |
|
3591 |
if (!lock_tables(thd, tables, counter, &need_reopen)) |
|
3592 |
break; |
|
3593 |
if (!need_reopen) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3594 |
return(-1); |
1
by brian
clean slate |
3595 |
close_tables_for_reopen(thd, &tables); |
3596 |
}
|
|
3597 |
if (derived && |
|
3598 |
(mysql_handle_derived(thd->lex, &mysql_derived_prepare) || |
|
3599 |
(thd->fill_derived_tables() && |
|
3600 |
mysql_handle_derived(thd->lex, &mysql_derived_filling)))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3601 |
return(true); /* purecov: inspected */ |
3602 |
return(0); |
|
1
by brian
clean slate |
3603 |
}
|
3604 |
||
3605 |
||
3606 |
/*
|
|
3607 |
Open all tables in list and process derived tables
|
|
3608 |
||
3609 |
SYNOPSIS
|
|
3610 |
open_normal_and_derived_tables
|
|
3611 |
thd - thread handler
|
|
3612 |
tables - list of tables for open
|
|
3613 |
flags - bitmap of flags to modify how the tables will be open:
|
|
3614 |
MYSQL_LOCK_IGNORE_FLUSH - open table even if someone has
|
|
3615 |
done a flush or namelock on it.
|
|
3616 |
||
3617 |
RETURN
|
|
55
by brian
Update for using real bool types. |
3618 |
false - ok
|
3619 |
true - error
|
|
1
by brian
clean slate |
3620 |
|
3621 |
NOTE
|
|
3622 |
This is to be used on prepare stage when you don't read any
|
|
3623 |
data from the tables.
|
|
3624 |
*/
|
|
3625 |
||
3626 |
bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags) |
|
3627 |
{
|
|
3628 |
uint counter; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3629 |
assert(!thd->fill_derived_tables()); |
1
by brian
clean slate |
3630 |
if (open_tables(thd, &tables, &counter, flags) || |
3631 |
mysql_handle_derived(thd->lex, &mysql_derived_prepare)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3632 |
return(true); /* purecov: inspected */ |
3633 |
return(0); |
|
1
by brian
clean slate |
3634 |
}
|
3635 |
||
3636 |
||
3637 |
/**
|
|
3638 |
Decide on logging format to use for the statement.
|
|
3639 |
||
3640 |
Compute the capabilities vector for the involved storage engines
|
|
3641 |
and mask out the flags for the binary log. Right now, the binlog
|
|
3642 |
flags only include the capabilities of the storage engines, so this
|
|
3643 |
is safe.
|
|
3644 |
||
3645 |
We now have three alternatives that prevent the statement from
|
|
3646 |
being loggable:
|
|
3647 |
||
3648 |
1. If there are no capabilities left (all flags are clear) it is
|
|
3649 |
not possible to log the statement at all, so we roll back the
|
|
3650 |
statement and report an error.
|
|
3651 |
||
3652 |
2. Statement mode is set, but the capabilities indicate that
|
|
3653 |
statement format is not possible.
|
|
3654 |
||
3655 |
3. Row mode is set, but the capabilities indicate that row
|
|
3656 |
format is not possible.
|
|
3657 |
||
3658 |
4. Statement is unsafe, but the capabilities indicate that row
|
|
3659 |
format is not possible.
|
|
3660 |
||
3661 |
If we are in MIXED mode, we then decide what logging format to use:
|
|
3662 |
||
3663 |
1. If the statement is unsafe, row-based logging is used.
|
|
3664 |
||
3665 |
2. If statement-based logging is not possible, row-based logging is
|
|
3666 |
used.
|
|
3667 |
||
3668 |
3. Otherwise, statement-based logging is used.
|
|
3669 |
||
3670 |
@param thd Client thread
|
|
3671 |
@param tables Tables involved in the query
|
|
3672 |
*/
|
|
3673 |
||
3674 |
int decide_logging_format(THD *thd, TABLE_LIST *tables) |
|
3675 |
{
|
|
3676 |
if (mysql_bin_log.is_open() && (thd->options & OPTION_BIN_LOG)) |
|
3677 |
{
|
|
3678 |
handler::Table_flags flags_some_set= handler::Table_flags(); |
|
3679 |
handler::Table_flags flags_all_set= ~handler::Table_flags(); |
|
199
by Brian Aker
my_bool... |
3680 |
bool multi_engine= false; |
1
by brian
clean slate |
3681 |
void* prev_ht= NULL; |
3682 |
for (TABLE_LIST *table= tables; table; table= table->next_global) |
|
3683 |
{
|
|
3684 |
if (!table->placeholder() && table->lock_type >= TL_WRITE_ALLOW_WRITE) |
|
3685 |
{
|
|
151
by Brian Aker
Ulonglong to uint64_t |
3686 |
uint64_t const flags= table->table->file->ha_table_flags(); |
1
by brian
clean slate |
3687 |
if (prev_ht && prev_ht != table->table->file->ht) |
55
by brian
Update for using real bool types. |
3688 |
multi_engine= true; |
1
by brian
clean slate |
3689 |
prev_ht= table->table->file->ht; |
3690 |
flags_all_set &= flags; |
|
3691 |
flags_some_set |= flags; |
|
3692 |
}
|
|
3693 |
}
|
|
3694 |
||
3695 |
int error= 0; |
|
3696 |
if (flags_all_set == 0) |
|
3697 |
{
|
|
3698 |
my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), |
|
3699 |
"Statement cannot be logged to the binary log in"
|
|
3700 |
" row-based nor statement-based format"); |
|
3701 |
}
|
|
3702 |
else if (thd->variables.binlog_format == BINLOG_FORMAT_STMT && |
|
3703 |
(flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) |
|
3704 |
{
|
|
3705 |
my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), |
|
3706 |
"Statement-based format required for this statement,"
|
|
3707 |
" but not allowed by this combination of engines"); |
|
3708 |
}
|
|
3709 |
else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW || |
|
3710 |
thd->lex->is_stmt_unsafe()) && |
|
3711 |
(flags_all_set & HA_BINLOG_ROW_CAPABLE) == 0) |
|
3712 |
{
|
|
3713 |
my_error((error= ER_BINLOG_LOGGING_IMPOSSIBLE), MYF(0), |
|
3714 |
"Row-based format required for this statement,"
|
|
3715 |
" but not allowed by this combination of engines"); |
|
3716 |
}
|
|
3717 |
||
3718 |
/*
|
|
3719 |
If more than one engine is involved in the statement and at
|
|
3720 |
least one is doing it's own logging (is *self-logging*), the
|
|
3721 |
statement cannot be logged atomically, so we generate an error
|
|
3722 |
rather than allowing the binlog to become corrupt.
|
|
3723 |
*/
|
|
3724 |
if (multi_engine && |
|
3725 |
(flags_some_set & HA_HAS_OWN_BINLOGGING)) |
|
3726 |
{
|
|
3727 |
error= ER_BINLOG_LOGGING_IMPOSSIBLE; |
|
3728 |
my_error(error, MYF(0), |
|
3729 |
"Statement cannot be written atomically since more"
|
|
3730 |
" than one engine involved and at least one engine"
|
|
3731 |
" is self-logging"); |
|
3732 |
}
|
|
3733 |
||
3734 |
if (error) |
|
3735 |
return -1; |
|
3736 |
||
3737 |
/*
|
|
3738 |
We switch to row-based format if we are in mixed mode and one of
|
|
3739 |
the following are true:
|
|
3740 |
||
3741 |
1. If the statement is unsafe
|
|
3742 |
2. If statement format cannot be used
|
|
3743 |
||
3744 |
Observe that point to cannot be decided before the tables
|
|
3745 |
involved in a statement has been checked, i.e., we cannot put
|
|
3746 |
this code in reset_current_stmt_binlog_row_based(), it has to be
|
|
3747 |
here.
|
|
3748 |
*/
|
|
3749 |
if (thd->lex->is_stmt_unsafe() || |
|
3750 |
(flags_all_set & HA_BINLOG_STMT_CAPABLE) == 0) |
|
3751 |
{
|
|
3752 |
thd->set_current_stmt_binlog_row_based_if_mixed(); |
|
3753 |
}
|
|
3754 |
}
|
|
3755 |
||
3756 |
return 0; |
|
3757 |
}
|
|
3758 |
||
3759 |
/*
|
|
3760 |
Lock all tables in list
|
|
3761 |
||
3762 |
SYNOPSIS
|
|
3763 |
lock_tables()
|
|
3764 |
thd Thread handler
|
|
3765 |
tables Tables to lock
|
|
3766 |
count Number of opened tables
|
|
55
by brian
Update for using real bool types. |
3767 |
need_reopen Out parameter which if true indicates that some
|
1
by brian
clean slate |
3768 |
tables were dropped or altered during this call
|
3769 |
and therefore invoker should reopen tables and
|
|
3770 |
try to lock them once again (in this case
|
|
3771 |
lock_tables() will also return error).
|
|
3772 |
||
3773 |
NOTES
|
|
3774 |
You can't call lock_tables twice, as this would break the dead-lock-free
|
|
3775 |
handling thr_lock gives us. You most always get all needed locks at
|
|
3776 |
once.
|
|
3777 |
||
3778 |
If query for which we are calling this function marked as requring
|
|
3779 |
prelocking, this function will do implicit LOCK TABLES and change
|
|
3780 |
thd::prelocked_mode accordingly.
|
|
3781 |
||
3782 |
RETURN VALUES
|
|
3783 |
0 ok
|
|
3784 |
-1 Error
|
|
3785 |
*/
|
|
3786 |
||
3787 |
int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen) |
|
3788 |
{
|
|
3789 |
TABLE_LIST *table; |
|
3790 |
||
3791 |
/*
|
|
3792 |
We can't meet statement requiring prelocking if we already
|
|
3793 |
in prelocked mode.
|
|
3794 |
*/
|
|
55
by brian
Update for using real bool types. |
3795 |
*need_reopen= false; |
1
by brian
clean slate |
3796 |
|
3797 |
if (!tables) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3798 |
return(decide_logging_format(thd, tables)); |
1
by brian
clean slate |
3799 |
|
3800 |
if (!thd->locked_tables) |
|
3801 |
{
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3802 |
assert(thd->lock == 0); // You must lock everything at once |
1
by brian
clean slate |
3803 |
TABLE **start,**ptr; |
3804 |
uint lock_flag= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN; |
|
3805 |
||
3806 |
if (!(ptr=start=(TABLE**) thd->alloc(sizeof(TABLE*)*count))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3807 |
return(-1); |
1
by brian
clean slate |
3808 |
for (table= tables; table; table= table->next_global) |
3809 |
{
|
|
3810 |
if (!table->placeholder()) |
|
3811 |
*(ptr++)= table->table; |
|
3812 |
}
|
|
3813 |
||
3814 |
if (!(thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start), |
|
3815 |
lock_flag, need_reopen))) |
|
3816 |
{
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3817 |
return(-1); |
1
by brian
clean slate |
3818 |
}
|
3819 |
}
|
|
3820 |
else
|
|
3821 |
{
|
|
3822 |
TABLE_LIST *first_not_own= thd->lex->first_not_own_table(); |
|
3823 |
/*
|
|
3824 |
When open_and_lock_tables() is called for a single table out of
|
|
3825 |
a table list, the 'next_global' chain is temporarily broken. We
|
|
3826 |
may not find 'first_not_own' before the end of the "list".
|
|
3827 |
Look for example at those places where open_n_lock_single_table()
|
|
3828 |
is called. That function implements the temporary breaking of
|
|
3829 |
a table list for opening a single table.
|
|
3830 |
*/
|
|
3831 |
for (table= tables; |
|
3832 |
table && table != first_not_own; |
|
3833 |
table= table->next_global) |
|
3834 |
{
|
|
3835 |
if (!table->placeholder() && |
|
3836 |
check_lock_and_start_stmt(thd, table->table, table->lock_type)) |
|
3837 |
{
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3838 |
return(-1); |
1
by brian
clean slate |
3839 |
}
|
3840 |
}
|
|
3841 |
}
|
|
3842 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3843 |
return(decide_logging_format(thd, tables)); |
1
by brian
clean slate |
3844 |
}
|
3845 |
||
3846 |
||
3847 |
/*
|
|
3848 |
Prepare statement for reopening of tables and recalculation of set of
|
|
3849 |
prelocked tables.
|
|
3850 |
||
3851 |
SYNOPSIS
|
|
3852 |
close_tables_for_reopen()
|
|
3853 |
thd in Thread context
|
|
3854 |
tables in/out List of tables which we were trying to open and lock
|
|
3855 |
||
3856 |
*/
|
|
3857 |
||
3858 |
void close_tables_for_reopen(THD *thd, TABLE_LIST **tables) |
|
3859 |
{
|
|
3860 |
/*
|
|
3861 |
If table list consists only from tables from prelocking set, table list
|
|
3862 |
for new attempt should be empty, so we have to update list's root pointer.
|
|
3863 |
*/
|
|
3864 |
if (thd->lex->first_not_own_table() == *tables) |
|
3865 |
*tables= 0; |
|
3866 |
thd->lex->chop_off_not_own_tables(); |
|
3867 |
for (TABLE_LIST *tmp= *tables; tmp; tmp= tmp->next_global) |
|
3868 |
tmp->table= 0; |
|
3869 |
close_thread_tables(thd); |
|
3870 |
}
|
|
3871 |
||
3872 |
||
3873 |
/*
|
|
3874 |
Open a single table without table caching and don't set it in open_list
|
|
3875 |
||
3876 |
SYNPOSIS
|
|
3877 |
open_temporary_table()
|
|
3878 |
thd Thread object
|
|
3879 |
path Path (without .frm)
|
|
3880 |
db database
|
|
3881 |
table_name Table name
|
|
3882 |
link_in_list 1 if table should be linked into thd->temporary_tables
|
|
3883 |
||
3884 |
NOTES:
|
|
3885 |
Used by alter_table to open a temporary table and when creating
|
|
3886 |
a temporary table with CREATE TEMPORARY ...
|
|
3887 |
||
3888 |
RETURN
|
|
3889 |
0 Error
|
|
3890 |
# TABLE object
|
|
3891 |
*/
|
|
3892 |
||
3893 |
TABLE *open_temporary_table(THD *thd, const char *path, const char *db, |
|
3894 |
const char *table_name, bool link_in_list, |
|
3895 |
open_table_mode open_mode) |
|
3896 |
{
|
|
3897 |
TABLE *tmp_table; |
|
3898 |
TABLE_SHARE *share; |
|
3899 |
char cache_key[MAX_DBKEY_LENGTH], *saved_cache_key, *tmp_path; |
|
3900 |
uint key_length; |
|
3901 |
TABLE_LIST table_list; |
|
3902 |
||
3903 |
table_list.db= (char*) db; |
|
3904 |
table_list.table_name= (char*) table_name; |
|
3905 |
/* Create the cache_key for temporary tables */
|
|
3906 |
key_length= create_table_def_key(thd, cache_key, &table_list, 1); |
|
3907 |
||
3908 |
if (!(tmp_table= (TABLE*) my_malloc(sizeof(*tmp_table) + sizeof(*share) + |
|
3909 |
strlen(path)+1 + key_length, |
|
3910 |
MYF(MY_WME)))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3911 |
return(0); /* purecov: inspected */ |
1
by brian
clean slate |
3912 |
|
3913 |
share= (TABLE_SHARE*) (tmp_table+1); |
|
3914 |
tmp_path= (char*) (share+1); |
|
266.1.21
by Monty Taylor
Removed references to strmov and strnmov |
3915 |
saved_cache_key= stpcpy(tmp_path, path)+1; |
1
by brian
clean slate |
3916 |
memcpy(saved_cache_key, cache_key, key_length); |
3917 |
||
3918 |
init_tmp_table_share(thd, share, saved_cache_key, key_length, |
|
3919 |
strend(saved_cache_key)+1, tmp_path); |
|
3920 |
||
3921 |
if (open_table_def(thd, share, 0) || |
|
3922 |
open_table_from_share(thd, share, table_name, |
|
3923 |
(open_mode == OTM_ALTER) ? 0 : |
|
3924 |
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | |
|
3925 |
HA_GET_INDEX), |
|
3926 |
(open_mode == OTM_ALTER) ? |
|
3927 |
(READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD | |
|
3928 |
OPEN_FRM_FILE_ONLY) |
|
3929 |
: (READ_KEYINFO | COMPUTE_TYPES | EXTRA_RECORD), |
|
3930 |
ha_open_options, |
|
3931 |
tmp_table, open_mode)) |
|
3932 |
{
|
|
3933 |
/* No need to lock share->mutex as this is not needed for tmp tables */
|
|
3934 |
free_table_share(share); |
|
3935 |
my_free((char*) tmp_table,MYF(0)); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3936 |
return(0); |
1
by brian
clean slate |
3937 |
}
|
3938 |
||
3939 |
tmp_table->reginfo.lock_type= TL_WRITE; // Simulate locked |
|
3940 |
if (open_mode == OTM_ALTER) |
|
3941 |
{
|
|
3942 |
/*
|
|
3943 |
Temporary table has been created with frm_only
|
|
3944 |
and has not been created in any storage engine
|
|
3945 |
*/
|
|
3946 |
share->tmp_table= TMP_TABLE_FRM_FILE_ONLY; |
|
3947 |
}
|
|
3948 |
else
|
|
3949 |
share->tmp_table= (tmp_table->file->has_transactions() ? |
|
3950 |
TRANSACTIONAL_TMP_TABLE : NON_TRANSACTIONAL_TMP_TABLE); |
|
3951 |
||
3952 |
if (link_in_list) |
|
3953 |
{
|
|
3954 |
/* growing temp list at the head */
|
|
3955 |
tmp_table->next= thd->temporary_tables; |
|
3956 |
if (tmp_table->next) |
|
3957 |
tmp_table->next->prev= tmp_table; |
|
3958 |
thd->temporary_tables= tmp_table; |
|
3959 |
thd->temporary_tables->prev= 0; |
|
3960 |
if (thd->slave_thread) |
|
3961 |
slave_open_temp_tables++; |
|
3962 |
}
|
|
3963 |
tmp_table->pos_in_table_list= 0; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3964 |
return(tmp_table); |
1
by brian
clean slate |
3965 |
}
|
3966 |
||
3967 |
||
3968 |
bool rm_temporary_table(handlerton *base, char *path, bool frm_only) |
|
3969 |
{
|
|
3970 |
bool error=0; |
|
3971 |
handler *file; |
|
3972 |
char *ext; |
|
3973 |
||
266.1.21
by Monty Taylor
Removed references to strmov and strnmov |
3974 |
stpcpy(ext= strend(path), reg_ext); |
1
by brian
clean slate |
3975 |
if (my_delete(path,MYF(0))) |
3976 |
error=1; /* purecov: inspected */ |
|
3977 |
*ext= 0; // remove extension |
|
3978 |
file= get_new_handler((TABLE_SHARE*) 0, current_thd->mem_root, base); |
|
3979 |
if (!frm_only && file && file->ha_delete_table(path)) |
|
3980 |
{
|
|
3981 |
error=1; |
|
3982 |
sql_print_warning("Could not remove temporary table: '%s', error: %d", |
|
3983 |
path, my_errno); |
|
3984 |
}
|
|
3985 |
delete file; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
3986 |
return(error); |
1
by brian
clean slate |
3987 |
}
|
3988 |
||
3989 |
||
3990 |
/*****************************************************************************
|
|
3991 |
* The following find_field_in_XXX procedures implement the core of the
|
|
3992 |
* name resolution functionality. The entry point to resolve a column name in a
|
|
3993 |
* list of tables is 'find_field_in_tables'. It calls 'find_field_in_table_ref'
|
|
3994 |
* for each table reference. In turn, depending on the type of table reference,
|
|
3995 |
* 'find_field_in_table_ref' calls one of the 'find_field_in_XXX' procedures
|
|
3996 |
* below specific for the type of table reference.
|
|
3997 |
******************************************************************************/
|
|
3998 |
||
3999 |
/* Special Field pointers as return values of find_field_in_XXX functions. */
|
|
4000 |
Field *not_found_field= (Field*) 0x1; |
|
4001 |
Field *view_ref_found= (Field*) 0x2; |
|
4002 |
||
4003 |
#define WRONG_GRANT (Field*) -1
|
|
4004 |
||
4005 |
static void update_field_dependencies(THD *thd, Field *field, TABLE *table) |
|
4006 |
{
|
|
4007 |
if (thd->mark_used_columns != MARK_COLUMNS_NONE) |
|
4008 |
{
|
|
4009 |
MY_BITMAP *current_bitmap, *other_bitmap; |
|
4010 |
||
4011 |
/*
|
|
4012 |
We always want to register the used keys, as the column bitmap may have
|
|
4013 |
been set for all fields (for example for view).
|
|
4014 |
*/
|
|
4015 |
||
4016 |
table->covering_keys.intersect(field->part_of_key); |
|
4017 |
table->merge_keys.merge(field->part_of_key); |
|
4018 |
||
4019 |
if (thd->mark_used_columns == MARK_COLUMNS_READ) |
|
4020 |
{
|
|
4021 |
current_bitmap= table->read_set; |
|
4022 |
other_bitmap= table->write_set; |
|
4023 |
}
|
|
4024 |
else
|
|
4025 |
{
|
|
4026 |
current_bitmap= table->write_set; |
|
4027 |
other_bitmap= table->read_set; |
|
4028 |
}
|
|
4029 |
||
4030 |
if (bitmap_fast_test_and_set(current_bitmap, field->field_index)) |
|
4031 |
{
|
|
4032 |
if (thd->mark_used_columns == MARK_COLUMNS_WRITE) |
|
4033 |
thd->dup_field= field; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4034 |
return; |
1
by brian
clean slate |
4035 |
}
|
4036 |
if (table->get_fields_in_item_tree) |
|
4037 |
field->flags|= GET_FIXED_FIELDS_FLAG; |
|
4038 |
table->used_fields++; |
|
4039 |
}
|
|
4040 |
else if (table->get_fields_in_item_tree) |
|
4041 |
field->flags|= GET_FIXED_FIELDS_FLAG; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4042 |
return; |
1
by brian
clean slate |
4043 |
}
|
4044 |
||
4045 |
||
4046 |
/*
|
|
4047 |
Find a field by name in a view that uses merge algorithm.
|
|
4048 |
||
4049 |
SYNOPSIS
|
|
4050 |
find_field_in_view()
|
|
4051 |
thd thread handler
|
|
4052 |
table_list view to search for 'name'
|
|
4053 |
name name of field
|
|
4054 |
length length of name
|
|
4055 |
item_name name of item if it will be created (VIEW)
|
|
4056 |
ref expression substituted in VIEW should be passed
|
|
4057 |
using this reference (return view_ref_found)
|
|
55
by brian
Update for using real bool types. |
4058 |
register_tree_change true if ref is not stack variable and we
|
1
by brian
clean slate |
4059 |
need register changes in item tree
|
4060 |
||
4061 |
RETURN
|
|
4062 |
0 field is not found
|
|
4063 |
view_ref_found found value in VIEW (real result is in *ref)
|
|
4064 |
# pointer to field - only for schema table fields
|
|
4065 |
*/
|
|
4066 |
||
4067 |
static Field * |
|
4068 |
find_field_in_view(THD *thd, TABLE_LIST *table_list, |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
4069 |
const char *name, uint length __attribute__((unused)), |
4070 |
const char *item_name __attribute__((unused)), |
|
77.1.45
by Monty Taylor
Warning fixes. |
4071 |
Item **ref, |
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
4072 |
bool register_tree_change __attribute__((unused))) |
1
by brian
clean slate |
4073 |
{
|
4074 |
Field_iterator_view field_it; |
|
4075 |
field_it.set(table_list); |
|
4076 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4077 |
assert(table_list->schema_table_reformed || |
1
by brian
clean slate |
4078 |
(ref != 0 && (0) != 0)); |
4079 |
for (; !field_it.end_of_fields(); field_it.next()) |
|
4080 |
{
|
|
4081 |
if (!my_strcasecmp(system_charset_info, field_it.name(), name)) |
|
4082 |
{
|
|
4083 |
/*
|
|
4084 |
create_item() may, or may not create a new Item, depending on
|
|
4085 |
the column reference. See create_view_field() for details.
|
|
4086 |
*/
|
|
4087 |
Item *item= field_it.create_item(thd); |
|
4088 |
||
4089 |
if (!item) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4090 |
return(0); |
1
by brian
clean slate |
4091 |
/*
|
4092 |
*ref != NULL means that *ref contains the item that we need to
|
|
4093 |
replace. If the item was aliased by the user, set the alias to
|
|
4094 |
the replacing item.
|
|
4095 |
We need to set alias on both ref itself and on ref real item.
|
|
4096 |
*/
|
|
4097 |
if (*ref && !(*ref)->is_autogenerated_name) |
|
4098 |
{
|
|
4099 |
item->set_name((*ref)->name, (*ref)->name_length, |
|
4100 |
system_charset_info); |
|
4101 |
item->real_item()->set_name((*ref)->name, (*ref)->name_length, |
|
4102 |
system_charset_info); |
|
4103 |
}
|
|
4104 |
if (register_tree_change) |
|
4105 |
thd->change_item_tree(ref, item); |
|
4106 |
else
|
|
4107 |
*ref= item; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4108 |
return((Field*) view_ref_found); |
1
by brian
clean slate |
4109 |
}
|
4110 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4111 |
return(0); |
1
by brian
clean slate |
4112 |
}
|
4113 |
||
4114 |
||
4115 |
/*
|
|
4116 |
Find field by name in a NATURAL/USING join table reference.
|
|
4117 |
||
4118 |
SYNOPSIS
|
|
4119 |
find_field_in_natural_join()
|
|
4120 |
thd [in] thread handler
|
|
4121 |
table_ref [in] table reference to search
|
|
4122 |
name [in] name of field
|
|
4123 |
length [in] length of name
|
|
4124 |
ref [in/out] if 'name' is resolved to a view field, ref is
|
|
4125 |
set to point to the found view field
|
|
55
by brian
Update for using real bool types. |
4126 |
register_tree_change [in] true if ref is not stack variable and we
|
1
by brian
clean slate |
4127 |
need register changes in item tree
|
4128 |
actual_table [out] the original table reference where the field
|
|
4129 |
belongs - differs from 'table_list' only for
|
|
4130 |
NATURAL/USING joins
|
|
4131 |
||
4132 |
DESCRIPTION
|
|
4133 |
Search for a field among the result fields of a NATURAL/USING join.
|
|
4134 |
Notice that this procedure is called only for non-qualified field
|
|
4135 |
names. In the case of qualified fields, we search directly the base
|
|
4136 |
tables of a natural join.
|
|
4137 |
||
4138 |
RETURN
|
|
4139 |
NULL if the field was not found
|
|
4140 |
WRONG_GRANT if no access rights to the found field
|
|
4141 |
# Pointer to the found Field
|
|
4142 |
*/
|
|
4143 |
||
4144 |
static Field * |
|
4145 |
find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
4146 |
uint length __attribute__((unused)), |
77.1.45
by Monty Taylor
Warning fixes. |
4147 |
Item **ref, bool register_tree_change, |
1
by brian
clean slate |
4148 |
TABLE_LIST **actual_table) |
4149 |
{
|
|
4150 |
List_iterator_fast<Natural_join_column> |
|
4151 |
field_it(*(table_ref->join_columns)); |
|
4152 |
Natural_join_column *nj_col, *curr_nj_col; |
|
4153 |
Field *found_field; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4154 |
|
4155 |
assert(table_ref->is_natural_join && table_ref->join_columns); |
|
4156 |
assert(*actual_table == NULL); |
|
1
by brian
clean slate |
4157 |
|
4158 |
for (nj_col= NULL, curr_nj_col= field_it++; curr_nj_col; |
|
4159 |
curr_nj_col= field_it++) |
|
4160 |
{
|
|
4161 |
if (!my_strcasecmp(system_charset_info, curr_nj_col->name(), name)) |
|
4162 |
{
|
|
4163 |
if (nj_col) |
|
4164 |
{
|
|
4165 |
my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4166 |
return(NULL); |
1
by brian
clean slate |
4167 |
}
|
4168 |
nj_col= curr_nj_col; |
|
4169 |
}
|
|
4170 |
}
|
|
4171 |
if (!nj_col) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4172 |
return(NULL); |
1
by brian
clean slate |
4173 |
|
4174 |
if (nj_col->view_field) |
|
4175 |
{
|
|
4176 |
Item *item; |
|
4177 |
/*
|
|
4178 |
create_item() may, or may not create a new Item, depending on the
|
|
4179 |
column reference. See create_view_field() for details.
|
|
4180 |
*/
|
|
4181 |
item= nj_col->create_item(thd); |
|
4182 |
/*
|
|
4183 |
*ref != NULL means that *ref contains the item that we need to
|
|
4184 |
replace. If the item was aliased by the user, set the alias to
|
|
4185 |
the replacing item.
|
|
4186 |
We need to set alias on both ref itself and on ref real item.
|
|
4187 |
*/
|
|
4188 |
if (*ref && !(*ref)->is_autogenerated_name) |
|
4189 |
{
|
|
4190 |
item->set_name((*ref)->name, (*ref)->name_length, |
|
4191 |
system_charset_info); |
|
4192 |
item->real_item()->set_name((*ref)->name, (*ref)->name_length, |
|
4193 |
system_charset_info); |
|
4194 |
}
|
|
4195 |
||
4196 |
if (!item) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4197 |
return(NULL); |
4198 |
assert(nj_col->table_field == NULL); |
|
1
by brian
clean slate |
4199 |
if (nj_col->table_ref->schema_table_reformed) |
4200 |
{
|
|
4201 |
/*
|
|
4202 |
Translation table items are always Item_fields and fixed
|
|
4203 |
already('mysql_schema_table' function). So we can return
|
|
4204 |
->field. It is used only for 'show & where' commands.
|
|
4205 |
*/
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4206 |
return(((Item_field*) (nj_col->view_field->item))->field); |
1
by brian
clean slate |
4207 |
}
|
4208 |
if (register_tree_change) |
|
4209 |
thd->change_item_tree(ref, item); |
|
4210 |
else
|
|
4211 |
*ref= item; |
|
4212 |
found_field= (Field*) view_ref_found; |
|
4213 |
}
|
|
4214 |
else
|
|
4215 |
{
|
|
4216 |
/* This is a base table. */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4217 |
assert(nj_col->view_field == NULL); |
4218 |
assert(nj_col->table_ref->table == nj_col->table_field->table); |
|
1
by brian
clean slate |
4219 |
found_field= nj_col->table_field; |
4220 |
update_field_dependencies(thd, found_field, nj_col->table_ref->table); |
|
4221 |
}
|
|
4222 |
||
4223 |
*actual_table= nj_col->table_ref; |
|
4224 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4225 |
return(found_field); |
1
by brian
clean slate |
4226 |
}
|
4227 |
||
4228 |
||
4229 |
/*
|
|
4230 |
Find field by name in a base table or a view with temp table algorithm.
|
|
4231 |
||
4232 |
SYNOPSIS
|
|
4233 |
find_field_in_table()
|
|
4234 |
thd thread handler
|
|
4235 |
table table where to search for the field
|
|
4236 |
name name of field
|
|
4237 |
length length of name
|
|
4238 |
allow_rowid do allow finding of "_rowid" field?
|
|
4239 |
cached_field_index_ptr cached position in field list (used to speedup
|
|
4240 |
lookup for fields in prepared tables)
|
|
4241 |
||
4242 |
RETURN
|
|
4243 |
0 field is not found
|
|
4244 |
# pointer to field
|
|
4245 |
*/
|
|
4246 |
||
4247 |
Field * |
|
4248 |
find_field_in_table(THD *thd, TABLE *table, const char *name, uint length, |
|
4249 |
bool allow_rowid, uint *cached_field_index_ptr) |
|
4250 |
{
|
|
4251 |
Field **field_ptr, *field; |
|
4252 |
uint cached_field_index= *cached_field_index_ptr; |
|
4253 |
||
4254 |
/* We assume here that table->field < NO_CACHED_FIELD_INDEX = UINT_MAX */
|
|
4255 |
if (cached_field_index < table->s->fields && |
|
4256 |
!my_strcasecmp(system_charset_info, |
|
4257 |
table->field[cached_field_index]->field_name, name)) |
|
4258 |
field_ptr= table->field + cached_field_index; |
|
4259 |
else if (table->s->name_hash.records) |
|
4260 |
{
|
|
4261 |
field_ptr= (Field**) hash_search(&table->s->name_hash, (uchar*) name, |
|
4262 |
length); |
|
4263 |
if (field_ptr) |
|
4264 |
{
|
|
4265 |
/*
|
|
4266 |
field_ptr points to field in TABLE_SHARE. Convert it to the matching
|
|
4267 |
field in table
|
|
4268 |
*/
|
|
4269 |
field_ptr= (table->field + (field_ptr - table->s->field)); |
|
4270 |
}
|
|
4271 |
}
|
|
4272 |
else
|
|
4273 |
{
|
|
4274 |
if (!(field_ptr= table->field)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4275 |
return((Field *)0); |
1
by brian
clean slate |
4276 |
for (; *field_ptr; ++field_ptr) |
4277 |
if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name, name)) |
|
4278 |
break; |
|
4279 |
}
|
|
4280 |
||
4281 |
if (field_ptr && *field_ptr) |
|
4282 |
{
|
|
4283 |
*cached_field_index_ptr= field_ptr - table->field; |
|
4284 |
field= *field_ptr; |
|
4285 |
}
|
|
4286 |
else
|
|
4287 |
{
|
|
4288 |
if (!allow_rowid || |
|
4289 |
my_strcasecmp(system_charset_info, name, "_rowid") || |
|
4290 |
table->s->rowid_field_offset == 0) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4291 |
return((Field*) 0); |
1
by brian
clean slate |
4292 |
field= table->field[table->s->rowid_field_offset-1]; |
4293 |
}
|
|
4294 |
||
4295 |
update_field_dependencies(thd, field, table); |
|
4296 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4297 |
return(field); |
1
by brian
clean slate |
4298 |
}
|
4299 |
||
4300 |
||
4301 |
/*
|
|
4302 |
Find field in a table reference.
|
|
4303 |
||
4304 |
SYNOPSIS
|
|
4305 |
find_field_in_table_ref()
|
|
4306 |
thd [in] thread handler
|
|
4307 |
table_list [in] table reference to search
|
|
4308 |
name [in] name of field
|
|
4309 |
length [in] field length of name
|
|
4310 |
item_name [in] name of item if it will be created (VIEW)
|
|
4311 |
db_name [in] optional database name that qualifies the
|
|
4312 |
table_name [in] optional table name that qualifies the field
|
|
4313 |
ref [in/out] if 'name' is resolved to a view field, ref
|
|
4314 |
is set to point to the found view field
|
|
4315 |
check_privileges [in] check privileges
|
|
4316 |
allow_rowid [in] do allow finding of "_rowid" field?
|
|
4317 |
cached_field_index_ptr [in] cached position in field list (used to
|
|
4318 |
speedup lookup for fields in prepared tables)
|
|
55
by brian
Update for using real bool types. |
4319 |
register_tree_change [in] true if ref is not stack variable and we
|
1
by brian
clean slate |
4320 |
need register changes in item tree
|
4321 |
actual_table [out] the original table reference where the field
|
|
4322 |
belongs - differs from 'table_list' only for
|
|
4323 |
NATURAL_USING joins.
|
|
4324 |
||
4325 |
DESCRIPTION
|
|
4326 |
Find a field in a table reference depending on the type of table
|
|
4327 |
reference. There are three types of table references with respect
|
|
4328 |
to the representation of their result columns:
|
|
4329 |
- an array of Field_translator objects for MERGE views and some
|
|
4330 |
information_schema tables,
|
|
4331 |
- an array of Field objects (and possibly a name hash) for stored
|
|
4332 |
tables,
|
|
4333 |
- a list of Natural_join_column objects for NATURAL/USING joins.
|
|
4334 |
This procedure detects the type of the table reference 'table_list'
|
|
4335 |
and calls the corresponding search routine.
|
|
4336 |
||
4337 |
RETURN
|
|
4338 |
0 field is not found
|
|
4339 |
view_ref_found found value in VIEW (real result is in *ref)
|
|
4340 |
# pointer to field
|
|
4341 |
*/
|
|
4342 |
||
4343 |
Field * |
|
4344 |
find_field_in_table_ref(THD *thd, TABLE_LIST *table_list, |
|
4345 |
const char *name, uint length, |
|
4346 |
const char *item_name, const char *db_name, |
|
4347 |
const char *table_name, Item **ref, |
|
4348 |
bool check_privileges, bool allow_rowid, |
|
4349 |
uint *cached_field_index_ptr, |
|
4350 |
bool register_tree_change, TABLE_LIST **actual_table) |
|
4351 |
{
|
|
4352 |
Field *fld; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4353 |
|
4354 |
assert(table_list->alias); |
|
4355 |
assert(name); |
|
4356 |
assert(item_name); |
|
1
by brian
clean slate |
4357 |
|
4358 |
/*
|
|
4359 |
Check that the table and database that qualify the current field name
|
|
4360 |
are the same as the table reference we are going to search for the field.
|
|
4361 |
||
4362 |
Exclude from the test below nested joins because the columns in a
|
|
4363 |
nested join generally originate from different tables. Nested joins
|
|
4364 |
also have no table name, except when a nested join is a merge view
|
|
4365 |
or an information schema table.
|
|
4366 |
||
4367 |
We include explicitly table references with a 'field_translation' table,
|
|
4368 |
because if there are views over natural joins we don't want to search
|
|
4369 |
inside the view, but we want to search directly in the view columns
|
|
4370 |
which are represented as a 'field_translation'.
|
|
4371 |
||
4372 |
TODO: Ensure that table_name, db_name and tables->db always points to
|
|
4373 |
something !
|
|
4374 |
*/
|
|
4375 |
if (/* Exclude nested joins. */ |
|
4376 |
(!table_list->nested_join || |
|
4377 |
/* Include merge views and information schema tables. */
|
|
4378 |
table_list->field_translation) && |
|
4379 |
/*
|
|
4380 |
Test if the field qualifiers match the table reference we plan
|
|
4381 |
to search.
|
|
4382 |
*/
|
|
4383 |
table_name && table_name[0] && |
|
4384 |
(my_strcasecmp(table_alias_charset, table_list->alias, table_name) || |
|
4385 |
(db_name && db_name[0] && table_list->db && table_list->db[0] && |
|
4386 |
strcmp(db_name, table_list->db)))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4387 |
return(0); |
1
by brian
clean slate |
4388 |
|
4389 |
*actual_table= NULL; |
|
4390 |
||
4391 |
if (table_list->field_translation) |
|
4392 |
{
|
|
4393 |
/* 'table_list' is a view or an information schema table. */
|
|
4394 |
if ((fld= find_field_in_view(thd, table_list, name, length, item_name, ref, |
|
4395 |
register_tree_change))) |
|
4396 |
*actual_table= table_list; |
|
4397 |
}
|
|
4398 |
else if (!table_list->nested_join) |
|
4399 |
{
|
|
4400 |
/* 'table_list' is a stored table. */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4401 |
assert(table_list->table); |
1
by brian
clean slate |
4402 |
if ((fld= find_field_in_table(thd, table_list->table, name, length, |
4403 |
allow_rowid, |
|
4404 |
cached_field_index_ptr))) |
|
4405 |
*actual_table= table_list; |
|
4406 |
}
|
|
4407 |
else
|
|
4408 |
{
|
|
4409 |
/*
|
|
4410 |
'table_list' is a NATURAL/USING join, or an operand of such join that
|
|
4411 |
is a nested join itself.
|
|
4412 |
||
4413 |
If the field name we search for is qualified, then search for the field
|
|
4414 |
in the table references used by NATURAL/USING the join.
|
|
4415 |
*/
|
|
4416 |
if (table_name && table_name[0]) |
|
4417 |
{
|
|
4418 |
List_iterator<TABLE_LIST> it(table_list->nested_join->join_list); |
|
4419 |
TABLE_LIST *table; |
|
4420 |
while ((table= it++)) |
|
4421 |
{
|
|
4422 |
if ((fld= find_field_in_table_ref(thd, table, name, length, item_name, |
|
4423 |
db_name, table_name, ref, |
|
4424 |
check_privileges, allow_rowid, |
|
4425 |
cached_field_index_ptr, |
|
4426 |
register_tree_change, actual_table))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4427 |
return(fld); |
1
by brian
clean slate |
4428 |
}
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4429 |
return(0); |
1
by brian
clean slate |
4430 |
}
|
4431 |
/*
|
|
4432 |
Non-qualified field, search directly in the result columns of the
|
|
4433 |
natural join. The condition of the outer IF is true for the top-most
|
|
4434 |
natural join, thus if the field is not qualified, we will search
|
|
4435 |
directly the top-most NATURAL/USING join.
|
|
4436 |
*/
|
|
4437 |
fld= find_field_in_natural_join(thd, table_list, name, length, ref, |
|
4438 |
register_tree_change, actual_table); |
|
4439 |
}
|
|
4440 |
||
4441 |
if (fld) |
|
4442 |
{
|
|
4443 |
if (thd->mark_used_columns != MARK_COLUMNS_NONE) |
|
4444 |
{
|
|
4445 |
/*
|
|
4446 |
Get rw_set correct for this field so that the handler
|
|
4447 |
knows that this field is involved in the query and gets
|
|
4448 |
retrieved/updated
|
|
4449 |
*/
|
|
4450 |
Field *field_to_set= NULL; |
|
4451 |
if (fld == view_ref_found) |
|
4452 |
{
|
|
4453 |
Item *it= (*ref)->real_item(); |
|
4454 |
if (it->type() == Item::FIELD_ITEM) |
|
4455 |
field_to_set= ((Item_field*)it)->field; |
|
4456 |
else
|
|
4457 |
{
|
|
4458 |
if (thd->mark_used_columns == MARK_COLUMNS_READ) |
|
4459 |
it->walk(&Item::register_field_in_read_map, 1, (uchar *) 0); |
|
4460 |
}
|
|
4461 |
}
|
|
4462 |
else
|
|
4463 |
field_to_set= fld; |
|
4464 |
if (field_to_set) |
|
4465 |
{
|
|
4466 |
TABLE *table= field_to_set->table; |
|
4467 |
if (thd->mark_used_columns == MARK_COLUMNS_READ) |
|
4468 |
bitmap_set_bit(table->read_set, field_to_set->field_index); |
|
4469 |
else
|
|
4470 |
bitmap_set_bit(table->write_set, field_to_set->field_index); |
|
4471 |
}
|
|
4472 |
}
|
|
4473 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4474 |
return(fld); |
1
by brian
clean slate |
4475 |
}
|
4476 |
||
4477 |
||
4478 |
/*
|
|
4479 |
Find field in table, no side effects, only purpose is to check for field
|
|
4480 |
in table object and get reference to the field if found.
|
|
4481 |
||
4482 |
SYNOPSIS
|
|
4483 |
find_field_in_table_sef()
|
|
4484 |
||
4485 |
table table where to find
|
|
4486 |
name Name of field searched for
|
|
4487 |
||
4488 |
RETURN
|
|
4489 |
0 field is not found
|
|
4490 |
# pointer to field
|
|
4491 |
*/
|
|
4492 |
||
4493 |
Field *find_field_in_table_sef(TABLE *table, const char *name) |
|
4494 |
{
|
|
4495 |
Field **field_ptr; |
|
4496 |
if (table->s->name_hash.records) |
|
4497 |
{
|
|
4498 |
field_ptr= (Field**)hash_search(&table->s->name_hash,(uchar*) name, |
|
4499 |
strlen(name)); |
|
4500 |
if (field_ptr) |
|
4501 |
{
|
|
4502 |
/*
|
|
4503 |
field_ptr points to field in TABLE_SHARE. Convert it to the matching
|
|
4504 |
field in table
|
|
4505 |
*/
|
|
4506 |
field_ptr= (table->field + (field_ptr - table->s->field)); |
|
4507 |
}
|
|
4508 |
}
|
|
4509 |
else
|
|
4510 |
{
|
|
4511 |
if (!(field_ptr= table->field)) |
|
4512 |
return (Field *)0; |
|
4513 |
for (; *field_ptr; ++field_ptr) |
|
4514 |
if (!my_strcasecmp(system_charset_info, (*field_ptr)->field_name, name)) |
|
4515 |
break; |
|
4516 |
}
|
|
4517 |
if (field_ptr) |
|
4518 |
return *field_ptr; |
|
4519 |
else
|
|
4520 |
return (Field *)0; |
|
4521 |
}
|
|
4522 |
||
4523 |
||
4524 |
/*
|
|
4525 |
Find field in table list.
|
|
4526 |
||
4527 |
SYNOPSIS
|
|
4528 |
find_field_in_tables()
|
|
4529 |
thd pointer to current thread structure
|
|
4530 |
item field item that should be found
|
|
4531 |
first_table list of tables to be searched for item
|
|
4532 |
last_table end of the list of tables to search for item. If NULL
|
|
4533 |
then search to the end of the list 'first_table'.
|
|
4534 |
ref if 'item' is resolved to a view field, ref is set to
|
|
4535 |
point to the found view field
|
|
4536 |
report_error Degree of error reporting:
|
|
4537 |
- IGNORE_ERRORS then do not report any error
|
|
4538 |
- IGNORE_EXCEPT_NON_UNIQUE report only non-unique
|
|
4539 |
fields, suppress all other errors
|
|
4540 |
- REPORT_EXCEPT_NON_UNIQUE report all other errors
|
|
4541 |
except when non-unique fields were found
|
|
4542 |
- REPORT_ALL_ERRORS
|
|
4543 |
check_privileges need to check privileges
|
|
55
by brian
Update for using real bool types. |
4544 |
register_tree_change true if ref is not a stack variable and we
|
1
by brian
clean slate |
4545 |
to need register changes in item tree
|
4546 |
||
4547 |
RETURN VALUES
|
|
4548 |
0 If error: the found field is not unique, or there are
|
|
4549 |
no sufficient access priviliges for the found field,
|
|
4550 |
or the field is qualified with non-existing table.
|
|
4551 |
not_found_field The function was called with report_error ==
|
|
4552 |
(IGNORE_ERRORS || IGNORE_EXCEPT_NON_UNIQUE) and a
|
|
4553 |
field was not found.
|
|
4554 |
view_ref_found View field is found, item passed through ref parameter
|
|
4555 |
found field If a item was resolved to some field
|
|
4556 |
*/
|
|
4557 |
||
4558 |
Field * |
|
4559 |
find_field_in_tables(THD *thd, Item_ident *item, |
|
4560 |
TABLE_LIST *first_table, TABLE_LIST *last_table, |
|
4561 |
Item **ref, find_item_error_report_type report_error, |
|
4562 |
bool check_privileges, bool register_tree_change) |
|
4563 |
{
|
|
4564 |
Field *found=0; |
|
4565 |
const char *db= item->db_name; |
|
4566 |
const char *table_name= item->table_name; |
|
4567 |
const char *name= item->field_name; |
|
4568 |
uint length=(uint) strlen(name); |
|
4569 |
char name_buff[NAME_LEN+1]; |
|
4570 |
TABLE_LIST *cur_table= first_table; |
|
4571 |
TABLE_LIST *actual_table; |
|
4572 |
bool allow_rowid; |
|
4573 |
||
4574 |
if (!table_name || !table_name[0]) |
|
4575 |
{
|
|
4576 |
table_name= 0; // For easier test |
|
4577 |
db= 0; |
|
4578 |
}
|
|
4579 |
||
4580 |
allow_rowid= table_name || (cur_table && !cur_table->next_local); |
|
4581 |
||
4582 |
if (item->cached_table) |
|
4583 |
{
|
|
4584 |
/*
|
|
4585 |
This shortcut is used by prepared statements. We assume that
|
|
4586 |
TABLE_LIST *first_table is not changed during query execution (which
|
|
4587 |
is true for all queries except RENAME but luckily RENAME doesn't
|
|
4588 |
use fields...) so we can rely on reusing pointer to its member.
|
|
4589 |
With this optimization we also miss case when addition of one more
|
|
4590 |
field makes some prepared query ambiguous and so erroneous, but we
|
|
4591 |
accept this trade off.
|
|
4592 |
*/
|
|
4593 |
TABLE_LIST *table_ref= item->cached_table; |
|
4594 |
/*
|
|
4595 |
The condition (table_ref->view == NULL) ensures that we will call
|
|
4596 |
find_field_in_table even in the case of information schema tables
|
|
4597 |
when table_ref->field_translation != NULL.
|
|
4598 |
*/
|
|
4599 |
if (table_ref->table) |
|
4600 |
found= find_field_in_table(thd, table_ref->table, name, length, |
|
55
by brian
Update for using real bool types. |
4601 |
true, &(item->cached_field_index)); |
1
by brian
clean slate |
4602 |
else
|
4603 |
found= find_field_in_table_ref(thd, table_ref, name, length, item->name, |
|
4604 |
NULL, NULL, ref, check_privileges, |
|
55
by brian
Update for using real bool types. |
4605 |
true, &(item->cached_field_index), |
1
by brian
clean slate |
4606 |
register_tree_change, |
4607 |
&actual_table); |
|
4608 |
if (found) |
|
4609 |
{
|
|
4610 |
if (found == WRONG_GRANT) |
|
4611 |
return (Field*) 0; |
|
4612 |
||
4613 |
/*
|
|
4614 |
Only views fields should be marked as dependent, not an underlying
|
|
4615 |
fields.
|
|
4616 |
*/
|
|
4617 |
if (!table_ref->belong_to_view) |
|
4618 |
{
|
|
4619 |
SELECT_LEX *current_sel= thd->lex->current_select; |
|
4620 |
SELECT_LEX *last_select= table_ref->select_lex; |
|
4621 |
/*
|
|
4622 |
If the field was an outer referencee, mark all selects using this
|
|
4623 |
sub query as dependent on the outer query
|
|
4624 |
*/
|
|
4625 |
if (current_sel != last_select) |
|
4626 |
mark_select_range_as_dependent(thd, last_select, current_sel, |
|
4627 |
found, *ref, item); |
|
4628 |
}
|
|
4629 |
return found; |
|
4630 |
}
|
|
4631 |
}
|
|
4632 |
||
4633 |
if (db && lower_case_table_names) |
|
4634 |
{
|
|
4635 |
/*
|
|
4636 |
convert database to lower case for comparison.
|
|
4637 |
We can't do this in Item_field as this would change the
|
|
4638 |
'name' of the item which may be used in the select list
|
|
4639 |
*/
|
|
4640 |
strmake(name_buff, db, sizeof(name_buff)-1); |
|
4641 |
my_casedn_str(files_charset_info, name_buff); |
|
4642 |
db= name_buff; |
|
4643 |
}
|
|
4644 |
||
4645 |
if (last_table) |
|
4646 |
last_table= last_table->next_name_resolution_table; |
|
4647 |
||
4648 |
for (; cur_table != last_table ; |
|
4649 |
cur_table= cur_table->next_name_resolution_table) |
|
4650 |
{
|
|
4651 |
Field *cur_field= find_field_in_table_ref(thd, cur_table, name, length, |
|
4652 |
item->name, db, table_name, ref, |
|
4653 |
(thd->lex->sql_command == |
|
4654 |
SQLCOM_SHOW_FIELDS) |
|
4655 |
? false : check_privileges, |
|
4656 |
allow_rowid, |
|
4657 |
&(item->cached_field_index), |
|
4658 |
register_tree_change, |
|
4659 |
&actual_table); |
|
4660 |
if (cur_field) |
|
4661 |
{
|
|
4662 |
if (cur_field == WRONG_GRANT) |
|
4663 |
{
|
|
4664 |
if (thd->lex->sql_command != SQLCOM_SHOW_FIELDS) |
|
4665 |
return (Field*) 0; |
|
4666 |
||
4667 |
thd->clear_error(); |
|
4668 |
cur_field= find_field_in_table_ref(thd, cur_table, name, length, |
|
4669 |
item->name, db, table_name, ref, |
|
4670 |
false, |
|
4671 |
allow_rowid, |
|
4672 |
&(item->cached_field_index), |
|
4673 |
register_tree_change, |
|
4674 |
&actual_table); |
|
4675 |
if (cur_field) |
|
4676 |
{
|
|
4677 |
Field *nf=new Field_null(NULL,0,Field::NONE, |
|
4678 |
cur_field->field_name, |
|
4679 |
&my_charset_bin); |
|
4680 |
nf->init(cur_table->table); |
|
4681 |
cur_field= nf; |
|
4682 |
}
|
|
4683 |
}
|
|
4684 |
||
4685 |
/*
|
|
4686 |
Store the original table of the field, which may be different from
|
|
4687 |
cur_table in the case of NATURAL/USING join.
|
|
4688 |
*/
|
|
4689 |
item->cached_table= (!actual_table->cacheable_table || found) ? |
|
4690 |
0 : actual_table; |
|
4691 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
4692 |
assert(thd->where); |
1
by brian
clean slate |
4693 |
/*
|
4694 |
If we found a fully qualified field we return it directly as it can't
|
|
4695 |
have duplicates.
|
|
4696 |
*/
|
|
4697 |
if (db) |
|
4698 |
return cur_field; |
|
4699 |
||
4700 |
if (found) |
|
4701 |
{
|
|
4702 |
if (report_error == REPORT_ALL_ERRORS || |
|
4703 |
report_error == IGNORE_EXCEPT_NON_UNIQUE) |
|
4704 |
my_error(ER_NON_UNIQ_ERROR, MYF(0), |
|
4705 |
table_name ? item->full_name() : name, thd->where); |
|
4706 |
return (Field*) 0; |
|
4707 |
}
|
|
4708 |
found= cur_field; |
|
4709 |
}
|
|
4710 |
}
|
|
4711 |
||
4712 |
if (found) |
|
4713 |
return found; |
|
4714 |
||
4715 |
/*
|
|
4716 |
If the field was qualified and there were no tables to search, issue
|
|
4717 |
an error that an unknown table was given. The situation is detected
|
|
4718 |
as follows: if there were no tables we wouldn't go through the loop
|
|
4719 |
and cur_table wouldn't be updated by the loop increment part, so it
|
|
4720 |
will be equal to the first table.
|
|
4721 |
*/
|
|
4722 |
if (table_name && (cur_table == first_table) && |
|
4723 |
(report_error == REPORT_ALL_ERRORS || |
|
4724 |
report_error == REPORT_EXCEPT_NON_UNIQUE)) |
|
4725 |
{
|
|
4726 |
char buff[NAME_LEN*2+1]; |
|
4727 |
if (db && db[0]) |
|
4728 |
{
|
|
4729 |
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS); |
|
4730 |
table_name=buff; |
|
4731 |
}
|
|
4732 |
my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, thd->where); |
|
4733 |
}
|
|
4734 |
else
|
|
4735 |
{
|
|
4736 |
if (report_error == REPORT_ALL_ERRORS || |
|
4737 |
report_error == REPORT_EXCEPT_NON_UNIQUE) |
|
4738 |
my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), thd->where); |
|
4739 |
else
|
|
4740 |
found= not_found_field; |
|
4741 |
}
|
|
4742 |
return found; |
|
4743 |
}
|
|
4744 |
||
4745 |
||
4746 |
/*
|
|
4747 |
Find Item in list of items (find_field_in_tables analog)
|
|
4748 |
||
4749 |
TODO
|
|
4750 |
is it better return only counter?
|
|
4751 |
||
4752 |
SYNOPSIS
|
|
4753 |
find_item_in_list()
|
|
4754 |
find Item to find
|
|
4755 |
items List of items
|
|
4756 |
counter To return number of found item
|
|
4757 |
report_error
|
|
4758 |
REPORT_ALL_ERRORS report errors, return 0 if error
|
|
4759 |
REPORT_EXCEPT_NOT_FOUND Do not report 'not found' error and
|
|
4760 |
return not_found_item, report other errors,
|
|
4761 |
return 0
|
|
4762 |
IGNORE_ERRORS Do not report errors, return 0 if error
|
|
4763 |
resolution Set to the resolution type if the item is found
|
|
4764 |
(it says whether the item is resolved
|
|
4765 |
against an alias name,
|
|
4766 |
or as a field name without alias,
|
|
4767 |
or as a field hidden by alias,
|
|
4768 |
or ignoring alias)
|
|
4769 |
|
|
4770 |
RETURN VALUES
|
|
4771 |
0 Item is not found or item is not unique,
|
|
4772 |
error message is reported
|
|
4773 |
not_found_item Function was called with
|
|
4774 |
report_error == REPORT_EXCEPT_NOT_FOUND and
|
|
4775 |
item was not found. No error message was reported
|
|
4776 |
found field
|
|
4777 |
*/
|
|
4778 |
||
4779 |
/* Special Item pointer to serve as a return value from find_item_in_list(). */
|
|
4780 |
Item **not_found_item= (Item**) 0x1; |
|
4781 |
||
4782 |
||
4783 |
Item ** |
|
4784 |
find_item_in_list(Item *find, List<Item> &items, uint *counter, |
|
4785 |
find_item_error_report_type report_error, |
|
4786 |
enum_resolution_type *resolution) |
|
4787 |
{
|
|
4788 |
List_iterator<Item> li(items); |
|
4789 |
Item **found=0, **found_unaliased= 0, *item; |
|
4790 |
const char *db_name=0; |
|
4791 |
const char *field_name=0; |
|
4792 |
const char *table_name=0; |
|
4793 |
bool found_unaliased_non_uniq= 0; |
|
4794 |
/*
|
|
4795 |
true if the item that we search for is a valid name reference
|
|
4796 |
(and not an item that happens to have a name).
|
|
4797 |
*/
|
|
4798 |
bool is_ref_by_name= 0; |
|
4799 |
uint unaliased_counter= 0; |
|
4800 |
||
4801 |
*resolution= NOT_RESOLVED; |
|
4802 |
||
4803 |
is_ref_by_name= (find->type() == Item::FIELD_ITEM || |
|
4804 |
find->type() == Item::REF_ITEM); |
|
4805 |
if (is_ref_by_name) |
|
4806 |
{
|
|
4807 |
field_name= ((Item_ident*) find)->field_name; |
|
4808 |
table_name= ((Item_ident*) find)->table_name; |
|
4809 |
db_name= ((Item_ident*) find)->db_name; |
|
4810 |
}
|
|
4811 |
||
4812 |
for (uint i= 0; (item=li++); i++) |
|
4813 |
{
|
|
4814 |
if (field_name && item->real_item()->type() == Item::FIELD_ITEM) |
|
4815 |
{
|
|
4816 |
Item_ident *item_field= (Item_ident*) item; |
|
4817 |
||
4818 |
/*
|
|
4819 |
In case of group_concat() with ORDER BY condition in the QUERY
|
|
4820 |
item_field can be field of temporary table without item name
|
|
4821 |
(if this field created from expression argument of group_concat()),
|
|
4822 |
=> we have to check presence of name before compare
|
|
4823 |
*/
|
|
4824 |
if (!item_field->name) |
|
4825 |
continue; |
|
4826 |
||
4827 |
if (table_name) |
|
4828 |
{
|
|
4829 |
/*
|
|
4830 |
If table name is specified we should find field 'field_name' in
|
|
4831 |
table 'table_name'. According to SQL-standard we should ignore
|
|
4832 |
aliases in this case.
|
|
4833 |
||
4834 |
Since we should NOT prefer fields from the select list over
|
|
4835 |
other fields from the tables participating in this select in
|
|
4836 |
case of ambiguity we have to do extra check outside this function.
|
|
4837 |
||
4838 |
We use strcmp for table names and database names as these may be
|
|
4839 |
case sensitive. In cases where they are not case sensitive, they
|
|
4840 |
are always in lower case.
|
|
4841 |
||
4842 |
item_field->field_name and item_field->table_name can be 0x0 if
|
|
4843 |
item is not fix_field()'ed yet.
|
|
4844 |
*/
|
|
4845 |
if (item_field->field_name && item_field->table_name && |
|
4846 |
!my_strcasecmp(system_charset_info, item_field->field_name, |
|
4847 |
field_name) && |
|
4848 |
!my_strcasecmp(table_alias_charset, item_field->table_name, |
|
4849 |
table_name) && |
|
4850 |
(!db_name || (item_field->db_name && |
|
4851 |
!strcmp(item_field->db_name, db_name)))) |
|
4852 |
{
|
|
4853 |
if (found_unaliased) |
|
4854 |
{
|
|
4855 |
if ((*found_unaliased)->eq(item, 0)) |
|
4856 |
continue; |
|
4857 |
/*
|
|
4858 |
Two matching fields in select list.
|
|
4859 |
We already can bail out because we are searching through
|
|
4860 |
unaliased names only and will have duplicate error anyway.
|
|
4861 |
*/
|
|
4862 |
if (report_error != IGNORE_ERRORS) |
|
4863 |
my_error(ER_NON_UNIQ_ERROR, MYF(0), |
|
4864 |
find->full_name(), current_thd->where); |
|
4865 |
return (Item**) 0; |
|
4866 |
}
|
|
4867 |
found_unaliased= li.ref(); |
|
4868 |
unaliased_counter= i; |
|
4869 |
*resolution= RESOLVED_IGNORING_ALIAS; |
|
4870 |
if (db_name) |
|
4871 |
break; // Perfect match |
|
4872 |
}
|
|
4873 |
}
|
|
4874 |
else
|
|
4875 |
{
|
|
4876 |
int fname_cmp= my_strcasecmp(system_charset_info, |
|
4877 |
item_field->field_name, |
|
4878 |
field_name); |
|
4879 |
if (!my_strcasecmp(system_charset_info, |
|
4880 |
item_field->name,field_name)) |
|
4881 |
{
|
|
4882 |
/*
|
|
4883 |
If table name was not given we should scan through aliases
|
|
4884 |
and non-aliased fields first. We are also checking unaliased
|
|
4885 |
name of the field in then next else-if, to be able to find
|
|
4886 |
instantly field (hidden by alias) if no suitable alias or
|
|
4887 |
non-aliased field was found.
|
|
4888 |
*/
|
|
4889 |
if (found) |
|
4890 |
{
|
|
4891 |
if ((*found)->eq(item, 0)) |
|
4892 |
continue; // Same field twice |
|
4893 |
if (report_error != IGNORE_ERRORS) |
|
4894 |
my_error(ER_NON_UNIQ_ERROR, MYF(0), |
|
4895 |
find->full_name(), current_thd->where); |
|
4896 |
return (Item**) 0; |
|
4897 |
}
|
|
4898 |
found= li.ref(); |
|
4899 |
*counter= i; |
|
4900 |
*resolution= fname_cmp ? RESOLVED_AGAINST_ALIAS: |
|
4901 |
RESOLVED_WITH_NO_ALIAS; |
|
4902 |
}
|
|
4903 |
else if (!fname_cmp) |
|
4904 |
{
|
|
4905 |
/*
|
|
4906 |
We will use non-aliased field or react on such ambiguities only if
|
|
4907 |
we won't be able to find aliased field.
|
|
4908 |
Again if we have ambiguity with field outside of select list
|
|
4909 |
we should prefer fields from select list.
|
|
4910 |
*/
|
|
4911 |
if (found_unaliased) |
|
4912 |
{
|
|
4913 |
if ((*found_unaliased)->eq(item, 0)) |
|
4914 |
continue; // Same field twice |
|
4915 |
found_unaliased_non_uniq= 1; |
|
4916 |
}
|
|
4917 |
found_unaliased= li.ref(); |
|
4918 |
unaliased_counter= i; |
|
4919 |
}
|
|
4920 |
}
|
|
4921 |
}
|
|
4922 |
else if (!table_name) |
|
4923 |
{
|
|
4924 |
if (is_ref_by_name && find->name && item->name && |
|
4925 |
!my_strcasecmp(system_charset_info,item->name,find->name)) |
|
4926 |
{
|
|
4927 |
found= li.ref(); |
|
4928 |
*counter= i; |
|
4929 |
*resolution= RESOLVED_AGAINST_ALIAS; |
|
4930 |
break; |
|
4931 |
}
|
|
4932 |
else if (find->eq(item,0)) |
|
4933 |
{
|
|
4934 |
found= li.ref(); |
|
4935 |
*counter= i; |
|
4936 |
*resolution= RESOLVED_IGNORING_ALIAS; |
|
4937 |
break; |
|
4938 |
}
|
|
4939 |
}
|
|
4940 |
else if (table_name && item->type() == Item::REF_ITEM && |
|
4941 |
((Item_ref *)item)->ref_type() == Item_ref::VIEW_REF) |
|
4942 |
{
|
|
4943 |
/*
|
|
4944 |
TODO:Here we process prefixed view references only. What we should
|
|
4945 |
really do is process all types of Item_refs. But this will currently
|
|
4946 |
lead to a clash with the way references to outer SELECTs (from the
|
|
4947 |
HAVING clause) are handled in e.g. :
|
|
4948 |
SELECT 1 FROM t1 AS t1_o GROUP BY a
|
|
4949 |
HAVING (SELECT t1_o.a FROM t1 AS t1_i GROUP BY t1_i.a LIMIT 1).
|
|
4950 |
Processing all Item_refs here will cause t1_o.a to resolve to itself.
|
|
4951 |
We still need to process the special case of Item_direct_view_ref
|
|
4952 |
because in the context of views they have the same meaning as
|
|
4953 |
Item_field for tables.
|
|
4954 |
*/
|
|
4955 |
Item_ident *item_ref= (Item_ident *) item; |
|
4956 |
if (item_ref->name && item_ref->table_name && |
|
4957 |
!my_strcasecmp(system_charset_info, item_ref->name, field_name) && |
|
4958 |
!my_strcasecmp(table_alias_charset, item_ref->table_name, |
|
4959 |
table_name) && |
|
4960 |
(!db_name || (item_ref->db_name && |
|
4961 |
!strcmp (item_ref->db_name, db_name)))) |
|
4962 |
{
|
|
4963 |
found= li.ref(); |
|
4964 |
*counter= i; |
|
4965 |
*resolution= RESOLVED_IGNORING_ALIAS; |
|
4966 |
break; |
|
4967 |
}
|
|
4968 |
}
|
|
4969 |
}
|
|
4970 |
if (!found) |
|
4971 |
{
|
|
4972 |
if (found_unaliased_non_uniq) |
|
4973 |
{
|
|
4974 |
if (report_error != IGNORE_ERRORS) |
|
4975 |
my_error(ER_NON_UNIQ_ERROR, MYF(0), |
|
4976 |
find->full_name(), current_thd->where); |
|
4977 |
return (Item **) 0; |
|
4978 |
}
|
|
4979 |
if (found_unaliased) |
|
4980 |
{
|
|
4981 |
found= found_unaliased; |
|
4982 |
*counter= unaliased_counter; |
|
4983 |
*resolution= RESOLVED_BEHIND_ALIAS; |
|
4984 |
}
|
|
4985 |
}
|
|
4986 |
if (found) |
|
4987 |
return found; |
|
4988 |
if (report_error != REPORT_EXCEPT_NOT_FOUND) |
|
4989 |
{
|
|
4990 |
if (report_error == REPORT_ALL_ERRORS) |
|
4991 |
my_error(ER_BAD_FIELD_ERROR, MYF(0), |
|
4992 |
find->full_name(), current_thd->where); |
|
4993 |
return (Item **) 0; |
|
4994 |
}
|
|
4995 |
else
|
|
4996 |
return (Item **) not_found_item; |
|
4997 |
}
|
|
4998 |
||
4999 |
||
5000 |
/*
|
|
5001 |
Test if a string is a member of a list of strings.
|
|
5002 |
||
5003 |
SYNOPSIS
|
|
5004 |
test_if_string_in_list()
|
|
5005 |
find the string to look for
|
|
5006 |
str_list a list of strings to be searched
|
|
5007 |
||
5008 |
DESCRIPTION
|
|
5009 |
Sequentially search a list of strings for a string, and test whether
|
|
5010 |
the list contains the same string.
|
|
5011 |
||
5012 |
RETURN
|
|
55
by brian
Update for using real bool types. |
5013 |
true if find is in str_list
|
5014 |
false otherwise
|
|
1
by brian
clean slate |
5015 |
*/
|
5016 |
||
5017 |
static bool |
|
5018 |
test_if_string_in_list(const char *find, List<String> *str_list) |
|
5019 |
{
|
|
5020 |
List_iterator<String> str_list_it(*str_list); |
|
5021 |
String *curr_str; |
|
5022 |
size_t find_length= strlen(find); |
|
5023 |
while ((curr_str= str_list_it++)) |
|
5024 |
{
|
|
5025 |
if (find_length != curr_str->length()) |
|
5026 |
continue; |
|
5027 |
if (!my_strcasecmp(system_charset_info, find, curr_str->ptr())) |
|
55
by brian
Update for using real bool types. |
5028 |
return true; |
1
by brian
clean slate |
5029 |
}
|
55
by brian
Update for using real bool types. |
5030 |
return false; |
1
by brian
clean slate |
5031 |
}
|
5032 |
||
5033 |
||
5034 |
/*
|
|
5035 |
Create a new name resolution context for an item so that it is
|
|
5036 |
being resolved in a specific table reference.
|
|
5037 |
||
5038 |
SYNOPSIS
|
|
5039 |
set_new_item_local_context()
|
|
5040 |
thd pointer to current thread
|
|
5041 |
item item for which new context is created and set
|
|
5042 |
table_ref table ref where an item showld be resolved
|
|
5043 |
||
5044 |
DESCRIPTION
|
|
5045 |
Create a new name resolution context for an item, so that the item
|
|
5046 |
is resolved only the supplied 'table_ref'.
|
|
5047 |
||
5048 |
RETURN
|
|
55
by brian
Update for using real bool types. |
5049 |
false if all OK
|
5050 |
true otherwise
|
|
1
by brian
clean slate |
5051 |
*/
|
5052 |
||
5053 |
static bool |
|
5054 |
set_new_item_local_context(THD *thd, Item_ident *item, TABLE_LIST *table_ref) |
|
5055 |
{
|
|
5056 |
Name_resolution_context *context; |
|
5057 |
if (!(context= new (thd->mem_root) Name_resolution_context)) |
|
55
by brian
Update for using real bool types. |
5058 |
return true; |
1
by brian
clean slate |
5059 |
context->init(); |
5060 |
context->first_name_resolution_table= |
|
5061 |
context->last_name_resolution_table= table_ref; |
|
5062 |
item->context= context; |
|
55
by brian
Update for using real bool types. |
5063 |
return false; |
1
by brian
clean slate |
5064 |
}
|
5065 |
||
5066 |
||
5067 |
/*
|
|
5068 |
Find and mark the common columns of two table references.
|
|
5069 |
||
5070 |
SYNOPSIS
|
|
5071 |
mark_common_columns()
|
|
5072 |
thd [in] current thread
|
|
5073 |
table_ref_1 [in] the first (left) join operand
|
|
5074 |
table_ref_2 [in] the second (right) join operand
|
|
5075 |
using_fields [in] if the join is JOIN...USING - the join columns,
|
|
5076 |
if NATURAL join, then NULL
|
|
5077 |
found_using_fields [out] number of fields from the USING clause that were
|
|
5078 |
found among the common fields
|
|
5079 |
||
5080 |
DESCRIPTION
|
|
5081 |
The procedure finds the common columns of two relations (either
|
|
5082 |
tables or intermediate join results), and adds an equi-join condition
|
|
5083 |
to the ON clause of 'table_ref_2' for each pair of matching columns.
|
|
5084 |
If some of table_ref_XXX represents a base table or view, then we
|
|
5085 |
create new 'Natural_join_column' instances for each column
|
|
5086 |
reference and store them in the 'join_columns' of the table
|
|
5087 |
reference.
|
|
5088 |
||
5089 |
IMPLEMENTATION
|
|
5090 |
The procedure assumes that store_natural_using_join_columns() was
|
|
5091 |
called for the previous level of NATURAL/USING joins.
|
|
5092 |
||
5093 |
RETURN
|
|
55
by brian
Update for using real bool types. |
5094 |
true error when some common column is non-unique, or out of memory
|
5095 |
false OK
|
|
1
by brian
clean slate |
5096 |
*/
|
5097 |
||
5098 |
static bool |
|
5099 |
mark_common_columns(THD *thd, TABLE_LIST *table_ref_1, TABLE_LIST *table_ref_2, |
|
5100 |
List<String> *using_fields, uint *found_using_fields) |
|
5101 |
{
|
|
5102 |
Field_iterator_table_ref it_1, it_2; |
|
5103 |
Natural_join_column *nj_col_1, *nj_col_2; |
|
55
by brian
Update for using real bool types. |
5104 |
bool result= true; |
5105 |
bool first_outer_loop= true; |
|
1
by brian
clean slate |
5106 |
/*
|
5107 |
Leaf table references to which new natural join columns are added
|
|
5108 |
if the leaves are != NULL.
|
|
5109 |
*/
|
|
5110 |
TABLE_LIST *leaf_1= (table_ref_1->nested_join && |
|
5111 |
!table_ref_1->is_natural_join) ? |
|
5112 |
NULL : table_ref_1; |
|
5113 |
TABLE_LIST *leaf_2= (table_ref_2->nested_join && |
|
5114 |
!table_ref_2->is_natural_join) ? |
|
5115 |
NULL : table_ref_2; |
|
5116 |
||
5117 |
*found_using_fields= 0; |
|
5118 |
||
5119 |
for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next()) |
|
5120 |
{
|
|
55
by brian
Update for using real bool types. |
5121 |
bool found= false; |
1
by brian
clean slate |
5122 |
const char *field_name_1; |
5123 |
/* true if field_name_1 is a member of using_fields */
|
|
5124 |
bool is_using_column_1; |
|
5125 |
if (!(nj_col_1= it_1.get_or_create_column_ref(leaf_1))) |
|
5126 |
goto err; |
|
5127 |
field_name_1= nj_col_1->name(); |
|
5128 |
is_using_column_1= using_fields && |
|
5129 |
test_if_string_in_list(field_name_1, using_fields); |
|
5130 |
||
5131 |
/*
|
|
5132 |
Find a field with the same name in table_ref_2.
|
|
5133 |
||
5134 |
Note that for the second loop, it_2.set() will iterate over
|
|
5135 |
table_ref_2->join_columns and not generate any new elements or
|
|
5136 |
lists.
|
|
5137 |
*/
|
|
5138 |
nj_col_2= NULL; |
|
5139 |
for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next()) |
|
5140 |
{
|
|
5141 |
Natural_join_column *cur_nj_col_2; |
|
5142 |
const char *cur_field_name_2; |
|
5143 |
if (!(cur_nj_col_2= it_2.get_or_create_column_ref(leaf_2))) |
|
5144 |
goto err; |
|
5145 |
cur_field_name_2= cur_nj_col_2->name(); |
|
5146 |
||
5147 |
/*
|
|
5148 |
Compare the two columns and check for duplicate common fields.
|
|
5149 |
A common field is duplicate either if it was already found in
|
|
55
by brian
Update for using real bool types. |
5150 |
table_ref_2 (then found == true), or if a field in table_ref_2
|
1
by brian
clean slate |
5151 |
was already matched by some previous field in table_ref_1
|
55
by brian
Update for using real bool types. |
5152 |
(then cur_nj_col_2->is_common == true).
|
1
by brian
clean slate |
5153 |
Note that it is too early to check the columns outside of the
|
5154 |
USING list for ambiguity because they are not actually "referenced"
|
|
5155 |
here. These columns must be checked only on unqualified reference
|
|
5156 |
by name (e.g. in SELECT list).
|
|
5157 |
*/
|
|
5158 |
if (!my_strcasecmp(system_charset_info, field_name_1, cur_field_name_2)) |
|
5159 |
{
|
|
5160 |
if (cur_nj_col_2->is_common || |
|
5161 |
(found && (!using_fields || is_using_column_1))) |
|
5162 |
{
|
|
5163 |
my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, thd->where); |
|
5164 |
goto err; |
|
5165 |
}
|
|
5166 |
nj_col_2= cur_nj_col_2; |
|
55
by brian
Update for using real bool types. |
5167 |
found= true; |
1
by brian
clean slate |
5168 |
}
|
5169 |
}
|
|
5170 |
if (first_outer_loop && leaf_2) |
|
5171 |
{
|
|
5172 |
/*
|
|
5173 |
Make sure that the next inner loop "knows" that all columns
|
|
5174 |
are materialized already.
|
|
5175 |
*/
|
|
55
by brian
Update for using real bool types. |
5176 |
leaf_2->is_join_columns_complete= true; |
5177 |
first_outer_loop= false; |
|
1
by brian
clean slate |
5178 |
}
|
5179 |
if (!found) |
|
5180 |
continue; // No matching field |
|
5181 |
||
5182 |
/*
|
|
5183 |
field_1 and field_2 have the same names. Check if they are in the USING
|
|
5184 |
clause (if present), mark them as common fields, and add a new
|
|
5185 |
equi-join condition to the ON clause.
|
|
5186 |
*/
|
|
5187 |
if (nj_col_2 && (!using_fields ||is_using_column_1)) |
|
5188 |
{
|
|
5189 |
Item *item_1= nj_col_1->create_item(thd); |
|
5190 |
Item *item_2= nj_col_2->create_item(thd); |
|
5191 |
Field *field_1= nj_col_1->field(); |
|
5192 |
Field *field_2= nj_col_2->field(); |
|
5193 |
Item_ident *item_ident_1, *item_ident_2; |
|
5194 |
Item_func_eq *eq_cond; |
|
5195 |
||
5196 |
if (!item_1 || !item_2) |
|
5197 |
goto err; // out of memory |
|
5198 |
||
5199 |
/*
|
|
5200 |
In the case of no_wrap_view_item == 0, the created items must be
|
|
5201 |
of sub-classes of Item_ident.
|
|
5202 |
*/
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5203 |
assert(item_1->type() == Item::FIELD_ITEM || |
1
by brian
clean slate |
5204 |
item_1->type() == Item::REF_ITEM); |
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5205 |
assert(item_2->type() == Item::FIELD_ITEM || |
1
by brian
clean slate |
5206 |
item_2->type() == Item::REF_ITEM); |
5207 |
||
5208 |
/*
|
|
5209 |
We need to cast item_1,2 to Item_ident, because we need to hook name
|
|
5210 |
resolution contexts specific to each item.
|
|
5211 |
*/
|
|
5212 |
item_ident_1= (Item_ident*) item_1; |
|
5213 |
item_ident_2= (Item_ident*) item_2; |
|
5214 |
/*
|
|
5215 |
Create and hook special name resolution contexts to each item in the
|
|
5216 |
new join condition . We need this to both speed-up subsequent name
|
|
5217 |
resolution of these items, and to enable proper name resolution of
|
|
5218 |
the items during the execute phase of PS.
|
|
5219 |
*/
|
|
5220 |
if (set_new_item_local_context(thd, item_ident_1, nj_col_1->table_ref) || |
|
5221 |
set_new_item_local_context(thd, item_ident_2, nj_col_2->table_ref)) |
|
5222 |
goto err; |
|
5223 |
||
5224 |
if (!(eq_cond= new Item_func_eq(item_ident_1, item_ident_2))) |
|
5225 |
goto err; /* Out of memory. */ |
|
5226 |
||
5227 |
/*
|
|
5228 |
Add the new equi-join condition to the ON clause. Notice that
|
|
5229 |
fix_fields() is applied to all ON conditions in setup_conds()
|
|
5230 |
so we don't do it here.
|
|
5231 |
*/
|
|
5232 |
add_join_on((table_ref_1->outer_join & JOIN_TYPE_RIGHT ? |
|
5233 |
table_ref_1 : table_ref_2), |
|
5234 |
eq_cond); |
|
5235 |
||
55
by brian
Update for using real bool types. |
5236 |
nj_col_1->is_common= nj_col_2->is_common= true; |
1
by brian
clean slate |
5237 |
|
5238 |
if (field_1) |
|
5239 |
{
|
|
5240 |
TABLE *table_1= nj_col_1->table_ref->table; |
|
5241 |
/* Mark field_1 used for table cache. */
|
|
5242 |
bitmap_set_bit(table_1->read_set, field_1->field_index); |
|
5243 |
table_1->covering_keys.intersect(field_1->part_of_key); |
|
5244 |
table_1->merge_keys.merge(field_1->part_of_key); |
|
5245 |
}
|
|
5246 |
if (field_2) |
|
5247 |
{
|
|
5248 |
TABLE *table_2= nj_col_2->table_ref->table; |
|
5249 |
/* Mark field_2 used for table cache. */
|
|
5250 |
bitmap_set_bit(table_2->read_set, field_2->field_index); |
|
5251 |
table_2->covering_keys.intersect(field_2->part_of_key); |
|
5252 |
table_2->merge_keys.merge(field_2->part_of_key); |
|
5253 |
}
|
|
5254 |
||
5255 |
if (using_fields != NULL) |
|
5256 |
++(*found_using_fields); |
|
5257 |
}
|
|
5258 |
}
|
|
5259 |
if (leaf_1) |
|
55
by brian
Update for using real bool types. |
5260 |
leaf_1->is_join_columns_complete= true; |
1
by brian
clean slate |
5261 |
|
5262 |
/*
|
|
5263 |
Everything is OK.
|
|
5264 |
Notice that at this point there may be some column names in the USING
|
|
5265 |
clause that are not among the common columns. This is an SQL error and
|
|
5266 |
we check for this error in store_natural_using_join_columns() when
|
|
5267 |
(found_using_fields < length(join_using_fields)).
|
|
5268 |
*/
|
|
55
by brian
Update for using real bool types. |
5269 |
result= false; |
1
by brian
clean slate |
5270 |
|
5271 |
err: |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5272 |
return(result); |
1
by brian
clean slate |
5273 |
}
|
5274 |
||
5275 |
||
5276 |
||
5277 |
/*
|
|
5278 |
Materialize and store the row type of NATURAL/USING join.
|
|
5279 |
||
5280 |
SYNOPSIS
|
|
5281 |
store_natural_using_join_columns()
|
|
5282 |
thd current thread
|
|
5283 |
natural_using_join the table reference of the NATURAL/USING join
|
|
5284 |
table_ref_1 the first (left) operand (of a NATURAL/USING join).
|
|
5285 |
table_ref_2 the second (right) operand (of a NATURAL/USING join).
|
|
5286 |
using_fields if the join is JOIN...USING - the join columns,
|
|
5287 |
if NATURAL join, then NULL
|
|
5288 |
found_using_fields number of fields from the USING clause that were
|
|
5289 |
found among the common fields
|
|
5290 |
||
5291 |
DESCRIPTION
|
|
5292 |
Iterate over the columns of both join operands and sort and store
|
|
5293 |
all columns into the 'join_columns' list of natural_using_join
|
|
5294 |
where the list is formed by three parts:
|
|
5295 |
part1: The coalesced columns of table_ref_1 and table_ref_2,
|
|
5296 |
sorted according to the column order of the first table.
|
|
5297 |
part2: The other columns of the first table, in the order in
|
|
5298 |
which they were defined in CREATE TABLE.
|
|
5299 |
part3: The other columns of the second table, in the order in
|
|
5300 |
which they were defined in CREATE TABLE.
|
|
5301 |
Time complexity - O(N1+N2), where Ni = length(table_ref_i).
|
|
5302 |
||
5303 |
IMPLEMENTATION
|
|
5304 |
The procedure assumes that mark_common_columns() has been called
|
|
5305 |
for the join that is being processed.
|
|
5306 |
||
5307 |
RETURN
|
|
55
by brian
Update for using real bool types. |
5308 |
true error: Some common column is ambiguous
|
5309 |
false OK
|
|
1
by brian
clean slate |
5310 |
*/
|
5311 |
||
5312 |
static bool |
|
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
5313 |
store_natural_using_join_columns(THD *thd __attribute__((unused)), |
77.1.45
by Monty Taylor
Warning fixes. |
5314 |
TABLE_LIST *natural_using_join, |
1
by brian
clean slate |
5315 |
TABLE_LIST *table_ref_1, |
5316 |
TABLE_LIST *table_ref_2, |
|
5317 |
List<String> *using_fields, |
|
5318 |
uint found_using_fields) |
|
5319 |
{
|
|
5320 |
Field_iterator_table_ref it_1, it_2; |
|
5321 |
Natural_join_column *nj_col_1, *nj_col_2; |
|
55
by brian
Update for using real bool types. |
5322 |
bool result= true; |
1
by brian
clean slate |
5323 |
List<Natural_join_column> *non_join_columns; |
5324 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5325 |
assert(!natural_using_join->join_columns); |
1
by brian
clean slate |
5326 |
|
5327 |
if (!(non_join_columns= new List<Natural_join_column>) || |
|
5328 |
!(natural_using_join->join_columns= new List<Natural_join_column>)) |
|
5329 |
goto err; |
|
5330 |
||
5331 |
/* Append the columns of the first join operand. */
|
|
5332 |
for (it_1.set(table_ref_1); !it_1.end_of_fields(); it_1.next()) |
|
5333 |
{
|
|
5334 |
nj_col_1= it_1.get_natural_column_ref(); |
|
5335 |
if (nj_col_1->is_common) |
|
5336 |
{
|
|
5337 |
natural_using_join->join_columns->push_back(nj_col_1); |
|
5338 |
/* Reset the common columns for the next call to mark_common_columns. */
|
|
55
by brian
Update for using real bool types. |
5339 |
nj_col_1->is_common= false; |
1
by brian
clean slate |
5340 |
}
|
5341 |
else
|
|
5342 |
non_join_columns->push_back(nj_col_1); |
|
5343 |
}
|
|
5344 |
||
5345 |
/*
|
|
5346 |
Check that all columns in the USING clause are among the common
|
|
5347 |
columns. If this is not the case, report the first one that was
|
|
5348 |
not found in an error.
|
|
5349 |
*/
|
|
5350 |
if (using_fields && found_using_fields < using_fields->elements) |
|
5351 |
{
|
|
5352 |
String *using_field_name; |
|
5353 |
List_iterator_fast<String> using_fields_it(*using_fields); |
|
5354 |
while ((using_field_name= using_fields_it++)) |
|
5355 |
{
|
|
5356 |
const char *using_field_name_ptr= using_field_name->c_ptr(); |
|
5357 |
List_iterator_fast<Natural_join_column> |
|
5358 |
it(*(natural_using_join->join_columns)); |
|
5359 |
Natural_join_column *common_field; |
|
5360 |
||
5361 |
for (;;) |
|
5362 |
{
|
|
5363 |
/* If reached the end of fields, and none was found, report error. */
|
|
5364 |
if (!(common_field= it++)) |
|
5365 |
{
|
|
5366 |
my_error(ER_BAD_FIELD_ERROR, MYF(0), using_field_name_ptr, |
|
5367 |
current_thd->where); |
|
5368 |
goto err; |
|
5369 |
}
|
|
5370 |
if (!my_strcasecmp(system_charset_info, |
|
5371 |
common_field->name(), using_field_name_ptr)) |
|
5372 |
break; // Found match |
|
5373 |
}
|
|
5374 |
}
|
|
5375 |
}
|
|
5376 |
||
5377 |
/* Append the non-equi-join columns of the second join operand. */
|
|
5378 |
for (it_2.set(table_ref_2); !it_2.end_of_fields(); it_2.next()) |
|
5379 |
{
|
|
5380 |
nj_col_2= it_2.get_natural_column_ref(); |
|
5381 |
if (!nj_col_2->is_common) |
|
5382 |
non_join_columns->push_back(nj_col_2); |
|
5383 |
else
|
|
5384 |
{
|
|
5385 |
/* Reset the common columns for the next call to mark_common_columns. */
|
|
55
by brian
Update for using real bool types. |
5386 |
nj_col_2->is_common= false; |
1
by brian
clean slate |
5387 |
}
|
5388 |
}
|
|
5389 |
||
5390 |
if (non_join_columns->elements > 0) |
|
5391 |
natural_using_join->join_columns->concat(non_join_columns); |
|
55
by brian
Update for using real bool types. |
5392 |
natural_using_join->is_join_columns_complete= true; |
1
by brian
clean slate |
5393 |
|
55
by brian
Update for using real bool types. |
5394 |
result= false; |
1
by brian
clean slate |
5395 |
|
5396 |
err: |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5397 |
return(result); |
1
by brian
clean slate |
5398 |
}
|
5399 |
||
5400 |
||
5401 |
/*
|
|
5402 |
Precompute and store the row types of the top-most NATURAL/USING joins.
|
|
5403 |
||
5404 |
SYNOPSIS
|
|
5405 |
store_top_level_join_columns()
|
|
5406 |
thd current thread
|
|
5407 |
table_ref nested join or table in a FROM clause
|
|
5408 |
left_neighbor neighbor table reference to the left of table_ref at the
|
|
5409 |
same level in the join tree
|
|
5410 |
right_neighbor neighbor table reference to the right of table_ref at the
|
|
5411 |
same level in the join tree
|
|
5412 |
||
5413 |
DESCRIPTION
|
|
5414 |
The procedure performs a post-order traversal of a nested join tree
|
|
5415 |
and materializes the row types of NATURAL/USING joins in a
|
|
5416 |
bottom-up manner until it reaches the TABLE_LIST elements that
|
|
5417 |
represent the top-most NATURAL/USING joins. The procedure should be
|
|
5418 |
applied to each element of SELECT_LEX::top_join_list (i.e. to each
|
|
5419 |
top-level element of the FROM clause).
|
|
5420 |
||
5421 |
IMPLEMENTATION
|
|
5422 |
Notice that the table references in the list nested_join->join_list
|
|
5423 |
are in reverse order, thus when we iterate over it, we are moving
|
|
5424 |
from the right to the left in the FROM clause.
|
|
5425 |
||
5426 |
RETURN
|
|
55
by brian
Update for using real bool types. |
5427 |
true Error
|
5428 |
false OK
|
|
1
by brian
clean slate |
5429 |
*/
|
5430 |
||
5431 |
static bool |
|
5432 |
store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, |
|
5433 |
TABLE_LIST *left_neighbor, |
|
5434 |
TABLE_LIST *right_neighbor) |
|
5435 |
{
|
|
55
by brian
Update for using real bool types. |
5436 |
bool result= true; |
1
by brian
clean slate |
5437 |
|
5438 |
/* Call the procedure recursively for each nested table reference. */
|
|
5439 |
if (table_ref->nested_join) |
|
5440 |
{
|
|
5441 |
List_iterator_fast<TABLE_LIST> nested_it(table_ref->nested_join->join_list); |
|
5442 |
TABLE_LIST *same_level_left_neighbor= nested_it++; |
|
5443 |
TABLE_LIST *same_level_right_neighbor= NULL; |
|
5444 |
/* Left/right-most neighbors, possibly at higher levels in the join tree. */
|
|
5445 |
TABLE_LIST *real_left_neighbor, *real_right_neighbor; |
|
5446 |
||
5447 |
while (same_level_left_neighbor) |
|
5448 |
{
|
|
5449 |
TABLE_LIST *cur_table_ref= same_level_left_neighbor; |
|
5450 |
same_level_left_neighbor= nested_it++; |
|
5451 |
/*
|
|
5452 |
The order of RIGHT JOIN operands is reversed in 'join list' to
|
|
5453 |
transform it into a LEFT JOIN. However, in this procedure we need
|
|
5454 |
the join operands in their lexical order, so below we reverse the
|
|
5455 |
join operands. Notice that this happens only in the first loop,
|
|
5456 |
and not in the second one, as in the second loop
|
|
5457 |
same_level_left_neighbor == NULL.
|
|
5458 |
This is the correct behavior, because the second loop sets
|
|
5459 |
cur_table_ref reference correctly after the join operands are
|
|
5460 |
swapped in the first loop.
|
|
5461 |
*/
|
|
5462 |
if (same_level_left_neighbor && |
|
5463 |
cur_table_ref->outer_join & JOIN_TYPE_RIGHT) |
|
5464 |
{
|
|
5465 |
/* This can happen only for JOIN ... ON. */
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5466 |
assert(table_ref->nested_join->join_list.elements == 2); |
1
by brian
clean slate |
5467 |
swap_variables(TABLE_LIST*, same_level_left_neighbor, cur_table_ref); |
5468 |
}
|
|
5469 |
||
5470 |
/*
|
|
5471 |
Pick the parent's left and right neighbors if there are no immediate
|
|
5472 |
neighbors at the same level.
|
|
5473 |
*/
|
|
5474 |
real_left_neighbor= (same_level_left_neighbor) ? |
|
5475 |
same_level_left_neighbor : left_neighbor; |
|
5476 |
real_right_neighbor= (same_level_right_neighbor) ? |
|
5477 |
same_level_right_neighbor : right_neighbor; |
|
5478 |
||
5479 |
if (cur_table_ref->nested_join && |
|
5480 |
store_top_level_join_columns(thd, cur_table_ref, |
|
5481 |
real_left_neighbor, real_right_neighbor)) |
|
5482 |
goto err; |
|
5483 |
same_level_right_neighbor= cur_table_ref; |
|
5484 |
}
|
|
5485 |
}
|
|
5486 |
||
5487 |
/*
|
|
5488 |
If this is a NATURAL/USING join, materialize its result columns and
|
|
5489 |
convert to a JOIN ... ON.
|
|
5490 |
*/
|
|
5491 |
if (table_ref->is_natural_join) |
|
5492 |
{
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5493 |
assert(table_ref->nested_join && |
1
by brian
clean slate |
5494 |
table_ref->nested_join->join_list.elements == 2); |
5495 |
List_iterator_fast<TABLE_LIST> operand_it(table_ref->nested_join->join_list); |
|
5496 |
/*
|
|
5497 |
Notice that the order of join operands depends on whether table_ref
|
|
5498 |
represents a LEFT or a RIGHT join. In a RIGHT join, the operands are
|
|
5499 |
in inverted order.
|
|
5500 |
*/
|
|
5501 |
TABLE_LIST *table_ref_2= operand_it++; /* Second NATURAL join operand.*/ |
|
5502 |
TABLE_LIST *table_ref_1= operand_it++; /* First NATURAL join operand. */ |
|
5503 |
List<String> *using_fields= table_ref->join_using_fields; |
|
5504 |
uint found_using_fields; |
|
5505 |
||
5506 |
/*
|
|
5507 |
The two join operands were interchanged in the parser, change the order
|
|
5508 |
back for 'mark_common_columns'.
|
|
5509 |
*/
|
|
5510 |
if (table_ref_2->outer_join & JOIN_TYPE_RIGHT) |
|
5511 |
swap_variables(TABLE_LIST*, table_ref_1, table_ref_2); |
|
5512 |
if (mark_common_columns(thd, table_ref_1, table_ref_2, |
|
5513 |
using_fields, &found_using_fields)) |
|
5514 |
goto err; |
|
5515 |
||
5516 |
/*
|
|
5517 |
Swap the join operands back, so that we pick the columns of the second
|
|
5518 |
one as the coalesced columns. In this way the coalesced columns are the
|
|
5519 |
same as of an equivalent LEFT JOIN.
|
|
5520 |
*/
|
|
5521 |
if (table_ref_1->outer_join & JOIN_TYPE_RIGHT) |
|
5522 |
swap_variables(TABLE_LIST*, table_ref_1, table_ref_2); |
|
5523 |
if (store_natural_using_join_columns(thd, table_ref, table_ref_1, |
|
5524 |
table_ref_2, using_fields, |
|
5525 |
found_using_fields)) |
|
5526 |
goto err; |
|
5527 |
||
5528 |
/*
|
|
5529 |
Change NATURAL JOIN to JOIN ... ON. We do this for both operands
|
|
5530 |
because either one of them or the other is the one with the
|
|
5531 |
natural join flag because RIGHT joins are transformed into LEFT,
|
|
5532 |
and the two tables may be reordered.
|
|
5533 |
*/
|
|
5534 |
table_ref_1->natural_join= table_ref_2->natural_join= NULL; |
|
5535 |
||
55
by brian
Update for using real bool types. |
5536 |
/* Add a true condition to outer joins that have no common columns. */
|
1
by brian
clean slate |
5537 |
if (table_ref_2->outer_join && |
5538 |
!table_ref_1->on_expr && !table_ref_2->on_expr) |
|
152
by Brian Aker
longlong replacement |
5539 |
table_ref_2->on_expr= new Item_int((int64_t) 1,1); /* Always true. */ |
1
by brian
clean slate |
5540 |
|
5541 |
/* Change this table reference to become a leaf for name resolution. */
|
|
5542 |
if (left_neighbor) |
|
5543 |
{
|
|
5544 |
TABLE_LIST *last_leaf_on_the_left; |
|
5545 |
last_leaf_on_the_left= left_neighbor->last_leaf_for_name_resolution(); |
|
5546 |
last_leaf_on_the_left->next_name_resolution_table= table_ref; |
|
5547 |
}
|
|
5548 |
if (right_neighbor) |
|
5549 |
{
|
|
5550 |
TABLE_LIST *first_leaf_on_the_right; |
|
5551 |
first_leaf_on_the_right= right_neighbor->first_leaf_for_name_resolution(); |
|
5552 |
table_ref->next_name_resolution_table= first_leaf_on_the_right; |
|
5553 |
}
|
|
5554 |
else
|
|
5555 |
table_ref->next_name_resolution_table= NULL; |
|
5556 |
}
|
|
55
by brian
Update for using real bool types. |
5557 |
result= false; /* All is OK. */ |
1
by brian
clean slate |
5558 |
|
5559 |
err: |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5560 |
return(result); |
1
by brian
clean slate |
5561 |
}
|
5562 |
||
5563 |
||
5564 |
/*
|
|
5565 |
Compute and store the row types of the top-most NATURAL/USING joins
|
|
5566 |
in a FROM clause.
|
|
5567 |
||
5568 |
SYNOPSIS
|
|
5569 |
setup_natural_join_row_types()
|
|
5570 |
thd current thread
|
|
5571 |
from_clause list of top-level table references in a FROM clause
|
|
5572 |
||
5573 |
DESCRIPTION
|
|
5574 |
Apply the procedure 'store_top_level_join_columns' to each of the
|
|
5575 |
top-level table referencs of the FROM clause. Adjust the list of tables
|
|
5576 |
for name resolution - context->first_name_resolution_table to the
|
|
5577 |
top-most, lef-most NATURAL/USING join.
|
|
5578 |
||
5579 |
IMPLEMENTATION
|
|
5580 |
Notice that the table references in 'from_clause' are in reverse
|
|
5581 |
order, thus when we iterate over it, we are moving from the right
|
|
5582 |
to the left in the FROM clause.
|
|
5583 |
||
5584 |
RETURN
|
|
55
by brian
Update for using real bool types. |
5585 |
true Error
|
5586 |
false OK
|
|
1
by brian
clean slate |
5587 |
*/
|
5588 |
static bool setup_natural_join_row_types(THD *thd, |
|
5589 |
List<TABLE_LIST> *from_clause, |
|
5590 |
Name_resolution_context *context) |
|
5591 |
{
|
|
5592 |
thd->where= "from clause"; |
|
5593 |
if (from_clause->elements == 0) |
|
55
by brian
Update for using real bool types. |
5594 |
return false; /* We come here in the case of UNIONs. */ |
1
by brian
clean slate |
5595 |
|
5596 |
List_iterator_fast<TABLE_LIST> table_ref_it(*from_clause); |
|
5597 |
TABLE_LIST *table_ref; /* Current table reference. */ |
|
5598 |
/* Table reference to the left of the current. */
|
|
5599 |
TABLE_LIST *left_neighbor; |
|
5600 |
/* Table reference to the right of the current. */
|
|
5601 |
TABLE_LIST *right_neighbor= NULL; |
|
5602 |
||
5603 |
/* Note that tables in the list are in reversed order */
|
|
5604 |
for (left_neighbor= table_ref_it++; left_neighbor ; ) |
|
5605 |
{
|
|
5606 |
table_ref= left_neighbor; |
|
5607 |
left_neighbor= table_ref_it++; |
|
5608 |
/* For stored procedures do not redo work if already done. */
|
|
5609 |
if (context->select_lex->first_execution) |
|
5610 |
{
|
|
5611 |
if (store_top_level_join_columns(thd, table_ref, |
|
5612 |
left_neighbor, right_neighbor)) |
|
55
by brian
Update for using real bool types. |
5613 |
return true; |
1
by brian
clean slate |
5614 |
if (left_neighbor) |
5615 |
{
|
|
5616 |
TABLE_LIST *first_leaf_on_the_right; |
|
5617 |
first_leaf_on_the_right= table_ref->first_leaf_for_name_resolution(); |
|
5618 |
left_neighbor->next_name_resolution_table= first_leaf_on_the_right; |
|
5619 |
}
|
|
5620 |
}
|
|
5621 |
right_neighbor= table_ref; |
|
5622 |
}
|
|
5623 |
||
5624 |
/*
|
|
5625 |
Store the top-most, left-most NATURAL/USING join, so that we start
|
|
5626 |
the search from that one instead of context->table_list. At this point
|
|
5627 |
right_neighbor points to the left-most top-level table reference in the
|
|
5628 |
FROM clause.
|
|
5629 |
*/
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5630 |
assert(right_neighbor); |
1
by brian
clean slate |
5631 |
context->first_name_resolution_table= |
5632 |
right_neighbor->first_leaf_for_name_resolution(); |
|
5633 |
||
55
by brian
Update for using real bool types. |
5634 |
return false; |
1
by brian
clean slate |
5635 |
}
|
5636 |
||
5637 |
||
5638 |
/****************************************************************************
|
|
5639 |
** Expand all '*' in given fields
|
|
5640 |
****************************************************************************/
|
|
5641 |
||
77.1.45
by Monty Taylor
Warning fixes. |
5642 |
int setup_wild(THD *thd, |
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
5643 |
TABLE_LIST *tables __attribute__((unused)), |
77.1.45
by Monty Taylor
Warning fixes. |
5644 |
List<Item> &fields, |
5645 |
List<Item> *sum_func_list, |
|
5646 |
uint wild_num) |
|
1
by brian
clean slate |
5647 |
{
|
5648 |
if (!wild_num) |
|
5649 |
return(0); |
|
5650 |
||
5651 |
Item *item; |
|
5652 |
List_iterator<Item> it(fields); |
|
5653 |
||
5654 |
thd->lex->current_select->cur_pos_in_select_list= 0; |
|
5655 |
while (wild_num && (item= it++)) |
|
5656 |
{
|
|
5657 |
if (item->type() == Item::FIELD_ITEM && |
|
5658 |
((Item_field*) item)->field_name && |
|
5659 |
((Item_field*) item)->field_name[0] == '*' && |
|
5660 |
!((Item_field*) item)->field) |
|
5661 |
{
|
|
5662 |
uint elem= fields.elements; |
|
5663 |
bool any_privileges= ((Item_field *) item)->any_privileges; |
|
5664 |
Item_subselect *subsel= thd->lex->current_select->master_unit()->item; |
|
5665 |
if (subsel && |
|
5666 |
subsel->substype() == Item_subselect::EXISTS_SUBS) |
|
5667 |
{
|
|
5668 |
/*
|
|
5669 |
It is EXISTS(SELECT * ...) and we can replace * by any constant.
|
|
5670 |
||
5671 |
Item_int do not need fix_fields() because it is basic constant.
|
|
5672 |
*/
|
|
152
by Brian Aker
longlong replacement |
5673 |
it.replace(new Item_int("Not_used", (int64_t) 1, |
1
by brian
clean slate |
5674 |
MY_INT64_NUM_DECIMAL_DIGITS)); |
5675 |
}
|
|
5676 |
else if (insert_fields(thd, ((Item_field*) item)->context, |
|
5677 |
((Item_field*) item)->db_name, |
|
5678 |
((Item_field*) item)->table_name, &it, |
|
5679 |
any_privileges)) |
|
5680 |
{
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5681 |
return(-1); |
1
by brian
clean slate |
5682 |
}
|
5683 |
if (sum_func_list) |
|
5684 |
{
|
|
5685 |
/*
|
|
5686 |
sum_func_list is a list that has the fields list as a tail.
|
|
5687 |
Because of this we have to update the element count also for this
|
|
5688 |
list after expanding the '*' entry.
|
|
5689 |
*/
|
|
5690 |
sum_func_list->elements+= fields.elements - elem; |
|
5691 |
}
|
|
5692 |
wild_num--; |
|
5693 |
}
|
|
5694 |
else
|
|
5695 |
thd->lex->current_select->cur_pos_in_select_list++; |
|
5696 |
}
|
|
5697 |
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5698 |
return(0); |
1
by brian
clean slate |
5699 |
}
|
5700 |
||
5701 |
/****************************************************************************
|
|
5702 |
** Check that all given fields exists and fill struct with current data
|
|
5703 |
****************************************************************************/
|
|
5704 |
||
5705 |
bool setup_fields(THD *thd, Item **ref_pointer_array, |
|
5706 |
List<Item> &fields, enum_mark_columns mark_used_columns, |
|
5707 |
List<Item> *sum_func_list, bool allow_sum_func) |
|
5708 |
{
|
|
5709 |
register Item *item; |
|
5710 |
enum_mark_columns save_mark_used_columns= thd->mark_used_columns; |
|
5711 |
nesting_map save_allow_sum_func= thd->lex->allow_sum_func; |
|
5712 |
List_iterator<Item> it(fields); |
|
5713 |
bool save_is_item_list_lookup; |
|
5714 |
||
5715 |
thd->mark_used_columns= mark_used_columns; |
|
5716 |
if (allow_sum_func) |
|
5717 |
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; |
|
5718 |
thd->where= THD::DEFAULT_WHERE; |
|
5719 |
save_is_item_list_lookup= thd->lex->current_select->is_item_list_lookup; |
|
5720 |
thd->lex->current_select->is_item_list_lookup= 0; |
|
5721 |
||
5722 |
/*
|
|
5723 |
To prevent fail on forward lookup we fill it with zerows,
|
|
5724 |
then if we got pointer on zero after find_item_in_list we will know
|
|
5725 |
that it is forward lookup.
|
|
5726 |
||
5727 |
There is other way to solve problem: fill array with pointers to list,
|
|
5728 |
but it will be slower.
|
|
5729 |
||
5730 |
TODO: remove it when (if) we made one list for allfields and
|
|
5731 |
ref_pointer_array
|
|
5732 |
*/
|
|
5733 |
if (ref_pointer_array) |
|
212.6.1
by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file. |
5734 |
memset(ref_pointer_array, 0, sizeof(Item *) * fields.elements); |
1
by brian
clean slate |
5735 |
|
5736 |
Item **ref= ref_pointer_array; |
|
5737 |
thd->lex->current_select->cur_pos_in_select_list= 0; |
|
5738 |
while ((item= it++)) |
|
5739 |
{
|
|
5740 |
if ((!item->fixed && item->fix_fields(thd, it.ref())) || (item= *(it.ref()))->check_cols(1)) |
|
5741 |
{
|
|
5742 |
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; |
|
5743 |
thd->lex->allow_sum_func= save_allow_sum_func; |
|
5744 |
thd->mark_used_columns= save_mark_used_columns; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5745 |
return(true); /* purecov: inspected */ |
1
by brian
clean slate |
5746 |
}
|
5747 |
if (ref) |
|
5748 |
*(ref++)= item; |
|
5749 |
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && |
|
5750 |
sum_func_list) |
|
5751 |
item->split_sum_func(thd, ref_pointer_array, *sum_func_list); |
|
5752 |
thd->used_tables|= item->used_tables(); |
|
5753 |
thd->lex->current_select->cur_pos_in_select_list++; |
|
5754 |
}
|
|
5755 |
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; |
|
5756 |
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS; |
|
5757 |
||
5758 |
thd->lex->allow_sum_func= save_allow_sum_func; |
|
5759 |
thd->mark_used_columns= save_mark_used_columns; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5760 |
return(test(thd->is_error())); |
1
by brian
clean slate |
5761 |
}
|
5762 |
||
5763 |
||
5764 |
/*
|
|
5765 |
make list of leaves of join table tree
|
|
5766 |
||
5767 |
SYNOPSIS
|
|
5768 |
make_leaves_list()
|
|
5769 |
list pointer to pointer on list first element
|
|
5770 |
tables table list
|
|
5771 |
||
5772 |
RETURN pointer on pointer to next_leaf of last element
|
|
5773 |
*/
|
|
5774 |
||
5775 |
TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables) |
|
5776 |
{
|
|
5777 |
for (TABLE_LIST *table= tables; table; table= table->next_local) |
|
5778 |
{
|
|
5779 |
{
|
|
5780 |
*list= table; |
|
5781 |
list= &table->next_leaf; |
|
5782 |
}
|
|
5783 |
}
|
|
5784 |
return list; |
|
5785 |
}
|
|
5786 |
||
5787 |
/*
|
|
5788 |
prepare tables
|
|
5789 |
||
5790 |
SYNOPSIS
|
|
5791 |
setup_tables()
|
|
5792 |
thd Thread handler
|
|
5793 |
context name resolution contest to setup table list there
|
|
5794 |
from_clause Top-level list of table references in the FROM clause
|
|
5795 |
tables Table list (select_lex->table_list)
|
|
5796 |
leaves List of join table leaves list (select_lex->leaf_tables)
|
|
5797 |
refresh It is onle refresh for subquery
|
|
5798 |
select_insert It is SELECT ... INSERT command
|
|
5799 |
||
5800 |
NOTE
|
|
5801 |
Check also that the 'used keys' and 'ignored keys' exists and set up the
|
|
5802 |
table structure accordingly.
|
|
5803 |
Create a list of leaf tables. For queries with NATURAL/USING JOINs,
|
|
5804 |
compute the row types of the top most natural/using join table references
|
|
5805 |
and link these into a list of table references for name resolution.
|
|
5806 |
||
5807 |
This has to be called for all tables that are used by items, as otherwise
|
|
5808 |
table->map is not set and all Item_field will be regarded as const items.
|
|
5809 |
||
5810 |
RETURN
|
|
55
by brian
Update for using real bool types. |
5811 |
false ok; In this case *map will includes the chosen index
|
5812 |
true error
|
|
1
by brian
clean slate |
5813 |
*/
|
5814 |
||
5815 |
bool setup_tables(THD *thd, Name_resolution_context *context, |
|
5816 |
List<TABLE_LIST> *from_clause, TABLE_LIST *tables, |
|
5817 |
TABLE_LIST **leaves, bool select_insert) |
|
5818 |
{
|
|
5819 |
uint tablenr= 0; |
|
5820 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5821 |
assert ((select_insert && !tables->next_name_resolution_table) || !tables || |
1
by brian
clean slate |
5822 |
(context->table_list && context->first_name_resolution_table)); |
5823 |
/*
|
|
5824 |
this is used for INSERT ... SELECT.
|
|
5825 |
For select we setup tables except first (and its underlying tables)
|
|
5826 |
*/
|
|
5827 |
TABLE_LIST *first_select_table= (select_insert ? |
|
5828 |
tables->next_local: |
|
5829 |
0); |
|
5830 |
if (!(*leaves)) |
|
5831 |
make_leaves_list(leaves, tables); |
|
5832 |
||
5833 |
TABLE_LIST *table_list; |
|
5834 |
for (table_list= *leaves; |
|
5835 |
table_list; |
|
5836 |
table_list= table_list->next_leaf, tablenr++) |
|
5837 |
{
|
|
5838 |
TABLE *table= table_list->table; |
|
5839 |
table->pos_in_table_list= table_list; |
|
5840 |
if (first_select_table && |
|
5841 |
table_list->top_table() == first_select_table) |
|
5842 |
{
|
|
5843 |
/* new counting for SELECT of INSERT ... SELECT command */
|
|
5844 |
first_select_table= 0; |
|
5845 |
tablenr= 0; |
|
5846 |
}
|
|
5847 |
setup_table_map(table, table_list, tablenr); |
|
5848 |
if (table_list->process_index_hints(table)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5849 |
return(1); |
1
by brian
clean slate |
5850 |
}
|
5851 |
if (tablenr > MAX_TABLES) |
|
5852 |
{
|
|
5853 |
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5854 |
return(1); |
1
by brian
clean slate |
5855 |
}
|
5856 |
||
5857 |
/* Precompute and store the row types of NATURAL/USING joins. */
|
|
5858 |
if (setup_natural_join_row_types(thd, from_clause, context)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5859 |
return(1); |
1
by brian
clean slate |
5860 |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
5861 |
return(0); |
1
by brian
clean slate |
5862 |
}
|
5863 |
||
5864 |
||
5865 |
/*
|
|
5866 |
prepare tables and check access for the view tables
|
|
5867 |
||
5868 |
SYNOPSIS
|
|
5869 |
setup_tables_and_check_view_access()
|
|
5870 |
thd Thread handler
|
|
5871 |
context name resolution contest to setup table list there
|
|
5872 |
from_clause Top-level list of table references in the FROM clause
|
|
5873 |
tables Table list (select_lex->table_list)
|
|
5874 |
conds Condition of current SELECT (can be changed by VIEW)
|
|
5875 |
leaves List of join table leaves list (select_lex->leaf_tables)
|
|
5876 |
refresh It is onle refresh for subquery
|
|
5877 |
select_insert It is SELECT ... INSERT command
|
|
5878 |
want_access what access is needed
|
|
5879 |
||
5880 |
NOTE
|
|
5881 |
a wrapper for check_tables that will also check the resulting
|
|
5882 |
table leaves list for access to all the tables that belong to a view
|
|
5883 |
||
5884 |
RETURN
|
|
55
by brian
Update for using real bool types. |
5885 |
false ok; In this case *map will include the chosen index
|
5886 |
true error
|
|
1
by brian
clean slate |
5887 |
*/
|
5888 |
bool setup_tables_and_check_access(THD *thd, |
|
5889 |
Name_resolution_context *context, |
|
5890 |
List<TABLE_LIST> *from_clause, |
|
5891 |
TABLE_LIST *tables, |
|
5892 |
TABLE_LIST **leaves, |
|
5893 |
bool select_insert) |
|
5894 |
{
|
|
5895 |
TABLE_LIST *leaves_tmp= NULL; |
|
5896 |
bool first_table= true; |
|
5897 |
||
5898 |
if (setup_tables(thd, context, from_clause, tables, |
|
5899 |
&leaves_tmp, select_insert)) |
|
55
by brian
Update for using real bool types. |
5900 |
return true; |
1
by brian
clean slate |
5901 |
|
5902 |
if (leaves) |
|
5903 |
*leaves= leaves_tmp; |
|
5904 |
||
5905 |
for (; leaves_tmp; leaves_tmp= leaves_tmp->next_leaf) |
|
5906 |
{
|
|
5907 |
if (leaves_tmp->belong_to_view) |
|
5908 |
{
|
|
55
by brian
Update for using real bool types. |
5909 |
return true; |
1
by brian
clean slate |
5910 |
}
|
5911 |
first_table= 0; |
|
5912 |
}
|
|
55
by brian
Update for using real bool types. |
5913 |
return false; |
1
by brian
clean slate |
5914 |
}
|
5915 |
||
5916 |
||
5917 |
/*
|
|
5918 |
Create a key_map from a list of index names
|
|
5919 |
||
5920 |
SYNOPSIS
|
|
5921 |
get_key_map_from_key_list()
|
|
5922 |
map key_map to fill in
|
|
5923 |
table Table
|
|
5924 |
index_list List of index names
|
|
5925 |
||
5926 |
RETURN
|
|
5927 |
0 ok; In this case *map will includes the choosed index
|
|
5928 |
1 error
|
|
5929 |
*/
|
|
5930 |
||
5931 |
bool get_key_map_from_key_list(key_map *map, TABLE *table, |
|
5932 |
List<String> *index_list) |
|
5933 |
{
|
|
5934 |
List_iterator_fast<String> it(*index_list); |
|
5935 |
String *name; |
|
5936 |
uint pos; |
|
5937 |
||
5938 |
map->clear_all(); |
|
5939 |
while ((name=it++)) |
|
5940 |
{
|
|
5941 |
if (table->s->keynames.type_names == 0 || |
|
5942 |
(pos= find_type(&table->s->keynames, name->ptr(), |
|
5943 |
name->length(), 1)) <= |
|
5944 |
0) |
|
5945 |
{
|
|
5946 |
my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), name->c_ptr(), |
|
5947 |
table->pos_in_table_list->alias); |
|
5948 |
map->set_all(); |
|
5949 |
return 1; |
|
5950 |
}
|
|
5951 |
map->set_bit(pos-1); |
|
5952 |
}
|
|
5953 |
return 0; |
|
5954 |
}
|
|
5955 |
||
5956 |
||
5957 |
/*
|
|
5958 |
Drops in all fields instead of current '*' field
|
|
5959 |
||
5960 |
SYNOPSIS
|
|
5961 |
insert_fields()
|
|
5962 |
thd Thread handler
|
|
5963 |
context Context for name resolution
|
|
5964 |
db_name Database name in case of 'database_name.table_name.*'
|
|
5965 |
table_name Table name in case of 'table_name.*'
|
|
5966 |
it Pointer to '*'
|
|
5967 |
any_privileges 0 If we should ensure that we have SELECT privileges
|
|
5968 |
for all columns
|
|
5969 |
1 If any privilege is ok
|
|
5970 |
RETURN
|
|
5971 |
0 ok 'it' is updated to point at last inserted
|
|
5972 |
1 error. Error message is generated but not sent to client
|
|
5973 |
*/
|
|
5974 |
||
5975 |
bool
|
|
5976 |
insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, |
|
77.1.45
by Monty Taylor
Warning fixes. |
5977 |
const char *table_name, List_iterator<Item> *it, |
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
5978 |
bool any_privileges __attribute__((unused))) |
1
by brian
clean slate |
5979 |
{
|
5980 |
Field_iterator_table_ref field_iterator; |
|
5981 |
bool found; |
|
5982 |
char name_buff[NAME_LEN+1]; |
|
5983 |
||
5984 |
if (db_name && lower_case_table_names) |
|
5985 |
{
|
|
5986 |
/*
|
|
5987 |
convert database to lower case for comparison
|
|
5988 |
We can't do this in Item_field as this would change the
|
|
5989 |
'name' of the item which may be used in the select list
|
|
5990 |
*/
|
|
5991 |
strmake(name_buff, db_name, sizeof(name_buff)-1); |
|
5992 |
my_casedn_str(files_charset_info, name_buff); |
|
5993 |
db_name= name_buff; |
|
5994 |
}
|
|
5995 |
||
55
by brian
Update for using real bool types. |
5996 |
found= false; |
1
by brian
clean slate |
5997 |
|
5998 |
/*
|
|
5999 |
If table names are qualified, then loop over all tables used in the query,
|
|
6000 |
else treat natural joins as leaves and do not iterate over their underlying
|
|
6001 |
tables.
|
|
6002 |
*/
|
|
6003 |
for (TABLE_LIST *tables= (table_name ? context->table_list : |
|
6004 |
context->first_name_resolution_table); |
|
6005 |
tables; |
|
6006 |
tables= (table_name ? tables->next_local : |
|
6007 |
tables->next_name_resolution_table) |
|
6008 |
)
|
|
6009 |
{
|
|
6010 |
Field *field; |
|
6011 |
TABLE *table= tables->table; |
|
6012 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6013 |
assert(tables->is_leaf_for_name_resolution()); |
1
by brian
clean slate |
6014 |
|
6015 |
if ((table_name && my_strcasecmp(table_alias_charset, table_name, tables->alias)) || |
|
6016 |
(db_name && strcmp(tables->db,db_name))) |
|
6017 |
continue; |
|
6018 |
||
6019 |
/*
|
|
6020 |
Update the tables used in the query based on the referenced fields. For
|
|
6021 |
views and natural joins this update is performed inside the loop below.
|
|
6022 |
*/
|
|
6023 |
if (table) |
|
6024 |
thd->used_tables|= table->map; |
|
6025 |
||
6026 |
/*
|
|
6027 |
Initialize a generic field iterator for the current table reference.
|
|
6028 |
Notice that it is guaranteed that this iterator will iterate over the
|
|
6029 |
fields of a single table reference, because 'tables' is a leaf (for
|
|
6030 |
name resolution purposes).
|
|
6031 |
*/
|
|
6032 |
field_iterator.set(tables); |
|
6033 |
||
6034 |
for (; !field_iterator.end_of_fields(); field_iterator.next()) |
|
6035 |
{
|
|
6036 |
Item *item; |
|
6037 |
||
6038 |
if (!(item= field_iterator.create_item(thd))) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6039 |
return(true); |
1
by brian
clean slate |
6040 |
|
6041 |
if (!found) |
|
6042 |
{
|
|
55
by brian
Update for using real bool types. |
6043 |
found= true; |
1
by brian
clean slate |
6044 |
it->replace(item); /* Replace '*' with the first found item. */ |
6045 |
}
|
|
6046 |
else
|
|
6047 |
it->after(item); /* Add 'item' to the SELECT list. */ |
|
6048 |
||
6049 |
if ((field= field_iterator.field())) |
|
6050 |
{
|
|
6051 |
/* Mark fields as used to allow storage engine to optimze access */
|
|
6052 |
bitmap_set_bit(field->table->read_set, field->field_index); |
|
6053 |
if (table) |
|
6054 |
{
|
|
6055 |
table->covering_keys.intersect(field->part_of_key); |
|
6056 |
table->merge_keys.merge(field->part_of_key); |
|
6057 |
}
|
|
6058 |
if (tables->is_natural_join) |
|
6059 |
{
|
|
6060 |
TABLE *field_table; |
|
6061 |
/*
|
|
6062 |
In this case we are sure that the column ref will not be created
|
|
6063 |
because it was already created and stored with the natural join.
|
|
6064 |
*/
|
|
6065 |
Natural_join_column *nj_col; |
|
6066 |
if (!(nj_col= field_iterator.get_natural_column_ref())) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6067 |
return(true); |
6068 |
assert(nj_col->table_field); |
|
1
by brian
clean slate |
6069 |
field_table= nj_col->table_ref->table; |
6070 |
if (field_table) |
|
6071 |
{
|
|
6072 |
thd->used_tables|= field_table->map; |
|
6073 |
field_table->covering_keys.intersect(field->part_of_key); |
|
6074 |
field_table->merge_keys.merge(field->part_of_key); |
|
6075 |
field_table->used_fields++; |
|
6076 |
}
|
|
6077 |
}
|
|
6078 |
}
|
|
6079 |
else
|
|
6080 |
thd->used_tables|= item->used_tables(); |
|
6081 |
thd->lex->current_select->cur_pos_in_select_list++; |
|
6082 |
}
|
|
6083 |
/*
|
|
6084 |
In case of stored tables, all fields are considered as used,
|
|
6085 |
while in the case of views, the fields considered as used are the
|
|
6086 |
ones marked in setup_tables during fix_fields of view columns.
|
|
6087 |
For NATURAL joins, used_tables is updated in the IF above.
|
|
6088 |
*/
|
|
6089 |
if (table) |
|
6090 |
table->used_fields= table->s->fields; |
|
6091 |
}
|
|
6092 |
if (found) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6093 |
return(false); |
1
by brian
clean slate |
6094 |
|
6095 |
/*
|
|
6096 |
TODO: in the case when we skipped all columns because there was a
|
|
6097 |
qualified '*', and all columns were coalesced, we have to give a more
|
|
6098 |
meaningful message than ER_BAD_TABLE_ERROR.
|
|
6099 |
*/
|
|
6100 |
if (!table_name) |
|
6101 |
my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0)); |
|
6102 |
else
|
|
6103 |
my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name); |
|
6104 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6105 |
return(true); |
1
by brian
clean slate |
6106 |
}
|
6107 |
||
6108 |
||
6109 |
/*
|
|
6110 |
Fix all conditions and outer join expressions.
|
|
6111 |
||
6112 |
SYNOPSIS
|
|
6113 |
setup_conds()
|
|
6114 |
thd thread handler
|
|
6115 |
tables list of tables for name resolving (select_lex->table_list)
|
|
6116 |
leaves list of leaves of join table tree (select_lex->leaf_tables)
|
|
6117 |
conds WHERE clause
|
|
6118 |
||
6119 |
DESCRIPTION
|
|
6120 |
TODO
|
|
6121 |
||
6122 |
RETURN
|
|
55
by brian
Update for using real bool types. |
6123 |
true if some error occured (e.g. out of memory)
|
6124 |
false if all is OK
|
|
1
by brian
clean slate |
6125 |
*/
|
6126 |
||
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
6127 |
int setup_conds(THD *thd, TABLE_LIST *tables __attribute__((unused)), |
77.1.45
by Monty Taylor
Warning fixes. |
6128 |
TABLE_LIST *leaves, |
1
by brian
clean slate |
6129 |
COND **conds) |
6130 |
{
|
|
6131 |
SELECT_LEX *select_lex= thd->lex->current_select; |
|
6132 |
TABLE_LIST *table= NULL; // For HP compilers |
|
6133 |
void *save_thd_marker= thd->thd_marker; |
|
6134 |
/*
|
|
55
by brian
Update for using real bool types. |
6135 |
it_is_update set to true when tables of primary SELECT_LEX (SELECT_LEX
|
1
by brian
clean slate |
6136 |
which belong to LEX, i.e. most up SELECT) will be updated by
|
6137 |
INSERT/UPDATE/LOAD
|
|
6138 |
NOTE: using this condition helps to prevent call of prepare_check_option()
|
|
6139 |
from subquery of VIEW, because tables of subquery belongs to VIEW
|
|
6140 |
(see condition before prepare_check_option() call)
|
|
6141 |
*/
|
|
6142 |
bool save_is_item_list_lookup= select_lex->is_item_list_lookup; |
|
6143 |
select_lex->is_item_list_lookup= 0; |
|
6144 |
||
6145 |
thd->mark_used_columns= MARK_COLUMNS_READ; |
|
6146 |
select_lex->cond_count= 0; |
|
6147 |
select_lex->between_count= 0; |
|
6148 |
select_lex->max_equal_elems= 0; |
|
6149 |
||
6150 |
thd->thd_marker= (void*)1; |
|
6151 |
if (*conds) |
|
6152 |
{
|
|
6153 |
thd->where="where clause"; |
|
6154 |
if ((!(*conds)->fixed && (*conds)->fix_fields(thd, conds)) || |
|
6155 |
(*conds)->check_cols(1)) |
|
6156 |
goto err_no_arena; |
|
6157 |
}
|
|
6158 |
thd->thd_marker= save_thd_marker; |
|
6159 |
||
6160 |
/*
|
|
6161 |
Apply fix_fields() to all ON clauses at all levels of nesting,
|
|
6162 |
including the ones inside view definitions.
|
|
6163 |
*/
|
|
6164 |
for (table= leaves; table; table= table->next_leaf) |
|
6165 |
{
|
|
6166 |
TABLE_LIST *embedded; /* The table at the current level of nesting. */ |
|
6167 |
TABLE_LIST *embedding= table; /* The parent nested table reference. */ |
|
6168 |
do
|
|
6169 |
{
|
|
6170 |
embedded= embedding; |
|
6171 |
if (embedded->on_expr) |
|
6172 |
{
|
|
6173 |
/* Make a join an a expression */
|
|
6174 |
thd->thd_marker= (void*)embedded; |
|
6175 |
thd->where="on clause"; |
|
6176 |
if ((!embedded->on_expr->fixed && embedded->on_expr->fix_fields(thd, &embedded->on_expr)) || |
|
6177 |
embedded->on_expr->check_cols(1)) |
|
6178 |
goto err_no_arena; |
|
6179 |
select_lex->cond_count++; |
|
6180 |
}
|
|
6181 |
embedding= embedded->embedding; |
|
6182 |
}
|
|
6183 |
while (embedding && |
|
6184 |
embedding->nested_join->join_list.head() == embedded); |
|
6185 |
||
6186 |
}
|
|
6187 |
thd->thd_marker= save_thd_marker; |
|
6188 |
||
6189 |
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6190 |
return(test(thd->is_error())); |
1
by brian
clean slate |
6191 |
|
6192 |
err_no_arena: |
|
6193 |
select_lex->is_item_list_lookup= save_is_item_list_lookup; |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6194 |
return(1); |
1
by brian
clean slate |
6195 |
}
|
6196 |
||
6197 |
||
6198 |
/******************************************************************************
|
|
6199 |
** Fill a record with data (for INSERT or UPDATE)
|
|
6200 |
** Returns : 1 if some field has wrong type
|
|
6201 |
******************************************************************************/
|
|
6202 |
||
6203 |
||
6204 |
/*
|
|
6205 |
Fill fields with given items.
|
|
6206 |
||
6207 |
SYNOPSIS
|
|
6208 |
fill_record()
|
|
6209 |
thd thread handler
|
|
6210 |
fields Item_fields list to be filled
|
|
6211 |
values values to fill with
|
|
55
by brian
Update for using real bool types. |
6212 |
ignore_errors true if we should ignore errors
|
1
by brian
clean slate |
6213 |
|
6214 |
NOTE
|
|
6215 |
fill_record() may set table->auto_increment_field_not_null and a
|
|
6216 |
caller should make sure that it is reset after their last call to this
|
|
6217 |
function.
|
|
6218 |
||
6219 |
RETURN
|
|
55
by brian
Update for using real bool types. |
6220 |
false OK
|
6221 |
true error occured
|
|
1
by brian
clean slate |
6222 |
*/
|
6223 |
||
6224 |
bool
|
|
6225 |
fill_record(THD * thd, List<Item> &fields, List<Item> &values, bool ignore_errors) |
|
6226 |
{
|
|
6227 |
List_iterator_fast<Item> f(fields),v(values); |
|
6228 |
Item *value, *fld; |
|
6229 |
Item_field *field; |
|
6230 |
TABLE *table= 0; |
|
6231 |
||
6232 |
/*
|
|
6233 |
Reset the table->auto_increment_field_not_null as it is valid for
|
|
6234 |
only one row.
|
|
6235 |
*/
|
|
6236 |
if (fields.elements) |
|
6237 |
{
|
|
6238 |
/*
|
|
6239 |
On INSERT or UPDATE fields are checked to be from the same table,
|
|
6240 |
thus we safely can take table from the first field.
|
|
6241 |
*/
|
|
6242 |
fld= (Item_field*)f++; |
|
6243 |
if (!(field= fld->filed_for_view_update())) |
|
6244 |
{
|
|
6245 |
my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name); |
|
6246 |
goto err; |
|
6247 |
}
|
|
6248 |
table= field->field->table; |
|
55
by brian
Update for using real bool types. |
6249 |
table->auto_increment_field_not_null= false; |
1
by brian
clean slate |
6250 |
f.rewind(); |
6251 |
}
|
|
6252 |
while ((fld= f++)) |
|
6253 |
{
|
|
6254 |
if (!(field= fld->filed_for_view_update())) |
|
6255 |
{
|
|
6256 |
my_error(ER_NONUPDATEABLE_COLUMN, MYF(0), fld->name); |
|
6257 |
goto err; |
|
6258 |
}
|
|
6259 |
value=v++; |
|
6260 |
Field *rfield= field->field; |
|
6261 |
table= rfield->table; |
|
6262 |
if (rfield == table->next_number_field) |
|
55
by brian
Update for using real bool types. |
6263 |
table->auto_increment_field_not_null= true; |
1
by brian
clean slate |
6264 |
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors) |
6265 |
{
|
|
6266 |
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0)); |
|
6267 |
goto err; |
|
6268 |
}
|
|
6269 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6270 |
return(thd->is_error()); |
1
by brian
clean slate |
6271 |
err: |
6272 |
if (table) |
|
55
by brian
Update for using real bool types. |
6273 |
table->auto_increment_field_not_null= false; |
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6274 |
return(true); |
1
by brian
clean slate |
6275 |
}
|
6276 |
||
6277 |
||
6278 |
/*
|
|
6279 |
Fill field buffer with values from Field list
|
|
6280 |
||
6281 |
SYNOPSIS
|
|
6282 |
fill_record()
|
|
6283 |
thd thread handler
|
|
6284 |
ptr pointer on pointer to record
|
|
6285 |
values list of fields
|
|
55
by brian
Update for using real bool types. |
6286 |
ignore_errors true if we should ignore errors
|
1
by brian
clean slate |
6287 |
|
6288 |
NOTE
|
|
6289 |
fill_record() may set table->auto_increment_field_not_null and a
|
|
6290 |
caller should make sure that it is reset after their last call to this
|
|
6291 |
function.
|
|
6292 |
||
6293 |
RETURN
|
|
55
by brian
Update for using real bool types. |
6294 |
false OK
|
6295 |
true error occured
|
|
1
by brian
clean slate |
6296 |
*/
|
6297 |
||
6298 |
bool
|
|
77.1.45
by Monty Taylor
Warning fixes. |
6299 |
fill_record(THD *thd, Field **ptr, List<Item> &values, |
212.1.3
by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)). |
6300 |
bool ignore_errors __attribute__((unused))) |
1
by brian
clean slate |
6301 |
{
|
6302 |
List_iterator_fast<Item> v(values); |
|
6303 |
Item *value; |
|
6304 |
TABLE *table= 0; |
|
6305 |
||
6306 |
Field *field; |
|
6307 |
/*
|
|
6308 |
Reset the table->auto_increment_field_not_null as it is valid for
|
|
6309 |
only one row.
|
|
6310 |
*/
|
|
6311 |
if (*ptr) |
|
6312 |
{
|
|
6313 |
/*
|
|
6314 |
On INSERT or UPDATE fields are checked to be from the same table,
|
|
6315 |
thus we safely can take table from the first field.
|
|
6316 |
*/
|
|
6317 |
table= (*ptr)->table; |
|
55
by brian
Update for using real bool types. |
6318 |
table->auto_increment_field_not_null= false; |
1
by brian
clean slate |
6319 |
}
|
6320 |
while ((field = *ptr++) && ! thd->is_error()) |
|
6321 |
{
|
|
6322 |
value=v++; |
|
6323 |
table= field->table; |
|
6324 |
if (field == table->next_number_field) |
|
55
by brian
Update for using real bool types. |
6325 |
table->auto_increment_field_not_null= true; |
1
by brian
clean slate |
6326 |
if (value->save_in_field(field, 0) < 0) |
6327 |
goto err; |
|
6328 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6329 |
return(thd->is_error()); |
1
by brian
clean slate |
6330 |
|
6331 |
err: |
|
6332 |
if (table) |
|
55
by brian
Update for using real bool types. |
6333 |
table->auto_increment_field_not_null= false; |
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6334 |
return(true); |
1
by brian
clean slate |
6335 |
}
|
6336 |
||
6337 |
||
198
by Brian Aker
More my_bool... man am I getting tired of writing this. |
6338 |
bool mysql_rm_tmp_tables(void) |
1
by brian
clean slate |
6339 |
{
|
6340 |
uint i, idx; |
|
6341 |
char filePath[FN_REFLEN], *tmpdir, filePathCopy[FN_REFLEN]; |
|
6342 |
MY_DIR *dirp; |
|
6343 |
FILEINFO *file; |
|
6344 |
TABLE_SHARE share; |
|
6345 |
THD *thd; |
|
6346 |
||
6347 |
if (!(thd= new THD)) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6348 |
return(1); |
1
by brian
clean slate |
6349 |
thd->thread_stack= (char*) &thd; |
6350 |
thd->store_globals(); |
|
6351 |
||
6352 |
for (i=0; i<=mysql_tmpdir_list.max; i++) |
|
6353 |
{
|
|
6354 |
tmpdir=mysql_tmpdir_list.list[i]; |
|
6355 |
/* See if the directory exists */
|
|
6356 |
if (!(dirp = my_dir(tmpdir,MYF(MY_WME | MY_DONT_SORT)))) |
|
6357 |
continue; |
|
6358 |
||
6359 |
/* Remove all SQLxxx tables from directory */
|
|
6360 |
||
6361 |
for (idx=0 ; idx < (uint) dirp->number_off_files ; idx++) |
|
6362 |
{
|
|
6363 |
file=dirp->dir_entry+idx; |
|
6364 |
||
6365 |
/* skiping . and .. */
|
|
6366 |
if (file->name[0] == '.' && (!file->name[1] || |
|
6367 |
(file->name[1] == '.' && !file->name[2]))) |
|
6368 |
continue; |
|
6369 |
||
212.6.6
by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove(). |
6370 |
if (!memcmp(file->name, tmp_file_prefix, tmp_file_prefix_length)) |
1
by brian
clean slate |
6371 |
{
|
6372 |
char *ext= fn_ext(file->name); |
|
6373 |
uint ext_len= strlen(ext); |
|
77.1.18
by Monty Taylor
Removed my_vsnprintf and my_snprintf. |
6374 |
uint filePath_len= snprintf(filePath, sizeof(filePath), |
6375 |
"%s%c%s", tmpdir, FN_LIBCHAR, |
|
6376 |
file->name); |
|
212.6.6
by Mats Kindahl
Removing redundant use of casts in drizzled/ for memcmp(), memcpy(), memset(), and memmove(). |
6377 |
if (!memcmp(reg_ext, ext, ext_len)) |
1
by brian
clean slate |
6378 |
{
|
6379 |
handler *handler_file= 0; |
|
6380 |
/* We should cut file extention before deleting of table */
|
|
6381 |
memcpy(filePathCopy, filePath, filePath_len - ext_len); |
|
6382 |
filePathCopy[filePath_len - ext_len]= 0; |
|
6383 |
init_tmp_table_share(thd, &share, "", 0, "", filePathCopy); |
|
6384 |
if (!open_table_def(thd, &share, 0) && |
|
6385 |
((handler_file= get_new_handler(&share, thd->mem_root, |
|
6386 |
share.db_type())))) |
|
6387 |
{
|
|
6388 |
handler_file->ha_delete_table(filePathCopy); |
|
6389 |
delete handler_file; |
|
6390 |
}
|
|
6391 |
free_table_share(&share); |
|
6392 |
}
|
|
6393 |
/*
|
|
6394 |
File can be already deleted by tmp_table.file->delete_table().
|
|
6395 |
So we hide error messages which happnes during deleting of these
|
|
6396 |
files(MYF(0)).
|
|
6397 |
*/
|
|
6398 |
VOID(my_delete(filePath, MYF(0))); |
|
6399 |
}
|
|
6400 |
}
|
|
6401 |
my_dirend(dirp); |
|
6402 |
}
|
|
6403 |
delete thd; |
|
6404 |
my_pthread_setspecific_ptr(THR_THD, 0); |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6405 |
return(0); |
1
by brian
clean slate |
6406 |
}
|
6407 |
||
6408 |
||
6409 |
||
6410 |
/*****************************************************************************
|
|
6411 |
unireg support functions
|
|
6412 |
*****************************************************************************/
|
|
6413 |
||
6414 |
/*
|
|
6415 |
Invalidate any cache entries that are for some DB
|
|
6416 |
||
6417 |
SYNOPSIS
|
|
6418 |
remove_db_from_cache()
|
|
6419 |
db Database name. This will be in lower case if
|
|
6420 |
lower_case_table_name is set
|
|
6421 |
||
6422 |
NOTE:
|
|
6423 |
We can't use hash_delete when looping hash_elements. We mark them first
|
|
6424 |
and afterwards delete those marked unused.
|
|
6425 |
*/
|
|
6426 |
||
6427 |
void remove_db_from_cache(const char *db) |
|
6428 |
{
|
|
6429 |
for (uint idx=0 ; idx < open_cache.records ; idx++) |
|
6430 |
{
|
|
6431 |
TABLE *table=(TABLE*) hash_element(&open_cache,idx); |
|
6432 |
if (!strcmp(table->s->db.str, db)) |
|
6433 |
{
|
|
6434 |
table->s->version= 0L; /* Free when thread is ready */ |
|
6435 |
if (!table->in_use) |
|
6436 |
relink_unused(table); |
|
6437 |
}
|
|
6438 |
}
|
|
6439 |
while (unused_tables && !unused_tables->s->version) |
|
6440 |
VOID(hash_delete(&open_cache,(uchar*) unused_tables)); |
|
6441 |
}
|
|
6442 |
||
6443 |
||
6444 |
/*
|
|
6445 |
free all unused tables
|
|
6446 |
||
6447 |
NOTE
|
|
6448 |
This is called by 'handle_manager' when one wants to periodicly flush
|
|
6449 |
all not used tables.
|
|
6450 |
*/
|
|
6451 |
||
6452 |
void flush_tables() |
|
6453 |
{
|
|
6454 |
(void) pthread_mutex_lock(&LOCK_open); |
|
6455 |
while (unused_tables) |
|
6456 |
hash_delete(&open_cache,(uchar*) unused_tables); |
|
6457 |
(void) pthread_mutex_unlock(&LOCK_open); |
|
6458 |
}
|
|
6459 |
||
6460 |
||
6461 |
/*
|
|
6462 |
Mark all entries with the table as deleted to force an reopen of the table
|
|
6463 |
||
6464 |
The table will be closed (not stored in cache) by the current thread when
|
|
6465 |
close_thread_tables() is called.
|
|
6466 |
||
6467 |
PREREQUISITES
|
|
6468 |
Lock on LOCK_open()
|
|
6469 |
||
6470 |
RETURN
|
|
6471 |
0 This thread now have exclusive access to this table and no other thread
|
|
6472 |
can access the table until close_thread_tables() is called.
|
|
6473 |
1 Table is in use by another thread
|
|
6474 |
*/
|
|
6475 |
||
6476 |
bool remove_table_from_cache(THD *thd, const char *db, const char *table_name, |
|
6477 |
uint flags) |
|
6478 |
{
|
|
6479 |
char key[MAX_DBKEY_LENGTH]; |
|
6480 |
uint key_length; |
|
6481 |
TABLE *table; |
|
6482 |
TABLE_SHARE *share; |
|
6483 |
bool result= 0, signalled= 0; |
|
6484 |
||
266.1.21
by Monty Taylor
Removed references to strmov and strnmov |
6485 |
key_length=(uint) (stpcpy(stpcpy(key,db)+1,table_name)-key)+1; |
1
by brian
clean slate |
6486 |
for (;;) |
6487 |
{
|
|
6488 |
HASH_SEARCH_STATE state; |
|
6489 |
result= signalled= 0; |
|
6490 |
||
6491 |
for (table= (TABLE*) hash_first(&open_cache, (uchar*) key, key_length, |
|
6492 |
&state); |
|
6493 |
table; |
|
6494 |
table= (TABLE*) hash_next(&open_cache, (uchar*) key, key_length, |
|
6495 |
&state)) |
|
6496 |
{
|
|
6497 |
THD *in_use; |
|
6498 |
||
6499 |
table->s->version=0L; /* Free when thread is ready */ |
|
6500 |
if (!(in_use=table->in_use)) |
|
6501 |
{
|
|
6502 |
relink_unused(table); |
|
6503 |
}
|
|
6504 |
else if (in_use != thd) |
|
6505 |
{
|
|
6506 |
/*
|
|
6507 |
Mark that table is going to be deleted from cache. This will
|
|
6508 |
force threads that are in mysql_lock_tables() (but not yet
|
|
6509 |
in thr_multi_lock()) to abort it's locks, close all tables and retry
|
|
6510 |
*/
|
|
6511 |
in_use->some_tables_deleted= 1; |
|
6512 |
if (table->is_name_opened()) |
|
6513 |
{
|
|
6514 |
result=1; |
|
6515 |
}
|
|
6516 |
/*
|
|
6517 |
Now we must abort all tables locks used by this thread
|
|
6518 |
as the thread may be waiting to get a lock for another table.
|
|
6519 |
Note that we need to hold LOCK_open while going through the
|
|
6520 |
list. So that the other thread cannot change it. The other
|
|
6521 |
thread must also hold LOCK_open whenever changing the
|
|
6522 |
open_tables list. Aborting the MERGE lock after a child was
|
|
6523 |
closed and before the parent is closed would be fatal.
|
|
6524 |
*/
|
|
6525 |
for (TABLE *thd_table= in_use->open_tables; |
|
6526 |
thd_table ; |
|
6527 |
thd_table= thd_table->next) |
|
6528 |
{
|
|
6529 |
/* Do not handle locks of MERGE children. */
|
|
6530 |
if (thd_table->db_stat) // If table is open |
|
6531 |
signalled|= mysql_lock_abort_for_thread(thd, thd_table); |
|
6532 |
}
|
|
6533 |
}
|
|
6534 |
else
|
|
6535 |
result= result || (flags & RTFC_OWNED_BY_THD_FLAG); |
|
6536 |
}
|
|
6537 |
while (unused_tables && !unused_tables->s->version) |
|
6538 |
VOID(hash_delete(&open_cache,(uchar*) unused_tables)); |
|
6539 |
||
6540 |
/* Remove table from table definition cache if it's not in use */
|
|
6541 |
if ((share= (TABLE_SHARE*) hash_search(&table_def_cache,(uchar*) key, |
|
6542 |
key_length))) |
|
6543 |
{
|
|
6544 |
share->version= 0; // Mark for delete |
|
6545 |
if (share->ref_count == 0) |
|
6546 |
{
|
|
6547 |
pthread_mutex_lock(&share->mutex); |
|
6548 |
VOID(hash_delete(&table_def_cache, (uchar*) share)); |
|
6549 |
}
|
|
6550 |
}
|
|
6551 |
||
6552 |
if (result && (flags & RTFC_WAIT_OTHER_THREAD_FLAG)) |
|
6553 |
{
|
|
6554 |
/*
|
|
6555 |
Signal any thread waiting for tables to be freed to
|
|
6556 |
reopen their tables
|
|
6557 |
*/
|
|
6558 |
broadcast_refresh(); |
|
6559 |
if (!(flags & RTFC_CHECK_KILLED_FLAG) || !thd->killed) |
|
6560 |
{
|
|
6561 |
dropping_tables++; |
|
6562 |
if (likely(signalled)) |
|
6563 |
(void) pthread_cond_wait(&COND_refresh, &LOCK_open); |
|
6564 |
else
|
|
6565 |
{
|
|
6566 |
struct timespec abstime; |
|
6567 |
/*
|
|
6568 |
It can happen that another thread has opened the
|
|
6569 |
table but has not yet locked any table at all. Since
|
|
6570 |
it can be locked waiting for a table that our thread
|
|
6571 |
has done LOCK TABLE x WRITE on previously, we need to
|
|
6572 |
ensure that the thread actually hears our signal
|
|
6573 |
before we go to sleep. Thus we wait for a short time
|
|
6574 |
and then we retry another loop in the
|
|
6575 |
remove_table_from_cache routine.
|
|
6576 |
*/
|
|
6577 |
set_timespec(abstime, 10); |
|
6578 |
pthread_cond_timedwait(&COND_refresh, &LOCK_open, &abstime); |
|
6579 |
}
|
|
6580 |
dropping_tables--; |
|
6581 |
continue; |
|
6582 |
}
|
|
6583 |
}
|
|
6584 |
break; |
|
6585 |
}
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6586 |
return(result); |
1
by brian
clean slate |
6587 |
}
|
6588 |
||
6589 |
||
6590 |
bool is_equal(const LEX_STRING *a, const LEX_STRING *b) |
|
6591 |
{
|
|
6592 |
return a->length == b->length && !strncmp(a->str, b->str, a->length); |
|
6593 |
}
|
|
6594 |
||
6595 |
||
6596 |
/*
|
|
6597 |
Open and lock system tables for read.
|
|
6598 |
||
6599 |
SYNOPSIS
|
|
6600 |
open_system_tables_for_read()
|
|
6601 |
thd Thread context.
|
|
6602 |
table_list List of tables to open.
|
|
6603 |
backup Pointer to Open_tables_state instance where
|
|
6604 |
information about currently open tables will be
|
|
6605 |
saved, and from which will be restored when we will
|
|
6606 |
end work with system tables.
|
|
6607 |
||
6608 |
NOTES
|
|
6609 |
Thanks to restrictions which we put on opening and locking of
|
|
6610 |
system tables for writing, we can open and lock them for reading
|
|
6611 |
even when we already have some other tables open and locked. One
|
|
6612 |
must call close_system_tables() to close systems tables opened
|
|
6613 |
with this call.
|
|
6614 |
||
6615 |
RETURN
|
|
55
by brian
Update for using real bool types. |
6616 |
false Success
|
6617 |
true Error
|
|
1
by brian
clean slate |
6618 |
*/
|
6619 |
||
6620 |
bool
|
|
6621 |
open_system_tables_for_read(THD *thd, TABLE_LIST *table_list, |
|
6622 |
Open_tables_state *backup) |
|
6623 |
{
|
|
6624 |
thd->reset_n_backup_open_tables_state(backup); |
|
6625 |
||
6626 |
uint count= 0; |
|
6627 |
bool not_used; |
|
6628 |
for (TABLE_LIST *tables= table_list; tables; tables= tables->next_global) |
|
6629 |
{
|
|
6630 |
TABLE *table= open_table(thd, tables, thd->mem_root, ¬_used, |
|
6631 |
MYSQL_LOCK_IGNORE_FLUSH); |
|
6632 |
if (!table) |
|
6633 |
goto error; |
|
6634 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6635 |
assert(table->s->table_category == TABLE_CATEGORY_SYSTEM); |
1
by brian
clean slate |
6636 |
|
6637 |
table->use_all_columns(); |
|
6638 |
table->reginfo.lock_type= tables->lock_type; |
|
6639 |
tables->table= table; |
|
6640 |
count++; |
|
6641 |
}
|
|
6642 |
||
6643 |
{
|
|
6644 |
TABLE **list= (TABLE**) thd->alloc(sizeof(TABLE*) * count); |
|
6645 |
TABLE **ptr= list; |
|
6646 |
for (TABLE_LIST *tables= table_list; tables; tables= tables->next_global) |
|
6647 |
*(ptr++)= tables->table; |
|
6648 |
||
6649 |
thd->lock= mysql_lock_tables(thd, list, count, |
|
6650 |
MYSQL_LOCK_IGNORE_FLUSH, ¬_used); |
|
6651 |
}
|
|
6652 |
if (thd->lock) |
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6653 |
return(false); |
1
by brian
clean slate |
6654 |
|
6655 |
error: |
|
6656 |
close_system_tables(thd, backup); |
|
6657 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6658 |
return(true); |
1
by brian
clean slate |
6659 |
}
|
6660 |
||
6661 |
||
6662 |
/*
|
|
6663 |
Close system tables, opened with open_system_tables_for_read().
|
|
6664 |
||
6665 |
SYNOPSIS
|
|
6666 |
close_system_tables()
|
|
6667 |
thd Thread context
|
|
6668 |
backup Pointer to Open_tables_state instance which holds
|
|
6669 |
information about tables which were open before we
|
|
6670 |
decided to access system tables.
|
|
6671 |
*/
|
|
6672 |
||
6673 |
void
|
|
6674 |
close_system_tables(THD *thd, Open_tables_state *backup) |
|
6675 |
{
|
|
6676 |
close_thread_tables(thd); |
|
6677 |
thd->restore_backup_open_tables_state(backup); |
|
6678 |
}
|
|
6679 |
||
6680 |
||
6681 |
/*
|
|
6682 |
Open and lock one system table for update.
|
|
6683 |
||
6684 |
SYNOPSIS
|
|
6685 |
open_system_table_for_update()
|
|
6686 |
thd Thread context.
|
|
6687 |
one_table Table to open.
|
|
6688 |
||
6689 |
NOTES
|
|
6690 |
Table opened with this call should closed using close_thread_tables().
|
|
6691 |
||
6692 |
RETURN
|
|
6693 |
0 Error
|
|
6694 |
# Pointer to TABLE object of system table
|
|
6695 |
*/
|
|
6696 |
||
6697 |
TABLE * |
|
6698 |
open_system_table_for_update(THD *thd, TABLE_LIST *one_table) |
|
6699 |
{
|
|
6700 |
TABLE *table= open_ltable(thd, one_table, one_table->lock_type, 0); |
|
6701 |
if (table) |
|
6702 |
{
|
|
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6703 |
assert(table->s->table_category == TABLE_CATEGORY_SYSTEM); |
1
by brian
clean slate |
6704 |
table->use_all_columns(); |
6705 |
}
|
|
6706 |
||
51.1.48
by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE |
6707 |
return(table); |
1
by brian
clean slate |
6708 |
}
|
6709 |
||
6710 |
/**
|
|
6711 |
@} (end of group Data_Dictionary)
|
|
6712 |
*/
|