13
13
along with this program; if not, write to the Free Software
14
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
16
#define DRIZZLE_LEX 1
20
#include <drizzled/my_hash.h>
17
#include <drizzled/server_includes.h>
18
#include <mysys/hash.h>
19
#include <drizzled/db.h>
21
20
#include <drizzled/error.h>
22
21
#include <drizzled/nested_join.h>
23
22
#include <drizzled/query_id.h>
24
#include "drizzled/transaction_services.h"
25
23
#include <drizzled/sql_parse.h>
26
24
#include <drizzled/data_home.h>
27
25
#include <drizzled/sql_base.h>
28
26
#include <drizzled/show.h>
29
#include <drizzled/db.h>
27
#include <drizzled/plugin/info_schema_table.h>
30
28
#include <drizzled/function/time/unix_timestamp.h>
31
29
#include <drizzled/function/get_system_var.h>
32
30
#include <drizzled/item/cmpfunc.h>
39
37
#include <drizzled/statement.h>
40
38
#include <drizzled/statement/alter_table.h>
41
39
#include "drizzled/probes.h"
42
#include "drizzled/session_list.h"
43
#include "drizzled/global_charset_info.h"
45
41
#include "drizzled/plugin/logging.h"
46
#include "drizzled/plugin/query_rewrite.h"
47
#include "drizzled/plugin/authorization.h"
48
#include "drizzled/optimizer/explain_plan.h"
49
#include "drizzled/pthread_globals.h"
42
#include "drizzled/plugin/info_schema_table.h"
54
45
#include <algorithm>
56
#include "drizzled/internal/my_sys.h"
47
using namespace drizzled;
58
48
using namespace std;
60
extern int DRIZZLEparse(void *session); // from sql_yacc.cc
66
51
bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
67
52
static bool parse_sql(Session *session, Lex_input_stream *lip);
68
void mysql_parse(Session *session, const char *inBuf, uint32_t length);
53
static void mysql_parse(Session *session, const char *inBuf, uint32_t length,
54
const char ** found_semicolon);
71
57
@defgroup Runtime_Environment Runtime Environment
129
115
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
130
116
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
118
sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND;
119
sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND;
120
sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND;
121
sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND;
122
sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND;
123
sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND;
132
124
sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND;
133
125
sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND;
126
sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND;
127
sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
134
128
sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
135
129
sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
131
sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
132
CF_SHOW_TABLE_COMMAND);
133
sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
134
CF_SHOW_TABLE_COMMAND);
138
136
The following admin table operations are allowed
217
208
if (! session->readAndStoreQuery(packet, packet_length))
218
209
break; // fatal error is set
219
DRIZZLE_QUERY_START(session->query.c_str(),
210
DRIZZLE_QUERY_START(session->query,
220
211
session->thread_id,
221
const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
212
const_cast<const char *>(session->db ? session->db : ""));
213
const char* end_of_stmt= NULL;
223
plugin::QueryRewriter::rewriteQuery(session->db, session->query);
224
mysql_parse(session, session->query.c_str(), session->query.length());
215
mysql_parse(session, session->query, session->query_length, &end_of_stmt);
312
302
session->set_proc_info("cleaning up");
313
303
session->command= COM_SLEEP;
314
304
memset(session->process_list_info, 0, PROCESS_LIST_WIDTH);
315
session->query.clear();
306
session->query_length= 0;
317
308
session->set_proc_info(NULL);
318
free_root(session->mem_root,MYF(memory::KEEP_PREALLOC));
309
free_root(session->mem_root,MYF(MY_KEEP_PREALLOC));
320
311
if (DRIZZLE_QUERY_DONE_ENABLED() || DRIZZLE_COMMAND_DONE_ENABLED())
355
346
1 out of memory or SHOW commands are not allowed
356
347
in this version of the server.
358
static bool _schema_select(Session *session, Select_Lex *sel,
359
const string& schema_table_name)
361
LEX_STRING db, table;
363
We have to make non const db_name & table_name
364
because of lower_case_table_names
366
session->make_lex_string(&db, "data_dictionary", sizeof("data_dictionary"), false);
367
session->make_lex_string(&table, schema_table_name, false);
369
if (! sel->add_table_to_list(session, new Table_ident(db, table),
377
int prepare_new_schema_table(Session *session, LEX *lex,
378
const string& schema_table_name)
350
int prepare_schema_table(Session *session, LEX *lex, Table_ident *table_ident,
351
const string& schema_table_name)
380
353
Select_Lex *schema_select_lex= NULL;
356
if (schema_table_name.compare("TABLES") == 0 ||
357
schema_table_name.compare("TABLE_NAMES") == 0)
361
if (lex->select_lex.db == NULL &&
362
lex->copy_db_to(&lex->select_lex.db, &dummy))
366
schema_select_lex= new Select_Lex();
367
db.str= schema_select_lex->db= lex->select_lex.db;
368
schema_select_lex->table_list.first= NULL;
369
db.length= strlen(db.str);
371
if (check_db_name(&db))
373
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
377
else if (schema_table_name.compare("COLUMNS") == 0 ||
378
schema_table_name.compare("STATISTICS") == 0)
381
TableList **query_tables_last= lex->query_tables_last;
382
schema_select_lex= new Select_Lex();
383
/* 'parent_lex' is used in init_query() so it must be before it. */
384
schema_select_lex->parent_lex= lex;
385
schema_select_lex->init_query();
386
if (! schema_select_lex->add_table_to_list(session, table_ident, 0, 0, TL_READ))
390
lex->query_tables_last= query_tables_last;
382
393
Select_Lex *select_lex= lex->current_select;
383
394
assert(select_lex);
384
if (_schema_select(session, select_lex, schema_table_name))
395
if (make_schema_select(session, select_lex, schema_table_name))
432
443
/* list of all tables in query */
433
444
TableList *all_tables;
434
445
/* A peek into the query string */
435
size_t proc_info_len= session->query.length() > PROCESS_LIST_WIDTH ?
436
PROCESS_LIST_WIDTH : session->query.length();
446
size_t proc_info_len= session->query_length > PROCESS_LIST_WIDTH ?
447
PROCESS_LIST_WIDTH : session->query_length;
438
memcpy(session->process_list_info, session->query.c_str(), proc_info_len);
449
memcpy(session->process_list_info, session->query, proc_info_len);
439
450
session->process_list_info[proc_info_len]= '\0';
711
721
@param session Current thread
712
722
@param inBuf Begining of the query text
713
723
@param length Length of the query text
724
@param[out] found_semicolon For multi queries, position of the character of
725
the next query in the query text.
716
void mysql_parse(Session *session, const char *inBuf, uint32_t length)
728
static void mysql_parse(Session *session, const char *inBuf, uint32_t length,
729
const char ** found_semicolon)
733
The purpose of query_cache_send_result_to_client() is to lookup the
734
query in the query cache first, to avoid parsing and executing it.
735
So, the natural implementation would be to:
736
- first, call query_cache_send_result_to_client,
737
- second, if caching failed, initialise the lexical and syntactic parser.
738
The problem is that the query cache depends on a clean initialization
739
of (among others) lex->safe_to_cache_query and session->server_status,
740
which are reset respectively in
742
- mysql_reset_session_for_next_command()
743
So, initializing the lexical analyser *before* using the query cache
744
is required for the cache to work properly.
745
FIXME: cleanup the dependencies in the code to simplify this.
718
747
lex_start(session);
719
748
session->reset_for_next_command();
721
LEX *lex= session->lex;
723
Lex_input_stream lip(session, inBuf, length);
725
bool err= parse_sql(session, &lip);
751
LEX *lex= session->lex;
753
Lex_input_stream lip(session, inBuf, length);
755
bool err= parse_sql(session, &lip);
756
*found_semicolon= lip.found_semicolon;
730
if (! session->is_error())
732
DRIZZLE_QUERY_EXEC_START(session->query.c_str(),
734
const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
735
/* Actually execute the query */
736
mysql_execute_command(session);
737
DRIZZLE_QUERY_EXEC_DONE(0);
761
if (! session->is_error())
764
Binlog logs a string starting from session->query and having length
765
session->query_length; so we set session->query_length correctly (to not
766
log several statements in one event, when we executed only first).
767
We set it to not see the ';' (otherwise it would get into binlog
768
and Query_log_event::print() would give ';;' output).
769
This also helps display only the current query in SHOW
771
Note that we don't need LOCK_thread_count to modify query_length.
773
if (*found_semicolon &&
774
(session->query_length= (ulong)(*found_semicolon - session->query)))
775
session->query_length--;
776
DRIZZLE_QUERY_EXEC_START(session->query,
778
const_cast<const char *>(session->db ? session->db : ""));
779
/* Actually execute the query */
780
mysql_execute_command(session);
781
DRIZZLE_QUERY_EXEC_DONE(0);
743
assert(session->is_error());
747
session->set_proc_info("freeing items");
748
session->end_statement();
749
session->cleanup_after_query();
787
assert(session->is_error());
790
session->set_proc_info("freeing items");
791
session->end_statement();
792
session->cleanup_after_query();
901
if (table->is_derived_table() == false && table->db.str)
945
if (table->is_derived_table() == false && table->db.str &&
946
check_db_name(&table->db))
903
my_casedn_str(files_charset_info, table->db.str);
905
SchemaIdentifier schema_identifier(string(table->db.str, table->db.length));
906
if (not check_db_name(schema_identifier))
909
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
948
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
914
952
if (!alias) /* Alias is case sensitive */
942
980
ptr->table_name=table->table.str;
943
981
ptr->table_name_length=table->table.length;
944
982
ptr->lock_type= lock_type;
983
ptr->updating= test(table_options & TL_OPTION_UPDATING);
945
984
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
946
985
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
947
986
ptr->derived= table->sel;
987
if (!ptr->derived && !my_strcasecmp(system_charset_info, ptr->db,
988
INFORMATION_SCHEMA_NAME.c_str()))
990
plugin::InfoSchemaTable *schema_table= plugin::InfoSchemaTable::getTable(ptr->table_name);
992
(schema_table->isHidden() &&
993
((sql_command_flags[lex->sql_command].test(CF_BIT_STATUS_COMMAND)) == 0 ||
995
this check is used for show columns|keys from I_S hidden table
997
lex->sql_command == SQLCOM_SHOW_FIELDS ||
998
lex->sql_command == SQLCOM_SHOW_KEYS)))
1000
my_error(ER_UNKNOWN_TABLE, MYF(0),
1001
ptr->table_name, INFORMATION_SCHEMA_NAME.c_str());
948
1005
ptr->select_lex= lex->current_select;
949
1006
ptr->index_hints= index_hints_arg;
950
1007
ptr->option= option ? option->str : 0;
1602
1658
bool create_table_precheck(TableIdentifier &identifier)
1604
if (not plugin::StorageEngine::canCreateTable(identifier))
1606
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", identifier.getSchemaName().c_str());
1610
if (not plugin::StorageEngine::doesSchemaExist(identifier))
1612
my_error(ER_BAD_DB_ERROR, MYF(0), identifier.getSchemaName().c_str());
1660
if (strcmp(identifier.getDBName(), "information_schema") == 0)
1662
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());