~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_parse.cc

  • Committer: Brian Aker
  • Date: 2010-09-12 01:42:27 UTC
  • mto: (1759.2.1 build)
  • mto: This revision was merged to the branch mainline in revision 1762.
  • Revision ID: brian@tangent.org-20100912014227-krt6d9z5ohqrokhb
Add two plugins to handle the string and math functions.

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"
48
48
#include "drizzled/plugin/authorization.h"
49
49
#include "drizzled/optimizer/explain_plan.h"
50
50
#include "drizzled/pthread_globals.h"
51
 
#include "drizzled/plugin/event_observer.h"
52
51
 
53
52
#include <limits.h>
54
53
 
55
54
#include <bitset>
56
55
#include <algorithm>
57
 
#include <boost/date_time.hpp>
 
56
 
58
57
#include "drizzled/internal/my_sys.h"
59
58
 
60
59
using namespace std;
170
169
  bool error= 0;
171
170
  Query_id &query_id= Query_id::get_query_id();
172
171
 
173
 
  DRIZZLE_COMMAND_START(session->thread_id, command);
 
172
  DRIZZLE_COMMAND_START(session->thread_id,
 
173
                        command);
174
174
 
175
175
  session->command= command;
176
176
  session->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
190
190
  /* TODO: set session->lex->sql_command to SQLCOM_END here */
191
191
 
192
192
  plugin::Logging::preDo(session);
193
 
  if (unlikely(plugin::EventObserver::beforeStatement(*session)))
194
 
  {
195
 
    // We should do something about an error...
196
 
  }
197
193
 
198
194
  session->server_status&=
199
195
           ~(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED);
218
214
  }
219
215
  case COM_QUERY:
220
216
  {
221
 
    if (not session->readAndStoreQuery(packet, packet_length))
 
217
    if (! session->readAndStoreQuery(packet, packet_length))
222
218
      break;                                    // fatal error is set
223
 
    DRIZZLE_QUERY_START(session->getQueryString()->c_str(),
 
219
    DRIZZLE_QUERY_START(session->query.c_str(),
224
220
                        session->thread_id,
225
 
                        const_cast<const char *>(session->schema()->c_str()));
 
221
                        const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
226
222
 
227
 
    mysql_parse(session, session->getQueryString()->c_str(), session->getQueryString()->length());
 
223
    plugin::QueryRewriter::rewriteQuery(session->db, session->query);
 
224
    mysql_parse(session, session->query.c_str(), session->query.length());
228
225
 
229
226
    break;
230
227
  }
269
266
    if (! session->main_da.is_set())
270
267
      session->send_kill_message();
271
268
  }
272
 
  if (session->getKilled() == Session::KILL_QUERY || session->getKilled() == Session::KILL_BAD_DATA)
 
269
  if (session->killed == Session::KILL_QUERY || session->killed == Session::KILL_BAD_DATA)
273
270
  {
274
 
    session->setKilled(Session::NOT_KILLED);
 
271
    session->killed= Session::NOT_KILLED;
275
272
    session->setAbort(false);
276
273
  }
277
274
 
310
307
  session->close_thread_tables();
311
308
 
312
309
  plugin::Logging::postDo(session);
313
 
  if (unlikely(plugin::EventObserver::afterStatement(*session)))
314
 
  {
315
 
    // We should do something about an error...
316
 
  }
317
310
 
318
311
  /* Store temp state for processlist */
319
312
  session->set_proc_info("cleaning up");
320
313
  session->command= COM_SLEEP;
321
 
  session->resetQueryString();
 
314
  memset(session->process_list_info, 0, PROCESS_LIST_WIDTH);
 
315
  session->query.clear();
322
316
 
323
317
  session->set_proc_info(NULL);
324
318
  session->mem_root->free_root(MYF(memory::KEEP_PREALLOC));
365
359
                           const string& schema_table_name)
