~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_parse.cc

  • Committer: Paweł Blokus
  • Date: 2010-06-09 20:36:51 UTC
  • mto: This revision was merged to the branch mainline in revision 1620.
  • Revision ID: pawel@pawel-desktop-20100609203651-mbq5x34bt9m3kv0o
minor style fixes

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
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 */
15
15
 
16
16
#include "config.h"
17
17
 
39
39
#include <drizzled/statement.h>
40
40
#include <drizzled/statement/alter_table.h>
41
41
#include "drizzled/probes.h"
42
 
#include "drizzled/session/cache.h"
 
42
#include "drizzled/session_list.h"
43
43
#include "drizzled/global_charset_info.h"
44
44
 
45
45
#include "drizzled/plugin/logging.h"
46
46
#include "drizzled/plugin/query_rewrite.h"
47
 
#include "drizzled/plugin/query_cache.h"
48
47
#include "drizzled/plugin/authorization.h"
49
48
#include "drizzled/optimizer/explain_plan.h"
50
49
#include "drizzled/pthread_globals.h"
51
 
#include "drizzled/plugin/event_observer.h"
52
50
 
53
51
#include <limits.h>
54
52
 
55
53
#include <bitset>
56
54
#include <algorithm>
57
 
#include <boost/date_time.hpp>
 
55
 
58
56
#include "drizzled/internal/my_sys.h"
59
57
 
60
58
using namespace std;
170
168
  bool error= 0;
171
169
  Query_id &query_id= Query_id::get_query_id();
172
170
 
173
 
  DRIZZLE_COMMAND_START(session->thread_id, command);
 
171
  DRIZZLE_COMMAND_START(session->thread_id,
 
172
                        command);
174
173
 
175
174
  session->command= command;
176
175
  session->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
183
182
    break;
184
183
  /* Increase id and count all other statements. */
185
184
  default:
186
 
    session->status_var.questions++;
 
185
    statistic_increment(session->status_var.questions, &LOCK_status);
187
186
    query_id.next();
188
187
  }
189
188
 
190
189
  /* TODO: set session->lex->sql_command to SQLCOM_END here */
191
190
 
192
191
  plugin::Logging::preDo(session);
193
 
  if (unlikely(plugin::EventObserver::beforeStatement(*session)))
194
 
  {
195
 
    // We should do something about an error...
196
 
  }
197
192
 
198
193
  session->server_status&=
199
194
           ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
218
213
  }
219
214
  case COM_QUERY:
220
215
  {
221
 
    if (not session->readAndStoreQuery(packet, packet_length))
 
216
    if (! session->readAndStoreQuery(packet, packet_length))
222
217
      break;                                    // fatal error is set
223
 
    DRIZZLE_QUERY_START(session->getQueryString()->c_str(),
 
218
    DRIZZLE_QUERY_START(session->query.c_str(),
224
219
                        session->thread_id,
225
 
                        const_cast<const char *>(session->schema()->c_str()));
 
220
                        const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
226
221
 
227
 
    mysql_parse(session, session->getQueryString()->c_str(), session->getQueryString()->length());
 
222
    plugin::QueryRewriter::rewriteQuery(session->db, session->query);
 
223
    mysql_parse(session, session->query.c_str(), session->query.length());
228
224
 
229
225
    break;
230
226
  }
235
231
    break;
236
232
  case COM_SHUTDOWN:
237
233
  {
238
 
    session->status_var.com_other++;
 
234
    status_var_increment(session->status_var.com_other);
239
235
    session->my_eof();
240
236
    session->close_thread_tables();                     // Free before kill
241
237
    kill_drizzle();
243
239
    break;
244
240
  }
245
241
  case COM_PING:
246
 
    session->status_var.com_other++;
 
242
    status_var_increment(session->status_var.com_other);
247
243
    session->my_ok();                           // Tell client we are alive
248
244
    break;
249
245
  case COM_SLEEP:
269
265
    if (! session->main_da.is_set())
270
266
      session->send_kill_message();
271
267
  }
272
 
  if (session->getKilled() == Session::KILL_QUERY || session->getKilled() == Session::KILL_BAD_DATA)
 
