~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_parse.cc

Extracted the LOAD command into its own class and implementation files.
Removed the corresponding case label from the switch statement.

Show diffs side-by-side

added added

removed removed

Lines of Context:
36
36
#include <drizzled/connect.h>
37
37
#include <drizzled/lock.h>
38
38
#include <drizzled/select_send.h>
39
 
#include <drizzled/statement.h>
 
39
#include <drizzled/command.h>
40
40
 
41
41
#include <bitset>
42
42
#include <algorithm>
46
46
/* Prototypes */
47
47
static bool append_file_to_dir(Session *session, const char **filename_ptr,
48
48
                               const char *table_name);
49
 
static bool reload_cache(Session *session, ulong options, TableList *tables);
50
49
 
51
50
bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
52
51
 
107
106
  sql_command_flags[SQLCOM_DROP_INDEX]=     CF_CHANGES_DATA;
108
107
 
109
108
  sql_command_flags[SQLCOM_UPDATE]=         CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
 
109
  sql_command_flags[SQLCOM_UPDATE_MULTI]=   CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
110
110
  sql_command_flags[SQLCOM_INSERT]=         CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
111
111
  sql_command_flags[SQLCOM_INSERT_SELECT]=  CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
112
112
  sql_command_flags[SQLCOM_DELETE]=         CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
 
113
  sql_command_flags[SQLCOM_DELETE_MULTI]=   CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
113
114
  sql_command_flags[SQLCOM_REPLACE]=        CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
114
115
  sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_HAS_ROW_COUNT;
115
116
 
569
570
        create_table->create= true;
570
571
      }
571
572
 
572
 
      if (!(res= session->openTablesLock(lex->query_tables)))
 
573
      if (!(res= session->open_and_lock_tables(lex->query_tables)))
