12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
17
#include "config.h"
20
18
#include <drizzled/my_hash.h>
21
19
#include <drizzled/error.h>
22
20
#include <drizzled/nested_join.h>
23
21
#include <drizzled/query_id.h>
24
#include "drizzled/transaction_services.h"
25
22
#include <drizzled/sql_parse.h>
26
23
#include <drizzled/data_home.h>
27
24
#include <drizzled/sql_base.h>
28
25
#include <drizzled/show.h>
29
26
#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/cache.h"
40
#include "drizzled/session_list.h"
43
41
#include "drizzled/global_charset_info.h"
45
44
#include "drizzled/plugin/logging.h"
46
#include "drizzled/plugin/query_rewrite.h"
47
#include "drizzled/plugin/query_cache.h"
48
#include "drizzled/plugin/authorization.h"
45
#include "drizzled/plugin/info_schema_table.h"
49
46
#include "drizzled/optimizer/explain_plan.h"
50
47
#include "drizzled/pthread_globals.h"
51
#include "drizzled/plugin/event_observer.h"
53
49
#include <limits.h>
56
52
#include <algorithm>
57
#include <boost/date_time.hpp>
58
54
#include "drizzled/internal/my_sys.h"
56
using namespace drizzled;
60
57
using namespace std;
62
extern int DRIZZLEparse(void *session); // from sql_yacc.cc
68
60
bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
69
61
static bool parse_sql(Session *session, Lex_input_stream *lip);
70
void mysql_parse(Session *session, const char *inBuf, uint32_t length);
62
static void mysql_parse(Session *session, const char *inBuf, uint32_t length,
63
const char ** found_semicolon);
73
66
@defgroup Runtime_Environment Runtime Environment
131
124
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
132
125
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
127
sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND;
128
sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND;
129
sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND;
130
sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND;
131
sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND;
132
sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND;
134
133
sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND;
135
134
sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND;
135
sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND;
136
sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
136
137
sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
137
138
sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
140
sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
141
CF_SHOW_TABLE_COMMAND);
142
sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
143
CF_SHOW_TABLE_COMMAND);
140
145
The following admin table operations are allowed
184
190
/* Increase id and count all other statements. */
186
session->status_var.questions++;
192
statistic_increment(session->status_var.questions, &LOCK_status);
190
196
/* TODO: set session->lex->sql_command to SQLCOM_END here */
192
198
plugin::Logging::preDo(session);
193
if (unlikely(plugin::EventObserver::beforeStatement(*session)))
195
// We should do something about an error...
198
200
session->server_status&=
199
201
~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
200
202
switch (command) {
201
203
case COM_INIT_DB:
203
if (packet_length == 0)
205
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
209
string tmp(packet, packet_length);
211
SchemaIdentifier identifier(tmp);
213
if (not mysql_change_db(session, identifier))
205
string database_name(packet);
206
NonNormalisedDatabaseName non_normalised_database_name(database_name);
207
NormalisedDatabaseName normalised_database_name(non_normalised_database_name);
209
status_var_increment(session->status_var.com_stat[SQLCOM_CHANGE_DB]);
211
if (! mysql_change_db(session, normalised_database_name, false))
215
213
session->my_ok();
221
if (not session->readAndStoreQuery(packet, packet_length))
219
if (! session->readAndStoreQuery(packet, packet_length))
222
220
break; // fatal error is set
223
DRIZZLE_QUERY_START(session->getQueryString()->c_str(),
221
DRIZZLE_QUERY_START(session->query,
224
222
session->thread_id,
225
const_cast<const char *>(session->schema()->c_str()));
223
const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
224
const char* end_of_stmt= NULL;
227
mysql_parse(session, session->getQueryString()->c_str(), session->getQueryString()->length());
226
mysql_parse(session, session->query, session->query_length, &end_of_stmt);
310
308
session->close_thread_tables();
312
310
plugin::Logging::postDo(session);
313
if (unlikely(plugin::EventObserver::afterStatement(*session)))
315
// We should do something about an error...
318
312
/* Store temp state for processlist */
319
313
session->set_proc_info("cleaning up");
320
314
session->command= COM_SLEEP;
321
session->resetQueryString();
315
memset(session->process_list_info, 0, PROCESS_LIST_WIDTH);
317
session->query_length= 0;
323
319
session->set_proc_info(NULL);
324
session->mem_root->free_root(MYF(memory::KEEP_PREALLOC));
320
free_root(session->mem_root,MYF(memory::KEEP_PREALLOC));
326
322
if (DRIZZLE_QUERY_DONE_ENABLED() || DRIZZLE_COMMAND_DONE_ENABLED())
361
357
1 out of memory or SHOW commands are not allowed
362
358
in this version of the server.
364
static bool _schema_select(Session *session, Select_Lex *sel,
365
const string& schema_table_name)
367
LEX_STRING db, table;
368
bitset<NUM_OF_TABLE_OPTIONS> table_options;
370
We have to make non const db_name & table_name
371
because of lower_case_table_names
373
session->make_lex_string(&db, "data_dictionary", sizeof("data_dictionary"), false);
374
session->make_lex_string(&table, schema_table_name, false);
376
if (! sel->add_table_to_list(session, new Table_ident(db, table),
377
NULL, table_options, TL_READ))
384
int prepare_new_schema_table(Session *session, LEX *lex,
385
const string& schema_table_name)
361
int prepare_schema_table(Session *session, LEX *lex, Table_ident *table_ident,
362
const string& schema_table_name)
387
364
Select_Lex *schema_select_lex= NULL;
367
if (schema_table_name.compare("TABLES") == 0 ||
368
schema_table_name.compare("TABLE_NAMES") == 0)
371
if (lex->select_lex.db == NULL &&
372
lex->copy_db_to(&lex->select_lex.db, &dummy))
376
schema_select_lex= new Select_Lex();
377
schema_select_lex->db= lex->select_lex.db;
379
string database_name(schema_select_lex->db);
380
NonNormalisedDatabaseName non_normalised_database_name(database_name);
381
NormalisedDatabaseName normalised_database_name(non_normalised_database_name);
383
schema_select_lex->table_list.first= NULL;
385
if (! normalised_database_name.isValid())
387
my_error(ER_WRONG_DB_NAME, MYF(0),
388
normalised_database_name.to_string().c_str());
392
else if (schema_table_name.compare("COLUMNS") == 0 ||
393
schema_table_name.compare("STATISTICS") == 0)
396
TableList **query_tables_last= lex->query_tables_last;
397
schema_select_lex= new Select_Lex();
398
/* 'parent_lex' is used in init_query() so it must be before it. */
399
schema_select_lex->parent_lex= lex;
400
schema_select_lex->init_query();
401
if (! schema_select_lex->add_table_to_list(session, table_ident, 0, 0, TL_READ))
405
lex->query_tables_last= query_tables_last;
389
408
Select_Lex *select_lex= lex->current_select;
390
409
assert(select_lex);
391
if (_schema_select(session, select_lex, schema_table_name))
410
if (make_schema_select(session, select_lex, schema_table_name))
712
737
@param session Current thread
713
738
@param inBuf Begining of the query text
714
739
@param length Length of the query text
740
@param[out] found_semicolon For multi queries, position of the character of
741
the next query in the query text.
717
void mysql_parse(Session *session, const char *inBuf, uint32_t length)
744
static void mysql_parse(Session *session, const char *inBuf, uint32_t length,
745
const char ** found_semicolon)
719
boost::posix_time::ptime start_time=boost::posix_time::microsec_clock::local_time();
720
session->lex->start(session);
749
The purpose of query_cache_send_result_to_client() is to lookup the
750
query in the query cache first, to avoid parsing and executing it.
751
So, the natural implementation would be to:
752
- first, call query_cache_send_result_to_client,
753
- second, if caching failed, initialise the lexical and syntactic parser.
754
The problem is that the query cache depends on a clean initialization
755
of (among others) lex->safe_to_cache_query and session->server_status,
756
which are reset respectively in
758
- mysql_reset_session_for_next_command()
759
So, initializing the lexical analyser *before* using the query cache
760
is required for the cache to work properly.
761
FIXME: cleanup the dependencies in the code to simplify this.
722
764
session->reset_for_next_command();
723
/* Check if the Query is Cached if and return true if yes
724
* TODO the plugin has to make sure that the query is cacheble
725
* by setting the query_safe_cache param to TRUE
728
if (plugin::QueryCache::isCached(session))
730
res= plugin::QueryCache::sendCachedResultset(session);
736
LEX *lex= session->lex;
737
Lex_input_stream lip(session, inBuf, length);
738
bool err= parse_sql(session, &lip);
767
LEX *lex= session->lex;
769
Lex_input_stream lip(session, inBuf, length);
771
bool err= parse_sql(session, &lip);
772
*found_semicolon= lip.found_semicolon;
742
if (not session->is_error())
744
DRIZZLE_QUERY_EXEC_START(session->getQueryString()->c_str(),
746
const_cast<const char *>(session->schema()->c_str()));
747
// Implement Views here --Brian
748
/* Actually execute the query */
777
if (! session->is_error())
780
Binlog logs a string starting from session->query and having length
781
session->query_length; so we set session->query_length correctly (to not
782
log several statements in one event, when we executed only first).
783
We set it to not see the ';' (otherwise it would get into binlog
784
and Query_log_event::print() would give ';;' output).
785
This also helps display only the current query in SHOW
787
Note that we don't need LOCK_thread_count to modify query_length.
789
if (*found_semicolon &&
790
(session->query_length= (ulong)(*found_semicolon - session->query)))
791
session->query_length--;
792
DRIZZLE_QUERY_EXEC_START(session->query,
794
const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
795
/* Actually execute the query */
751
796
mysql_execute_command(session);
755
// Just try to catch any random failures that could have come
759
DRIZZLE_QUERY_EXEC_DONE(0);
797
DRIZZLE_QUERY_EXEC_DONE(0);
765
assert(session->is_error());
768
session->set_proc_info("freeing items");
769
session->end_statement();
770
session->cleanup_after_query();
771
boost::posix_time::ptime end_time=boost::posix_time::microsec_clock::local_time();
772
session->status_var.execution_time_nsec+=(end_time-start_time).total_microseconds();
803
assert(session->is_error());
806
session->set_proc_info("freeing items");
807
session->end_statement();
808
session->cleanup_after_query();
922
961
if (table->is_derived_table() == false && table->db.str)
924
my_casedn_str(files_charset_info, table->db.str);
963
string database_name(table->db.str);
964
NonNormalisedDatabaseName non_normalised_database_name(database_name);
965
NormalisedDatabaseName normalised_database_name(non_normalised_database_name);
926
SchemaIdentifier schema_identifier(string(table->db.str));
927
if (not check_db_name(session, schema_identifier))
967
if (! normalised_database_name.isValid())
930
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
969
my_error(ER_WRONG_DB_NAME, MYF(0), normalised_database_name.to_string().c_str());
973
strncpy(table->db.str, normalised_database_name.to_string().c_str(),
935
977
if (!alias) /* Alias is case sensitive */
946
988
if (!(ptr = (TableList *) session->calloc(sizeof(TableList))))
949
990
if (table->db.str)
951
ptr->setIsFqtn(true);
952
ptr->setSchemaName(table->db.str);
993
ptr->db= table->db.str;
953
994
ptr->db_length= table->db.length;
955
else if (lex->copy_db_to(ptr->getSchemaNamePtr(), &ptr->db_length))
996
else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
958
ptr->setIsFqtn(false);
960
1001
ptr->alias= alias_str;
961
ptr->setIsAlias(alias ? true : false);
962
ptr->setTableName(table->table.str);
1002
ptr->is_alias= alias ? true : false;
1003
if (table->table.length)
1004
table->table.length= my_casedn_str(files_charset_info, table->table.str);
1005
ptr->table_name=table->table.str;
963
1006
ptr->table_name_length=table->table.length;
964
1007
ptr->lock_type= lock_type;
965
ptr->force_index= table_options.test(TL_OPTION_FORCE_INDEX);
966
ptr->ignore_leaves= table_options.test(TL_OPTION_IGNORE_LEAVES);
1008
ptr->updating= test(table_options & TL_OPTION_UPDATING);
1009
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
1010
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
967
1011
ptr->derived= table->sel;
1012
if (!ptr->derived && !my_strcasecmp(system_charset_info, ptr->db,
1013
INFORMATION_SCHEMA_NAME.c_str()))
1015
plugin::InfoSchemaTable *schema_table= plugin::InfoSchemaTable::getTable(ptr->table_name);
1016
if (!schema_table ||
1017
(schema_table->isHidden() &&
1018
((sql_command_flags[lex->sql_command].test(CF_BIT_STATUS_COMMAND)) == 0 ||
1020
this check is used for show columns|keys from I_S hidden table
1022
lex->sql_command == SQLCOM_SHOW_FIELDS ||
1023
lex->sql_command == SQLCOM_SHOW_KEYS)))
1025
my_error(ER_UNKNOWN_TABLE, MYF(0),
1026
ptr->table_name, INFORMATION_SCHEMA_NAME.c_str());
968
1030
ptr->select_lex= lex->current_select;
969
1031
ptr->index_hints= index_hints_arg;
970
1032
ptr->option= option ? option->str : 0;
1046
1108
if (!(ptr= (TableList*) session->calloc(ALIGN_SIZE(sizeof(TableList))+
1047
1109
sizeof(nested_join_st))))
1049
ptr->setNestedJoin(((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList)))));
1050
nested_join= ptr->getNestedJoin();
1111
nested_join= ptr->nested_join=
1112
((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList))));
1051
1114
join_list->push_front(ptr);
1052
ptr->setEmbedding(embedding);
1053
ptr->setJoinList(join_list);
1115
ptr->embedding= embedding;
1116
ptr->join_list= join_list;
1054
1117
ptr->alias= (char*) "(nested_join)";
1055
1118
embedding= ptr;
1056
1119
join_list= &nested_join->join_list;
1081
1144
assert(embedding);
1082
1145
ptr= embedding;
1083
join_list= ptr->getJoinList();
1084
embedding= ptr->getEmbedding();
1085
nested_join= ptr->getNestedJoin();
1146
join_list= ptr->join_list;
1147
embedding= ptr->embedding;
1148
nested_join= ptr->nested_join;
1086
1149
if (nested_join->join_list.elements == 1)
1088
1151
TableList *embedded= nested_join->join_list.head();
1089
1152
join_list->pop();
1090
embedded->setJoinList(join_list);
1091
embedded->setEmbedding(embedding);
1153
embedded->join_list= join_list;
1154
embedded->embedding= embedding;
1092
1155
join_list->push_front(embedded);
1121
1184
List<TableList> *embedded_list;
1123
1186
if (!(ptr= (TableList*) session->calloc(ALIGN_SIZE(sizeof(TableList))+
1124
sizeof(nested_join_st))))
1187
sizeof(nested_join_st))))
1126
ptr->setNestedJoin(((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList)))));
1127
nested_join= ptr->getNestedJoin();
1128
ptr->setEmbedding(embedding);
1129
ptr->setJoinList(join_list);
1189
nested_join= ptr->nested_join=
1190
((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList))));
1192
ptr->embedding= embedding;
1193
ptr->join_list= join_list;
1130
1194
ptr->alias= (char*) "(nest_last_join)";
1131
1195
embedded_list= &nested_join->join_list;
1132
1196
embedded_list->empty();
1488
@param session Thread class
1490
@param only_kill_query Should it kill the query or the connection
1493
This is written such that we have a short lock on LOCK_thread_count
1497
kill_one_thread(Session *, ulong id, bool only_kill_query)
1500
uint32_t error=ER_NO_SUCH_THREAD;
1501
pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
1503
for( vector<Session*>::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
1505
if ((*it)->thread_id == id)
1508
pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete
1512
pthread_mutex_unlock(&LOCK_thread_count);
1515
tmp->awake(only_kill_query ? Session::KILL_QUERY : Session::KILL_CONNECTION);
1517
pthread_mutex_unlock(&tmp->LOCK_delete);
1524
kills a thread and sends response
1528
session Thread class
1530
only_kill_query Should it kill the query or the connection
1533
void sql_kill(Session *session, ulong id, bool only_kill_query)
1536
if (!(error= kill_one_thread(session, id, only_kill_query)))
1539
my_error(error, MYF(0), id);
1418
1544
Check if the select is a simple select (not an union).