268
  if (session->killed == Session::KILL_QUERY || session->killed == Session::KILL_BAD_DATA)
273
269
  {
274
 
    session->setKilled(Session::NOT_KILLED);
275
 
    session->setAbort(false);
 
270
    session->killed= Session::NOT_KILLED;
 
271
    session->mysys_var->abort= 0;
276
272
  }
277
273
 
278
274
  /* Can not be true, but do not take chances in production. */
310
306
  session->close_thread_tables();
311
307
 
312
308
  plugin::Logging::postDo(session);
313
 
  if (unlikely(plugin::EventObserver::afterStatement(*session)))
314
 
  {
315
 
    // We should do something about an error...
316
 
  }
317
309
 
318
310
  /* Store temp state for processlist */
319
311
  session->set_proc_info("cleaning up");
320
312
  session->command= COM_SLEEP;
321
 
  session->resetQueryString();
 
313
  memset(session->process_list_info, 0, PROCESS_LIST_WIDTH);
 
314
  session->query.clear();
322
315
 
323
316
  session->set_proc_info(NULL);
324
317
  session->mem_root->free_root(MYF(memory::KEEP_PREALLOC));
365
358
                           const string& schema_table_name)
366
359
{
367
360
  LEX_STRING db, table;
368
 
  bitset<NUM_OF_TABLE_OPTIONS> table_options;
369
361
  /*
370
362
     We have to make non const db_name & table_name
371
363
     because of lower_case_table_names
374
366
  session->make_lex_string(&table, schema_table_name, false);
375
367
 
376
368
  if (! sel->add_table_to_list(session, new Table_ident(db, table),
377
 
                               NULL, table_options, TL_READ))
 
369
                               NULL, 0, TL_READ))
378
370
  {
379
371
    return true;
380
372
  }
429
421
    true        Error
430
422
*/
431
423
 
432
 
static int mysql_execute_command(Session *session)
 
424
static int
 
425
mysql_execute_command(Session *session)
433
426
{
434
427
  bool res= false;
435
428
  LEX  *lex= session->lex;
437
430
  Select_Lex *select_lex= &lex->select_lex;
438
431
  /* list of all tables in query */
439
432
  TableList *all_tables;
 
433
  /* A peek into the query string */
 
434
  size_t proc_info_len= session->query.length() > PROCESS_LIST_WIDTH ?
 
435
                        PROCESS_LIST_WIDTH : session->query.length();
 
436
 
 
437
  memcpy(session->process_list_info, session->query.c_str(), proc_info_len);
 
438
  session->process_list_info[proc_info_len]= '\0';
440
439
 
441
440
  /*
442
441
    In many cases first table of main Select_Lex have special meaning =>
477
476
 
478
477
  /* now we are ready to execute the statement */
479
478
  res= lex->statement->execute();
 
479
 
480
480
  session->set_proc_info("query end");
 
481
 
481
482
  /*
482
483
    The return value for ROW_COUNT() is "implementation dependent" if the
483
484
    statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC
491
492
 
492
493
  return (res || session->is_error());
493
494
}
 
495
 
494
496
bool execute_sqlcom_select(Session *session, TableList *all_tables)
495
497
{
496
498
  LEX   *lex= session->lex;
538
540
    {
539
541
      if (!result && !(result= new select_send()))
540
542
        return true;
541
 
 
542
 
      /* Init the Query Cache plugin */
543
 
      plugin::QueryCache::prepareResultset(session); 
544
543
      res= handle_select(session, lex, result, 0);
545
 
      /* Send the Resultset to the cache */
546
 
      plugin::QueryCache::setResultset(session); 
547
 
 
548
544
      if (result != lex->result)
549
545
        delete result;
550
546
    }
716
712
 
717
713
void mysql_parse(Session *session, const char *inBuf, uint32_t length)
718
714
{
719
 
  boost::posix_time::ptime start_time=boost::posix_time::microsec_clock::local_time();
720
 
  session->lex->start(session);
721
 
 
 
715
  lex_start(session);
722
716
  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
726
 
   */
727
 
  bool res= true;
728
 
  if (plugin::QueryCache::isCached(session))
729
 
  {
730
 
    res= plugin::QueryCache::sendCachedResultset(session);
731
 
  }
732
 
  if (not res)
733
 
  {
734
 
    return;
735
 
  }
 
717
 
736
718
  LEX *lex= session->lex;
 
719
 
737
720
  Lex_input_stream lip(session, inBuf, length);
 
721
 
738
722
  bool err= parse_sql(session, &lip);
 
723
 
739
724
  if (!err)
740
725
  {
741
726
    {
742
 
      if (not session->is_error())
 
727
      if (! session->is_error())
743
728
      {
744
 
        DRIZZLE_QUERY_EXEC_START(session->getQueryString()->c_str(),
 
729
        DRIZZLE_QUERY_EXEC_START(session->query.c_str(),
745
730
                                 session->thread_id,
746
 
                                 const_cast<const char *>(session->schema()->c_str()));
747
 
        // Implement Views here --Brian
 
731
                                 const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
748
732
        /* Actually execute the query */
749
 
        try 
750
 
        {
751
 
          mysql_execute_command(session);
752
 
        }
753
 
        catch (...)
754
 
        {
755
 
          // Just try to catch any random failures that could have come
756
 
          // during execution.
757
 
          unireg_abort(1);
758
 
        }
 
733
        mysql_execute_command(session);
759
734
        DRIZZLE_QUERY_EXEC_DONE(0);
760
735
      }
761
736
    }
764
739
  {
765
740
    assert(session->is_error());
766
741
  }
 
742
 
767
743
  lex->unit.cleanup();
768
744
  session->set_proc_info("freeing items");
769
745
  session->end_statement();
770
746
  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();
 
747
 
 
748
  return;
773
749
}
774
750
 
775
751
 
897
873
*/
898
874
 
899
875
TableList *Select_Lex::add_table_to_list(Session *session,
900
 
                                                             Table_ident *table,
901
 
                                                             LEX_STRING *alias,
902
 
                                                             const bitset<NUM_OF_TABLE_OPTIONS>& table_options,
903
 
                                                             thr_lock_type lock_type,
904
 
                                                             List<Index_hint> *index_hints_arg,
905
 
                                         LEX_STRING *option)
 
876
                                             Table_ident *table,
 
877
                                             LEX_STRING *alias,
 
878
                                             uint32_t table_options,
 
879
                                             thr_lock_type lock_type,
 
880
                                             List<Index_hint> *index_hints_arg,
 
881
                                             LEX_STRING *option)
906
882
{
907
 
  TableList *ptr;
 
883
  register TableList *ptr;
908
884
  TableList *previous_table_ref; /* The table preceding the current one. */
909
885
  char *alias_str;
910
886
  LEX *lex= session->lex;
912
888
  if (!table)
913
889
    return NULL;                                // End of memory
914
890
  alias_str= alias ? alias->str : table->table.str;
915
 
  if (! table_options.test(TL_OPTION_ALIAS) &&
 
891
  if (!test(table_options & TL_OPTION_ALIAS) &&
916
892
      check_table_name(table->table.str, table->table.length))
917
893
  {
918
894
    my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
945
921
  }
946
922
  if (!(ptr = (TableList *) session->calloc(sizeof(TableList))))
947
923
    return NULL;
948
 
 
949
924
  if (table->db.str)
950
925
  {
951
 
    ptr->setIsFqtn(true);
952
 
    ptr->setSchemaName(table->db.str);
 
926
    ptr->is_fqtn= true;
 
927
    ptr->db= table->db.str;
953
928
    ptr->db_length= table->db.length;
954
929
  }
955
 
  else if (lex->copy_db_to(ptr->getSchemaNamePtr(), &ptr->db_length))
 
930
  else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
956
931
    return NULL;
957
932
  else
958
 
    ptr->setIsFqtn(false);
 
933
    ptr->is_fqtn= false;
959
934
 
960
935
  ptr->alias= alias_str;
961
 
  ptr->setIsAlias(alias ? true : false);
962
 
  ptr->setTableName(table->table.str);
 
936
  ptr->is_alias= alias ? true : false;
 
937
  if (table->table.length)
 
938
    table->table.length= my_casedn_str(files_charset_info, table->table.str);
 
939
  ptr->table_name=table->table.str;
963
940
  ptr->table_name_length=table->table.length;
964
941
  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);
 
942
  ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
 
943
  ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
967
944
  ptr->derived=     table->sel;
968
945
  ptr->select_lex=  lex->current_select;
969
946
  ptr->index_hints= index_hints_arg;
977
954
         tables=tables->next_local)
978
955
    {
979
956
      if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
980
 
          !strcasecmp(ptr->getSchemaName(), tables->getSchemaName()))
 
957
          !strcasecmp(ptr->db, tables->db))
981
958
      {
982
959
        my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str);
983
960
        return NULL;
1046
1023
  if (!(ptr= (TableList*) session->calloc(ALIGN_SIZE(sizeof(TableList))+
1047
1024
                                       sizeof(nested_join_st))))
1048
1025
    return true;
1049
 
  ptr->setNestedJoin(((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList)))));