573
574
      {
574
575
        /*
575
576
          Is table which we are changing used somewhere in other parts
789
790
                      unit->select_limit_cnt,
790
791
                      lex->duplicates, lex->ignore);
791
792
    break;
 
793
  case SQLCOM_UPDATE_MULTI:
 
794
  {
 
795
    assert(first_table == all_tables && first_table != 0);
 
796
    if ((res= update_precheck(session, all_tables)))
 
797
      break;
 
798
 
 
799
    if ((res= mysql_multi_update_prepare(session)))
 
800
      break;
 
801
 
 
802
    res= mysql_multi_update(session, all_tables,
 
803
                            &select_lex->item_list,
 
804
                            &lex->value_list,
 
805
                            select_lex->where,
 
806
                            select_lex->options,
 
807
                            lex->duplicates, lex->ignore, unit, select_lex);
 
808
    break;
 
809
  }
792
810
  case SQLCOM_REPLACE:
793
811
  case SQLCOM_INSERT:
794
812
  {
827
845
      break;
828
846
    }
829
847
 
830
 
    if (!(res= session->openTablesLock(all_tables)))
 
848
    if (!(res= session->open_and_lock_tables(all_tables)))
831
849
    {
832
850
      /* Skip first table, which is the table we are inserting in */
833
851
      TableList *second_table= first_table->next_local;
886
904
    res= mysql_truncate(session, first_table, 0);
887
905
 
888
906
    break;
 
907
  case SQLCOM_DELETE:
 
908
  {
 
909
    assert(first_table == all_tables && first_table != 0);
 
910
    assert(select_lex->offset_limit == 0);
 
911
    unit->set_limit(select_lex);
 
912
 
 
913
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
914
    {
 
915
      res= 1;
 
916
      break;
 
917
    }
 
918
 
 
919
    res = mysql_delete(session, all_tables, select_lex->where,
 
920
                       &select_lex->order_list,
 
921
                       unit->select_limit_cnt, select_lex->options,
 
922
                       false);
 
923
    break;
 
924
  }
 
925
  case SQLCOM_DELETE_MULTI:
 
926
  {
 
927
    assert(first_table == all_tables && first_table != 0);
 
928
    TableList *aux_tables=
 
929
      (TableList *)session->lex->auxiliary_table_list.first;
 
930
    multi_delete *del_result;
 
931
 
 
932
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
 
933
    {
 
934
      res= 1;
 
935
      break;
 
936
    }
 
937
 
 
938
    if ((res= multi_delete_precheck(session, all_tables)))
 
939
      break;
 
940
 
 
941
    /* condition will be true on SP re-excuting */
 
942
    if (select_lex->item_list.elements != 0)
 
943
      select_lex->item_list.empty();
 
944
    if (session->add_item_to_list(new Item_null()))
 
945
      goto error;
 
946
 
 
947
    session->set_proc_info("init");
 
948
    if ((res= session->open_and_lock_tables(all_tables)))
 
949
      break;
 
950
 
 
951
    if ((res= mysql_multi_delete_prepare(session)))
 
952
      goto error;
 
953
 
 
954
    if (!session->is_fatal_error &&
 
955
        (del_result= new multi_delete(aux_tables, lex->table_count)))
 
956
    {
 
957
      res= mysql_select(session, &select_lex->ref_pointer_array,
 
958
                        select_lex->get_table_list(),
 
959
                        select_lex->with_wild,
 
960
                        select_lex->item_list,
 
961
                        select_lex->where,
 
962
                        0, (order_st *)NULL, (order_st *)NULL, (Item *)NULL,
 
963
                        select_lex->options | session->options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK | OPTION_SETUP_TABLES_DONE,
 
964
                        del_result, unit, select_lex);
 
965
      res|= session->is_error();
 
966
      if (res)
 
967
        del_result->abort();
 
968
      delete del_result;
 
969
    }
 
970
    else
 
971
      res= true;                                // Error
 
972
    break;
 
973
  }
889
974
  case SQLCOM_DROP_TABLE:
890
975
  {
891
976
    assert(first_table == all_tables && first_table != 0);
916
1001
  {
917
1002
    List<set_var_base> *lex_var_list= &lex->var_list;
918
1003
 
919
 
    if (session->openTablesLock(all_tables))
 
1004
    if (session->open_and_lock_tables(all_tables))
920
1005
      goto error;
921
1006
    if (!(res= sql_set_variables(session, lex_var_list)))
922
1007
    {
1068
1153
      goto error;
1069
1154
    session->my_ok();
1070
1155
    break;
 
1156
  case SQLCOM_COMMIT:
 
1157
    if (! session->endTransaction(lex->tx_release ? COMMIT_RELEASE : lex->tx_chain ? COMMIT_AND_CHAIN : COMMIT))
 
1158
      goto error;
 
1159
    session->my_ok();
 
1160
    break;
 
1161
  case SQLCOM_ROLLBACK:
 
1162
    if (! session->endTransaction(lex->tx_release ? ROLLBACK_RELEASE : lex->tx_chain ? ROLLBACK_AND_CHAIN : ROLLBACK))
 
1163
      goto error;
 
1164
    session->my_ok();
 
1165
    break;
1071
1166
  case SQLCOM_RELEASE_SAVEPOINT:
1072
1167
  {
1073
1168
    SAVEPOINT *sv;
1181
1276
   */
1182
1277
  if (comm_not_executed)
1183
1278
  {
1184
 
    /* now we are ready to execute the statement */
1185
 
    res= lex->statement->execute();
 
1279
    /* now we are ready to execute the command */
 
1280
    res= lex->command->execute();
1186
1281
  }
1187
1282
 
1188
1283
  session->set_proc_info("query end");
1225
1320
      param->select_limit=
1226
1321
        new Item_int((uint64_t) session->variables.select_limit);
1227
1322
  }
1228
 
  if (!(res= session->openTablesLock(all_tables)))
 
1323
  if (!(res= session->open_and_lock_tables(all_tables)))
1229
1324
  {
1230
1325
    if (lex->describe)
1231
1326
    {
1421
1516
}
1422
1517
 
1423
1518
 
 
1519
void mysql_init_multi_delete(LEX *lex)
 
1520
{
 
1521
  lex->sql_command=  SQLCOM_DELETE_MULTI;
 
1522
  mysql_init_select(lex);
 
1523
  lex->select_lex.select_limit= 0;
 
1524
  lex->unit.select_limit_cnt= HA_POS_ERROR;
 
1525
  lex->select_lex.table_list.save_and_clear(&lex->auxiliary_table_list);
 
1526
  lex->lock_option= TL_READ;
 
1527
  lex->query_tables= 0;
 
1528
  lex->query_tables_last= &lex->query_tables;
 
1529
}
 
1530
 
 
1531
 
1424
1532
/**
1425
1533
  Parse a query.
1426
1534
 
1601
1709
}
1602
1710
 
1603
1711
/**
 
1712
  save order by and tables in own lists.
 
1713
*/
 
1714
 
 
1715
bool add_to_list(Session *session, SQL_LIST &list,Item *item,bool asc)
 
1716
{
 
1717
  order_st *order;
 
1718
  if (!(order = (order_st *) session->alloc(sizeof(order_st))))
 
1719
    return(1);
 
1720
  order->item_ptr= item;
 
1721
  order->item= &order->item_ptr;
 
1722
  order->asc = asc;
 
1723
  order->free_me=0;
 
1724
  order->used=0;
 
1725
  order->counter_used= 0;
 
1726
  list.link_in_list((unsigned char*) order,(unsigned char**) &order->next);
 
1727
  return(0);
 
1728
}
 
1729
 
 
1730
 
 
1731
/**
1604
1732
  Add a table to list of used tables.
1605
1733
 
1606
1734
  @param table          Table to add
2178
2306
    @retval !=0  Error; session->killed is set or session->is_error() is true
2179
2307
*/
2180
2308
 
2181
 
static bool reload_cache(Session *session, ulong options, TableList *tables)
 
2309
bool reload_cache(Session *session, ulong options, TableList *tables)
2182
2310
{
2183
2311
  bool result=0;
2184
2312
 
2197
2325
    {
2198
2326
      if (lock_global_read_lock(session))
2199
2327
        return true;                               // Killed
2200
 
      result= session->close_cached_tables(tables, (options & REFRESH_FAST) ?  false : true, true);
 
2328
      result= close_cached_tables(session, tables, (options & REFRESH_FAST) ?
 
2329
                                  false : true, true);
2201
2330
      if (make_global_read_lock_block_commit(session)) // Killed
2202
2331
      {
2203
2332
        /* Don't leave things in a half-locked state */
2207
2336
      }
2208
2337
    }
2209
2338
    else
2210
 
      result= session->close_cached_tables(tables, (options & REFRESH_FAST) ?  false : true, false);
 
2339
      result= close_cached_tables(session, tables, (options & REFRESH_FAST) ?
 
2340
                                  false : true, false);
2211
2341
  }
2212
2342
  if (session && (options & REFRESH_STATUS))
2213
2343
    session->refresh_status();
2398
2528
  return(false);
2399
2529
}
2400
2530
 
 
2531
/**
 
2532
  Multi delete query pre-check.
 
2533
 
 
2534
  @param session                        Thread handler
 
2535
  @param tables         Global/local table list
 
2536
 
 
2537
  @retval
 
2538
    false OK
 
2539
  @retval
 
2540
    true  error
 
2541
*/
 
2542
 
 
2543
bool multi_delete_precheck(Session *session, TableList *)
 
2544
{
 
2545
  Select_Lex *select_lex= &session->lex->select_lex;
 
2546
  TableList **save_query_tables_own_last= session->lex->query_tables_own_last;
 
2547
 
 
2548
  session->lex->query_tables_own_last= 0;
 
2549
  session->lex->query_tables_own_last= save_query_tables_own_last;
 
2550
 
 
2551
  if ((session->options & OPTION_SAFE_UPDATES) && !select_lex->where)
 
2552
  {
 
2553
    my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
 
2554
               ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
 
2555
    return(true);
 
2556
  }
 
2557
  return(false);
 
2558
}
 
2559
 
 
2560
 
 
2561
/*
 
2562
  Given a table in the source list, find a correspondent table in the
 
2563
  table references list.
 
2564
 
 
2565
  @param lex Pointer to LEX representing multi-delete.
 
2566
  @param src Source table to match.
 
2567
  @param ref Table references list.
 
2568
 
 
2569
  @remark The source table list (tables listed before the FROM clause
 
2570
  or tables listed in the FROM clause before the USING clause) may
 
2571
  contain table names or aliases that must match unambiguously one,
 
2572
  and only one, table in the target table list (table references list,
 
2573
  after FROM/USING clause).
 
2574
 
 
2575
  @return Matching table, NULL otherwise.
 
2576
*/
 
2577
 
 
2578
static TableList *multi_delete_table_match(LEX *, TableList *tbl,
 
2579
                                           TableList *tables)
 
2580
{
 
2581
  TableList *match= NULL;
 
2582
 
 
2583
  for (TableList *elem= tables; elem; elem= elem->next_local)
 
2584
  {
 
2585
    int cmp;
 
2586
 
 
2587
    if (tbl->is_fqtn && elem->is_alias)
 
2588
      continue; /* no match */
 
2589
    if (tbl->is_fqtn && elem->is_fqtn)
 
2590
      cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
 
2591
           strcmp(tbl->db, elem->db);
 
2592
    else if (elem->is_alias)
 
2593
      cmp= my_strcasecmp(table_alias_charset, tbl->alias, elem->alias);
 
2594
    else
 
2595
      cmp= my_strcasecmp(table_alias_charset, tbl->table_name, elem->table_name) ||
 
2596
           strcmp(tbl->db, elem->db);
 
2597
 
 
2598
    if (cmp)
 
2599
      continue;
 
2600
 
 
2601
    if (match)
 
2602
    {
 
2603
      my_error(ER_NONUNIQ_TABLE, MYF(0), elem->alias);
 
2604
      return NULL;
 
2605
    }
 
2606
 
 
2607
    match= elem;
 
2608
  }
 
2609
 
 
2610
  if (!match)
 
2611
    my_error(ER_UNKNOWN_TABLE, MYF(0), tbl->table_name, "MULTI DELETE");
 
2612
 
 
2613
  return(match);
 
2614
}
 
2615
 
 
2616
 
 
2617
/**
 
2618
  Link tables in auxilary table list of multi-delete with corresponding
 
2619
  elements in main table list, and set proper locks for them.
 
2620
 
 
2621
  @param lex   pointer to LEX representing multi-delete
 
2622
 
 
2623
  @retval
 
2624
    false   success
 
2625
  @retval
 
2626
    true    error
 
2627
*/
 
2628
 
 
2629
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
 
2630
{
 
2631
  TableList *tables= (TableList*)lex->select_lex.table_list.first;
 
2632
  TableList *target_tbl;
 
2633
 
 
2634
  lex->table_count= 0;
 
2635
 
 
2636
  for (target_tbl= (TableList *)lex->auxiliary_table_list.first;
 
2637
       target_tbl; target_tbl= target_tbl->next_local)
 
2638
  {
 
2639
    lex->table_count++;
 
2640
    /* All tables in aux_tables must be found in FROM PART */
 
2641
    TableList *walk= multi_delete_table_match(lex, target_tbl, tables);
 
2642
    if (!walk)
 
2643
      return(true);
 
2644
    if (!walk->derived)
 
2645
    {
 
2646
      target_tbl->table_name= walk->table_name;
 
2647
      target_tbl->table_name_length= walk->table_name_length;
 
2648
    }
 
2649
    walk->updating= target_tbl->updating;
 
2650
    walk->lock_type= target_tbl->lock_type;
 
2651
    target_tbl->correspondent_table= walk;      // Remember corresponding table
 
2652
  }
 
2653
  return(false);
 
2654
}
 
2655
 
2401
2656
 
2402
2657
/**
2403
2658
  simple INSERT query pre-check.