366
360
{
367
361
  LEX_STRING db, table;
368
 
  bitset<NUM_OF_TABLE_OPTIONS> table_options;
369
362
  /*
370
363
     We have to make non const db_name & table_name
371
364
     because of lower_case_table_names
374
367
  session->make_lex_string(&table, schema_table_name, false);
375
368
 
376
369
  if (! sel->add_table_to_list(session, new Table_ident(db, table),
377
 
                               NULL, table_options, TL_READ))
 
370
                               NULL, 0, TL_READ))
378
371
  {
379
372
    return true;
380
373
  }
429
422
    true        Error
430
423
*/
431
424
 
432
 
static int mysql_execute_command(Session *session)
 
425
static int
 
426
mysql_execute_command(Session *session)
433
427
{
434
428
  bool res= false;
435
429
  LEX  *lex= session->lex;
437
431
  Select_Lex *select_lex= &lex->select_lex;
438
432
  /* list of all tables in query */
439
433
  TableList *all_tables;
 
434
  /* 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();
 
437
 
 
438
  memcpy(session->process_list_info, session->query.c_str(), proc_info_len);
 
439
  session->process_list_info[proc_info_len]= '\0';
440
440
 
441
441
  /*
442
442
    In many cases first table of main Select_Lex have special meaning =>
716
716
 
717
717
void mysql_parse(Session *session, const char *inBuf, uint32_t length)
718
718
{
719
 
  boost::posix_time::ptime start_time=boost::posix_time::microsec_clock::local_time();
720
 
  session->lex->start(session);
721
 
 
 
719
  uint64_t start_time= my_getsystime();
 
720
  lex_start(session);
722
721
  session->reset_for_next_command();
723
722
  /* Check if the Query is Cached if and return true if yes
724
723
   * TODO the plugin has to make sure that the query is cacheble
739
738
  if (!err)
740
739
  {
741
740
    {
742
 
      if (not session->is_error())
 
741
      if (! session->is_error())
743
742
      {
744
 
        DRIZZLE_QUERY_EXEC_START(session->getQueryString()->c_str(),
 
743
        DRIZZLE_QUERY_EXEC_START(session->query.c_str(),
745
744
                                 session->thread_id,
746
 
                                 const_cast<const char *>(session->schema()->c_str()));
 
745
                                 const_cast<const char *>(session->db.empty() ? "" : session->db.c_str()));
747
746
        // Implement Views here --Brian
748
747
        /* Actually execute the query */
749
748
        try 
754
753
        {
755
754
          // Just try to catch any random failures that could have come
756
755
          // during execution.
757
 
          unireg_abort(1);
758
756
        }
759
757
        DRIZZLE_QUERY_EXEC_DONE(0);
760
758
      }
768
766
  session->set_proc_info("freeing items");
769
767
  session->end_statement();
770
768
  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();
 
769
  session->status_var.execution_time_nsec+= my_getsystime() - start_time;
773
770
}
774
771
 
775
772
 
897
894
*/
898
895
 
899
896
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)
 
897
                                             Table_ident *table,
 
898
                                             LEX_STRING *alias,
 
899
                                             uint32_t table_options,
 
900
                                             thr_lock_type lock_type,
 
901
                                             List<Index_hint> *index_hints_arg,
 
902
                                             LEX_STRING *option)
906
903
{
907
 
  TableList *ptr;
 
904
  register TableList *ptr;
908
905
  TableList *previous_table_ref; /* The table preceding the current one. */
909
906
  char *alias_str;
910
907
  LEX *lex= session->lex;
912
909
  if (!table)
913
910
    return NULL;                                // End of memory
914
911
  alias_str= alias ? alias->str : table->table.str;
915
 
  if (! table_options.test(TL_OPTION_ALIAS) &&
 
912
  if (!test(table_options & TL_OPTION_ALIAS) &&
916
913
      check_table_name(table->table.str, table->table.length))
917
914
  {
918
915
    my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
949
946
  if (table->db.str)
950
947
  {
951
948
    ptr->setIsFqtn(true);
952
 
    ptr->setSchemaName(table->db.str);
 
949
    ptr->db= table->db.str;
953
950
    ptr->db_length= table->db.length;
954
951
  }
955
 
  else if (lex->copy_db_to(ptr->getSchemaNamePtr(), &ptr->db_length))
 
952
  else if (lex->copy_db_to(&ptr->db, &ptr->db_length))
956
953
    return NULL;
957
954
  else
958
955
    ptr->setIsFqtn(false);
959
956
 
960
957
  ptr->alias= alias_str;
961
958
  ptr->setIsAlias(alias ? true : false);
962
 
  ptr->setTableName(table->table.str);
 
959
  if (table->table.length)
 
960
    table->table.length= my_casedn_str(files_charset_info, table->table.str);
 
961
  ptr->table_name=table->table.str;
963
962
  ptr->table_name_length=table->table.length;
964
963
  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);
 
964
  ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
 
965
  ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
967
966
  ptr->derived=     table->sel;
968
967
  ptr->select_lex=  lex->current_select;
969
968
  ptr->index_hints= index_hints_arg;
977
976
         tables=tables->next_local)
978
977
    {
979
978
      if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
980
 
          !strcasecmp(ptr->getSchemaName(), tables->getSchemaName()))
 
979
          !strcasecmp(ptr->db, tables->db))