1050
 
  nested_join= ptr->getNestedJoin();
 
1026
  nested_join= ptr->nested_join=
 
1027
    ((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList))));
 
1028
 
1051
1029
  join_list->push_front(ptr);
1052
 
  ptr->setEmbedding(embedding);
1053
 
  ptr->setJoinList(join_list);
 
1030
  ptr->embedding= embedding;
 
1031
  ptr->join_list= join_list;
1054
1032
  ptr->alias= (char*) "(nested_join)";
1055
1033
  embedding= ptr;
1056
1034
  join_list= &nested_join->join_list;
1080
1058
 
1081
1059
  assert(embedding);
1082
1060
  ptr= embedding;
1083
 
  join_list= ptr->getJoinList();
1084
 
  embedding= ptr->getEmbedding();
1085
 
  nested_join= ptr->getNestedJoin();
 
1061
  join_list= ptr->join_list;
 
1062
  embedding= ptr->embedding;
 
1063
  nested_join= ptr->nested_join;
1086
1064
  if (nested_join->join_list.elements == 1)
1087
1065
  {
1088
1066
    TableList *embedded= nested_join->join_list.head();
1089
1067
    join_list->pop();
1090
 
    embedded->setJoinList(join_list);
1091
 
    embedded->setEmbedding(embedding);
 
1068
    embedded->join_list= join_list;
 
1069
    embedded->embedding= embedding;
1092
1070
    join_list->push_front(embedded);
1093
1071
    ptr= embedded;
1094
1072
  }
