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 */
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>
37
35
#include <drizzled/select_send.h>
38
36
#include <drizzled/plugin/client.h>
39
37
#include <drizzled/statement.h>
40
#include <drizzled/statement/alter_table.h>
41
38
#include "drizzled/probes.h"
42
#include "drizzled/session/cache.h"
43
#include "drizzled/global_charset_info.h"
45
#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"
49
#include "drizzled/optimizer/explain_plan.h"
50
#include "drizzled/pthread_globals.h"
51
#include "drizzled/plugin/event_observer.h"
40
#include "drizzled/plugin/registry.h"
56
43
#include <algorithm>
57
#include <boost/date_time.hpp>
58
#include "drizzled/internal/my_sys.h"
45
using namespace drizzled;
60
46
using namespace std;
62
extern int DRIZZLEparse(void *session); // from sql_yacc.cc
68
49
bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
69
static bool parse_sql(Session *session, Lex_input_stream *lip);
70
void mysql_parse(Session *session, const char *inBuf, uint32_t length);
73
52
@defgroup Runtime_Environment Runtime Environment
131
111
sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
132
112
sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
114
sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND;
115
sql_command_flags[SQLCOM_SHOW_DATABASES]= CF_STATUS_COMMAND;
116
sql_command_flags[SQLCOM_SHOW_OPEN_TABLES]= CF_STATUS_COMMAND;
117
sql_command_flags[SQLCOM_SHOW_FIELDS]= CF_STATUS_COMMAND;
118
sql_command_flags[SQLCOM_SHOW_KEYS]= CF_STATUS_COMMAND;
119
sql_command_flags[SQLCOM_SHOW_VARIABLES]= CF_STATUS_COMMAND;
134
120
sql_command_flags[SQLCOM_SHOW_WARNS]= CF_STATUS_COMMAND;
135
121
sql_command_flags[SQLCOM_SHOW_ERRORS]= CF_STATUS_COMMAND;
122
sql_command_flags[SQLCOM_SHOW_ENGINE_STATUS]= CF_STATUS_COMMAND;
123
sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
136
124
sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
137
125
sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
127
sql_command_flags[SQLCOM_SHOW_TABLES]= (CF_STATUS_COMMAND |
128
CF_SHOW_TABLE_COMMAND);
129
sql_command_flags[SQLCOM_SHOW_TABLE_STATUS]= (CF_STATUS_COMMAND |
130
CF_SHOW_TABLE_COMMAND);
140
132
The following admin table operations are allowed
135
sql_command_flags[SQLCOM_OPTIMIZE]= CF_WRITE_LOGS_COMMAND;
143
136
sql_command_flags[SQLCOM_ANALYZE]= CF_WRITE_LOGS_COMMAND;
140
bool is_update_query(enum enum_sql_command command)
142
assert(command >= 0 && command <= SQLCOM_END);
143
return (sql_command_flags[command].test(CF_BIT_CHANGES_DATA));
147
147
Perform one connection-level (COM_XXXX) command.
184
186
/* Increase id and count all other statements. */
186
session->status_var.questions++;
188
statistic_increment(session->status_var.questions, &LOCK_status);
190
192
/* TODO: set session->lex->sql_command to SQLCOM_END here */
192
plugin::Logging::preDo(session);
193
if (unlikely(plugin::EventObserver::beforeStatement(*session)))
195
// We should do something about an error...
194
plugins.logging.pre_do(session);
198
196
session->server_status&=
199
197
~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
200
198
switch (command) {
201
199
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))
202
status_var_increment(session->status_var.com_stat[SQLCOM_CHANGE_DB]);
204
tmp.length= packet_length;
205
if (!mysql_change_db(session, &tmp, false))
215
207
session->my_ok();
221
if (not session->readAndStoreQuery(packet, packet_length))
213
if (! session->readAndStoreQuery(packet, packet_length))
222
214
break; // fatal error is set
223
DRIZZLE_QUERY_START(session->getQueryString()->c_str(),
215
DRIZZLE_QUERY_START(session->query,
224
216
session->thread_id,
225
const_cast<const char *>(session->schema()->c_str()));
217
const_cast<const char *>(session->db ? session->db : ""));
218
const char* end_of_stmt= NULL;
227
mysql_parse(session, session->getQueryString()->c_str(), session->getQueryString()->length());
220
mysql_parse(session, session->query, session->query_length, &end_of_stmt);
309
301
/* Free tables */
310
302
session->close_thread_tables();
312
plugin::Logging::postDo(session);
313
if (unlikely(plugin::EventObserver::afterStatement(*session)))
315
// We should do something about an error...
304
plugins.logging.post_do(session);
318
306
/* Store temp state for processlist */
319
307
session->set_proc_info("cleaning up");
320
308
session->command= COM_SLEEP;
321
session->resetQueryString();
309
memset(session->process_list_info, 0, PROCESS_LIST_WIDTH);
311
session->query_length= 0;
323
313
session->set_proc_info(NULL);
324
session->mem_root->free_root(MYF(memory::KEEP_PREALLOC));
314
session->packet.shrink(session->variables.net_buffer_length); // Reclaim some memory
315
free_root(session->mem_root,MYF(MY_KEEP_PREALLOC));
326
317
if (DRIZZLE_QUERY_DONE_ENABLED() || DRIZZLE_COMMAND_DONE_ENABLED())
361
352
1 out of memory or SHOW commands are not allowed
362
353
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)
356
int prepare_schema_table(Session *session, LEX *lex, Table_ident *table_ident,
357
const string& schema_table_name)
387
359
Select_Lex *schema_select_lex= NULL;
362
if (schema_table_name.compare("TABLES") == 0 ||
363
schema_table_name.compare("TABLE_NAMES") == 0)
367
if (lex->select_lex.db == NULL &&
368
lex->copy_db_to(&lex->select_lex.db, &dummy))
372
schema_select_lex= new Select_Lex();
373
db.str= schema_select_lex->db= lex->select_lex.db;
374
schema_select_lex->table_list.first= NULL;
375
db.length= strlen(db.str);
377
if (check_db_name(&db))
379
my_error(ER_WRONG_DB_NAME, MYF(0), db.str);
383
else if (schema_table_name.compare("COLUMNS") == 0 ||
384
schema_table_name.compare("STATISTICS") == 0)
387
TableList **query_tables_last= lex->query_tables_last;
388
schema_select_lex= new Select_Lex();
389
/* 'parent_lex' is used in init_query() so it must be before it. */
390
schema_select_lex->parent_lex= lex;
391
schema_select_lex->init_query();
392
if (! schema_select_lex->add_table_to_list(session, table_ident, 0, 0, TL_READ))
396
lex->query_tables_last= query_tables_last;
389
399
Select_Lex *select_lex= lex->current_select;
390
400
assert(select_lex);
391
if (_schema_select(session, select_lex, schema_table_name))
401
if (make_schema_select(session, select_lex, schema_table_name))
712
727
@param session Current thread
713
728
@param inBuf Begining of the query text
714
729
@param length Length of the query text
730
@param[out] found_semicolon For multi queries, position of the character of
731
the next query in the query text.
717
void mysql_parse(Session *session, const char *inBuf, uint32_t length)
734
void mysql_parse(Session *session, const char *inBuf, uint32_t length,
735
const char ** found_semicolon)
719
boost::posix_time::ptime start_time=boost::posix_time::microsec_clock::local_time();
720
session->lex->start(session);
739
The purpose of query_cache_send_result_to_client() is to lookup the
740
query in the query cache first, to avoid parsing and executing it.
741
So, the natural implementation would be to:
742
- first, call query_cache_send_result_to_client,
743
- second, if caching failed, initialise the lexical and syntactic parser.
744
The problem is that the query cache depends on a clean initialization
745
of (among others) lex->safe_to_cache_query and session->server_status,
746
which are reset respectively in
748
- mysql_reset_session_for_next_command()
749
So, initializing the lexical analyser *before* using the query cache
750
is required for the cache to work properly.
751
FIXME: cleanup the dependencies in the code to simplify this.
722
754
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);
757
LEX *lex= session->lex;
759
Lex_input_stream lip(session, inBuf, length);
761
bool err= parse_sql(session, &lip);
762
*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 */
767
if (! session->is_error())
770
Binlog logs a string starting from session->query and having length
771
session->query_length; so we set session->query_length correctly (to not
772
log several statements in one event, when we executed only first).
773
We set it to not see the ';' (otherwise it would get into binlog
774
and Query_log_event::print() would give ';;' output).
775
This also helps display only the current query in SHOW
777
Note that we don't need LOCK_thread_count to modify query_length.
779
if (*found_semicolon &&
780
(session->query_length= (ulong)(*found_semicolon - session->query)))
781
session->query_length--;
782
DRIZZLE_QUERY_EXEC_START(session->query,
784
const_cast<const char *>(session->db ? session->db : ""));
785
/* Actually execute the query */
751
786
mysql_execute_command(session);
755
// Just try to catch any random failures that could have come
759
DRIZZLE_QUERY_EXEC_DONE(0);
787
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();
793
assert(session->is_error());
796
session->set_proc_info("freeing items");
797
session->end_statement();
798
session->cleanup_after_query();
843
871
my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
847
875
else if (type_modifier & AUTO_INCREMENT_FLAG)
849
877
my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
854
882
if (on_update_value && type != DRIZZLE_TYPE_TIMESTAMP)
856
884
my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str);
860
888
if (!(new_field= new CreateField()) ||
861
889
new_field->init(session, field_name->str, type, length, decimals, type_modifier,
862
890
default_value, on_update_value, comment, change,
863
891
interval_list, cs, 0, column_format))
866
statement->alter_info.create_list.push_back(new_field);
894
lex->alter_info.create_list.push_back(new_field);
867
895
lex->last_field=new_field;
913
940
return NULL; // End of memory
914
941
alias_str= alias ? alias->str : table->table.str;
915
if (! table_options.test(TL_OPTION_ALIAS) &&
942
if (!test(table_options & TL_OPTION_ALIAS) &&
916
943
check_table_name(table->table.str, table->table.length))
918
945
my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
922
if (table->is_derived_table() == false && table->db.str)
949
if (table->is_derived_table() == false && table->db.str &&
950
check_db_name(&table->db))
924
my_casedn_str(files_charset_info, table->db.str);
926
SchemaIdentifier schema_identifier(string(table->db.str));
927
if (not check_db_name(session, schema_identifier))
930
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
952
my_error(ER_WRONG_DB_NAME, MYF(0), table->db.str);
935
956
if (!alias) /* Alias is case sensitive */
946
967
if (!(ptr = (TableList *) session->calloc(sizeof(TableList))))
949
969
if (table->db.str)
951
ptr->setIsFqtn(true);
952
ptr->setSchemaName(table->db.str);
972
ptr->db= table->db.str;
953
973
ptr->db_length= table->db.length;
955
else if (lex->copy_db_to(ptr->getSchemaNamePtr(), &ptr->db_length))
975
else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
958
ptr->setIsFqtn(false);
960
980
ptr->alias= alias_str;
961
ptr->setIsAlias(alias ? true : false);
962
ptr->setTableName(table->table.str);
981
ptr->is_alias= alias ? true : false;
982
if (table->table.length)
983
table->table.length= my_casedn_str(files_charset_info, table->table.str);
984
ptr->table_name=table->table.str;
963
985
ptr->table_name_length=table->table.length;
964
986
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);
987
ptr->updating= test(table_options & TL_OPTION_UPDATING);
988
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
989
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
967
990
ptr->derived= table->sel;
991
if (!ptr->derived && !my_strcasecmp(system_charset_info, ptr->db,
992
INFORMATION_SCHEMA_NAME.c_str()))
994
plugin::InfoSchemaTable *schema_table= find_schema_table(ptr->table_name);
996
(schema_table->isHidden() &&
997
((sql_command_flags[lex->sql_command].test(CF_BIT_STATUS_COMMAND)) == 0 ||
999
this check is used for show columns|keys from I_S hidden table
1001
lex->sql_command == SQLCOM_SHOW_FIELDS ||
1002
lex->sql_command == SQLCOM_SHOW_KEYS)))
1004
my_error(ER_UNKNOWN_TABLE, MYF(0),
1005
ptr->table_name, INFORMATION_SCHEMA_NAME.c_str());
1008
ptr->schema_table_name= ptr->table_name;
1009
ptr->schema_table= schema_table;
968
1011
ptr->select_lex= lex->current_select;
969
1012
ptr->index_hints= index_hints_arg;
970
1013
ptr->option= option ? option->str : 0;
1046
1089
if (!(ptr= (TableList*) session->calloc(ALIGN_SIZE(sizeof(TableList))+
1047
1090
sizeof(nested_join_st))))
1049
ptr->setNestedJoin(((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList)))));
1050
nested_join= ptr->getNestedJoin();
1092
nested_join= ptr->nested_join=
1093
((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList))));
1051
1095
join_list->push_front(ptr);
1052
ptr->setEmbedding(embedding);
1053
ptr->setJoinList(join_list);
1096
ptr->embedding= embedding;
1097
ptr->join_list= join_list;
1054
1098
ptr->alias= (char*) "(nested_join)";
1055
1099
embedding= ptr;
1056
1100
join_list= &nested_join->join_list;
1081
1125
assert(embedding);
1082
1126
ptr= embedding;
1083
join_list= ptr->getJoinList();
1084
embedding= ptr->getEmbedding();
1085
nested_join= ptr->getNestedJoin();
1127
join_list= ptr->join_list;
1128
embedding= ptr->embedding;
1129
nested_join= ptr->nested_join;
1086
1130
if (nested_join->join_list.elements == 1)
1088
1132
TableList *embedded= nested_join->join_list.head();
1089
1133
join_list->pop();
1090
embedded->setJoinList(join_list);
1091
embedded->setEmbedding(embedding);
1134
embedded->join_list= join_list;
1135
embedded->embedding= embedding;
1092
1136
join_list->push_front(embedded);
1121
1165
List<TableList> *embedded_list;
1123
1167
if (!(ptr= (TableList*) session->calloc(ALIGN_SIZE(sizeof(TableList))+
1124
sizeof(nested_join_st))))
1168
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);
1170
nested_join= ptr->nested_join=
1171
((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList))));
1173
ptr->embedding= embedding;
1174
ptr->join_list= join_list;
1130
1175
ptr->alias= (char*) "(nest_last_join)";
1131
1176
embedded_list= &nested_join->join_list;
1132
1177
embedded_list->empty();
1469
@param session Thread class
1471
@param only_kill_query Should it kill the query or the connection
1474
This is written such that we have a short lock on LOCK_thread_count
1478
kill_one_thread(Session *, ulong id, bool only_kill_query)
1481
uint32_t error=ER_NO_SUCH_THREAD;
1482
pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
1484
for( vector<Session*>::iterator it= session_list.begin(); it != session_list.end(); ++it )
1486
if ((*it)->thread_id == id)
1489
pthread_mutex_lock(&tmp->LOCK_delete); // Lock from delete
1493
pthread_mutex_unlock(&LOCK_thread_count);
1496
tmp->awake(only_kill_query ? Session::KILL_QUERY : Session::KILL_CONNECTION);
1498
pthread_mutex_unlock(&tmp->LOCK_delete);
1505
kills a thread and sends response
1509
session Thread class
1511
only_kill_query Should it kill the query or the connection
1514
void sql_kill(Session *session, ulong id, bool only_kill_query)
1517
if (!(error= kill_one_thread(session, id, only_kill_query)))
1520
my_error(error, MYF(0), id);
1418
1525
Check if the select is a simple select (not an union).
1652
CREATE TABLE query pre-check.
1654
@param session Thread handler
1655
@param tables Global table list
1656
@param create_table Table which will be created
1664
bool create_table_precheck(Session *, TableList *,
1665
TableList *create_table)
1667
bool error= true; // Error message is given
1669
if (create_table && (strcmp(create_table->db, "information_schema") == 0))
1671
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
1545
1682
negate given expression.
1547
1684
@param session thread handler
1791
Check if path does not contain mysql data home directory
1793
test_if_data_home_dir()
1795
conv_home_dir converted data home directory
1796
home_dir_len converted data home directory length
1803
bool test_if_data_home_dir(const char *dir)
1805
char path[FN_REFLEN], conv_path[FN_REFLEN];
1806
uint32_t dir_len, home_dir_len= strlen(drizzle_unpacked_real_data_home);
1811
(void) fn_format(path, dir, "", "",
1812
(MY_RETURN_REAL_PATH|MY_RESOLVE_SYMLINKS));
1813
dir_len= unpack_dirname(conv_path, dir);
1815
if (home_dir_len < dir_len)
1817
if (!my_strnncoll(character_set_filesystem,
1818
(const unsigned char*) conv_path, home_dir_len,
1819
(const unsigned char*) drizzle_unpacked_real_data_home,
1827
extern int DRIZZLEparse(void *session); // from sql_yacc.cc
1654
1831
This is a wrapper of DRIZZLEparse(). All the code should call parse_sql()
1655
1832
instead of DRIZZLEparse().