981
980
      {
982
981
        my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str);
983
982
        return NULL;
1415
1414
 
1416
1415
 
1417
1416
/**
 
1417
  kill on thread.
 
1418
 
 
1419
  @param session                        Thread class
 
1420
  @param id                     Thread id
 
1421
  @param only_kill_query        Should it kill the query or the connection
 
1422
 
 
1423
  @note
 
1424
    This is written such that we have a short lock on LOCK_thread_count
 
1425
*/
 
1426
 
 
1427
static unsigned int
 
1428
kill_one_thread(Session *, ulong id, bool only_kill_query)
 
1429
{
 
1430
  Session *tmp= NULL;
 
1431
  uint32_t error= ER_NO_SUCH_THREAD;
 
1432
  LOCK_thread_count.lock(); // For unlink from list
 
1433
  
 
1434
  for (SessionList::iterator it= getSessionList().begin(); it != getSessionList().end(); ++it )
 
1435
  {
 
1436
    if ((*it)->thread_id == id)
 
1437
    {
 
1438
      tmp= *it;
 
1439
      tmp->lockForDelete();
 
1440
      break;
 
1441
    }
 
1442
  }
 
1443
  LOCK_thread_count.unlock();
 
1444
  if (tmp)
 
1445
  {
 
1446
 
 
1447
    if (tmp->isViewable())
 
1448
    {
 
1449
      tmp->awake(only_kill_query ? Session::KILL_QUERY : Session::KILL_CONNECTION);
 
1450
      error= 0;
 
1451
    }
 
1452
 
 
1453
    tmp->unlockForDelete();
 
1454
  }
 
1455
  return(error);
 
1456
}
 
1457
 
 
1458
 
 
1459
/*
 
1460
  kills a thread and sends response
 
1461
 
 
1462
  SYNOPSIS
 
1463
    sql_kill()
 
1464
    session                     Thread class
 
1465
    id                  Thread id
 
1466
    only_kill_query     Should it kill the query or the connection
 
1467
*/
 
1468
 
 
1469
void sql_kill(Session *session, ulong id, bool only_kill_query)
 
1470
{
 
1471
  uint32_t error;
 
1472
  if (!(error= kill_one_thread(session, id, only_kill_query)))
 
1473
    session->my_ok();
 
1474
  else
 
1475
    my_error(error, MYF(0), id);
 
1476
}
 
1477
 
 
1478
 
 
1479
/**
1418
1480
  Check if the select is a simple select (not an union).
1419
1481
 
1420
1482
  @retval
1542
1604
 
1543
1605
 
1544
1606
/**
 
1607
  CREATE TABLE query pre-check.
 
1608
 
 
1609
  @param session                        Thread handler
 
1610
  @param tables         Global table list
 
1611
  @param create_table           Table which will be created
 
1612
 
 
1613
  @retval
 
1614
    false   OK
 
1615
  @retval
 
1616
    true   Error
 
1617
*/
 
1618
 
 
1619
bool create_table_precheck(TableIdentifier &identifier)
 
1620
{
 
1621
  if (not plugin::StorageEngine::canCreateTable(identifier))
 
1622
  {
 
1623
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", identifier.getSchemaName().c_str());
 
1624
    return true;
 
1625
  }
 
1626
 
 
1627
  if (not plugin::StorageEngine::doesSchemaExist(identifier))
 
1628
  {
 
1629
    my_error(ER_BAD_DB_ERROR, MYF(0), identifier.getSchemaName().c_str());
 
1630
    return true;
 
1631
  }
 
1632
 
 
1633
  return false;
 
1634
}
 
1635
 
 
1636
 
 
1637
/**
1545
1638
  negate given expression.
1546
1639
 
1547
1640
  @param session  thread handler
1666
1759
{
1667
1760
  assert(session->m_lip == NULL);
1668
1761
 
1669
 
  DRIZZLE_QUERY_PARSE_START(session->getQueryString()->c_str());
 
1762
  DRIZZLE_QUERY_PARSE_START(session->query.c_str());
1670
1763
 
1671
1764
  /* Set Lex_input_stream. */
1672
1765