1121
1099
  List<TableList> *embedded_list;
1122
1100
 
1123
1101
  if (!(ptr= (TableList*) session->calloc(ALIGN_SIZE(sizeof(TableList))+
1124
 
                                          sizeof(nested_join_st))))
 
1102
                                       sizeof(nested_join_st))))
1125
1103
    return NULL;
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);
 
1104
  nested_join= ptr->nested_join=
 
1105
    ((nested_join_st*) ((unsigned char*) ptr + ALIGN_SIZE(sizeof(TableList))));
 
1106
 
 
1107
  ptr->embedding= embedding;
 
1108
  ptr->join_list= join_list;
1130
1109
  ptr->alias= (char*) "(nest_last_join)";
1131
1110
  embedded_list= &nested_join->join_list;
1132
1111
  embedded_list->empty();
1134
1113
  for (uint32_t i=0; i < 2; i++)
1135
1114
  {
1136
1115
    TableList *table= join_list->pop();
1137
 
    table->setJoinList(embedded_list);
1138
 
    table->setEmbedding(ptr);
 
1116
    table->join_list= embedded_list;
 
1117
    table->embedding= ptr;
1139
1118
    embedded_list->push_back(table);
1140
1119
    if (table->natural_join)
1141
1120
    {
1171
1150
void Select_Lex::add_joined_table(TableList *table)
1172
1151
{
1173
1152
  join_list->push_front(table);
1174
 
  table->setJoinList(join_list);
1175
 
  table->setEmbedding(embedding);
 
1153
  table->join_list= join_list;
 
1154
  table->embedding= embedding;
1176
1155
}
1177
1156
 
1178
1157
 
1415
1394
 
1416
1395
 
1417
1396
/**
 
1397
  kill on thread.
 
1398
 
 
1399
  @param session                        Thread class
 
1400
  @param id                     Thread id
 
1401
  @param only_kill_query        Should it kill the query or the connection
 
1402
 
 
1403
  @note
 
1404
    This is written such that we have a short lock on LOCK_thread_count
 
1405
*/
 
1406
 
 
1407
static unsigned int
 
1408
kill_one_thread(Session *, ulong id, bool only_kill_query)
 
1409
{
 
1410
  Session *tmp= NULL;
 
1411
  uint32_t error= ER_NO_SUCH_THREAD;
 
1412
  pthread_mutex_lock(&LOCK_thread_count); // For unlink from list
 
1413
  
 
1414
  for (SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
1415
  {
 
1416
    if ((*it)->thread_id == id)
 
1417
    {
 
1418
      tmp= *it;
 
1419
      pthread_mutex_lock(&tmp->LOCK_delete);    // Lock from delete
 
1420
      break;
 
1421
    }
 
1422
  }
 
1423
  pthread_mutex_unlock(&LOCK_thread_count);
 
1424
  if (tmp)
 
1425
  {
 
1426
 
 
1427
    if (tmp->isViewable())
 
1428
    {
 
1429
      tmp->awake(only_kill_query ? Session::KILL_QUERY : Session::KILL_CONNECTION);
 
1430
      error= 0;
 
1431
    }
 
1432
 
 
1433
    pthread_mutex_unlock(&tmp->LOCK_delete);
 
1434
  }
 
1435
  return(error);
 
1436
}
 
1437
 
 
1438
 
 
1439
/*
 
1440
  kills a thread and sends response
 
1441
 
 
1442
  SYNOPSIS
 
1443
    sql_kill()
 
1444
    session                     Thread class
 
1445
    id                  Thread id
 
1446
    only_kill_query     Should it kill the query or the connection
 
1447
*/
 
1448
 
 
1449
void sql_kill(Session *session, ulong id, bool only_kill_query)
 
1450
{
 
1451
  uint32_t error;
 
1452
  if (!(error= kill_one_thread(session, id, only_kill_query)))
 
1453
    session->my_ok();
 
1454
  else
 
1455
    my_error(error, MYF(0), id);
 
1456
}
 
1457
 
 
1458
 
 
1459
/**
1418
1460
  Check if the select is a simple select (not an union).
1419
1461
 
1420
1462
  @retval
1542
1584
 
1543
1585
 
1544
1586
/**
 
1587
  CREATE TABLE query pre-check.
 
1588
 
 
1589
  @param session                        Thread handler
 
1590
  @param tables         Global table list
 
1591
  @param create_table           Table which will be created
 
1592
 
 
1593
  @retval
 
1594
    false   OK
 
1595
  @retval
 
1596
    true   Error
 
1597
*/
 
1598
 
 
1599
bool create_table_precheck(TableIdentifier &identifier)
 
1600
{
 
1601
  if (not plugin::StorageEngine::canCreateTable(identifier))
 
1602
  {
 
1603
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", identifier.getSchemaName().c_str());
 
1604
    return true;
 
1605
  }
 
1606
 
 
1607
  if (not plugin::StorageEngine::doesSchemaExist(identifier))
 
1608
  {
 
1609
    my_error(ER_BAD_DB_ERROR, MYF(0), identifier.getSchemaName().c_str());
 
1610
    return true;
 
1611
  }
 
1612
 
 
1613
  return false;
 
1614
}
 
1615
 
 
1616
 
 
1617
/**
1545
1618
  negate given expression.
1546
1619
 
1547
1620
  @param session  thread handler
1666
1739
{
1667
1740
  assert(session->m_lip == NULL);
1668
1741
 
1669
 
  DRIZZLE_QUERY_PARSE_START(session->getQueryString()->c_str());
 
1742
  DRIZZLE_QUERY_PARSE_START(session->query.c_str());
1670
1743
 
1671
1744
  /* Set Lex_input_stream. */
1672
1745