~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_parse.cc

Merge Padraig

Show diffs side-by-side

added added

removed removed

Lines of Context:
26
26
#include <drizzled/sql_base.h>
27
27
#include <drizzled/show.h>
28
28
#include <drizzled/info_schema.h>
29
 
#include <drizzled/rename.h>
30
29
#include <drizzled/function/time/unix_timestamp.h>
31
30
#include <drizzled/function/get_system_var.h>
32
31
#include <drizzled/item/cmpfunc.h>
423
422
static int
424
423
mysql_execute_command(Session *session)
425
424
{
426
 
  int res= false;
427
 
  bool comm_not_executed= false;
428
 
  bool need_start_waiting= false; // have protection against global read lock
 
425
  bool res= false;
429
426
  LEX  *lex= session->lex;
430
427
  /* first Select_Lex (have special meaning for many of non-SELECTcommands) */
431
428
  Select_Lex *select_lex= &lex->select_lex;
432
 
  /* first table of first Select_Lex */
433
 
  TableList *first_table= (TableList*) select_lex->table_list.first;
434
429
  /* list of all tables in query */
435
430
  TableList *all_tables;
436
 
  /* most outer Select_Lex_Unit of query */
437
 
  Select_Lex_Unit *unit= &lex->unit;
438
431
  /* A peek into the query string */
439
432
  size_t proc_info_len= session->query_length > PROCESS_LIST_WIDTH ?
440
433
                        PROCESS_LIST_WIDTH : session->query_length;
472
465
    variables, but for now this is probably good enough.
473
466
    Don't reset warnings when executing a stored routine.
474
467
  */
475
 
  if (all_tables || !lex->is_single_level_stmt())
 
468
  if (all_tables || ! lex->is_single_level_stmt())
 
469
  {
476
470
    drizzle_reset_errors(session, 0);
 
471
  }
477
472
 
478
473
  status_var_increment(session->status_var.com_stat[lex->sql_command]);
479
474
 
480
475
  assert(session->transaction.stmt.modified_non_trans_table == false);
481
476
 
482
 
 
483
 
  switch (lex->sql_command) {
484
 
  case SQLCOM_CREATE_TABLE:
485
 
  {
486
 
    /* If CREATE TABLE of non-temporary table, do implicit commit */
487
 
    if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
488
 
    {
489
 
      if (! session->endActiveTransaction())
490
 
      {
491
 
        res= -1;
492
 
        break;
493
 
      }
494
 
    }
495
 
    assert(first_table == all_tables && first_table != 0);
496
 
    bool link_to_local;
497
 
    // Skip first table, which is the table we are creating
498
 
    TableList *create_table= lex->unlink_first_table(&link_to_local);
499
 
    TableList *select_tables= lex->query_tables;
500
 
    /*
501
 
      Code below (especially in mysql_create_table() and select_create
502
 
      methods) may modify HA_CREATE_INFO structure in LEX, so we have to
503
 
      use a copy of this structure to make execution prepared statement-
504
 
      safe. A shallow copy is enough as this code won't modify any memory
505
 
      referenced from this structure.
506
 
    */
507
 
    HA_CREATE_INFO create_info(lex->create_info);
508
 
    /*
509
 
      We need to copy alter_info for the same reasons of re-execution
510
 
      safety, only in case of Alter_info we have to do (almost) a deep
511
 
      copy.
512
 
    */
513
 
    Alter_info alter_info(lex->alter_info, session->mem_root);
514
 
 
515
 
    if (session->is_fatal_error)
516
 
    {
517
 
      /* If out of memory when creating a copy of alter_info. */
518
 
      res= 1;
519
 
      goto end_with_restore_list;
520
 
    }
521
 
 
522
 
    if ((res= create_table_precheck(session, select_tables, create_table)))
523
 
      goto end_with_restore_list;
524
 
 
525
 
    /* Might have been updated in create_table_precheck */
526
 
    create_info.alias= create_table->alias;
527
 
 
528
 
    /*
529
 
      The create-select command will open and read-lock the select table
530
 
      and then create, open and write-lock the new table. If a global
531
 
      read lock steps in, we get a deadlock. The write lock waits for
532
 
      the global read lock, while the global read lock waits for the
533
 
      select table to be closed. So we wait until the global readlock is
534
 
      gone before starting both steps. Note that
535
 
      wait_if_global_read_lock() sets a protection against a new global
536
 
      read lock when it succeeds. This needs to be released by
537
 
      start_waiting_global_read_lock(). We protect the normal CREATE
538
 
      TABLE in the same way. That way we avoid that a new table is
539
 
      created during a gobal read lock.
540
 
    */
541
 
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
542
 
    {
543
 
      res= 1;
544
 
      goto end_with_restore_list;
545
 
    }
546
 
    if (select_lex->item_list.elements)         // With select
547
 
    {
548
 
      select_result *result;
549
 
 
550
 
      select_lex->options|= SELECT_NO_UNLOCK;
551
 
      unit->set_limit(select_lex);
552
 
 
553
 
      if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
554
 
      {
555
 
        lex->link_first_table_back(create_table, link_to_local);
556
 
        create_table->create= true;
557
 
      }
558
 
 
559
 
      if (!(res= session->openTablesLock(lex->query_tables)))
560
 
      {
561
 
        /*
562
 
          Is table which we are changing used somewhere in other parts
563
 
          of query
564
 
        */
565
 
        if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
566
 
        {
567
 
          TableList *duplicate;
568
 
          create_table= lex->unlink_first_table(&link_to_local);
569
 
          if ((duplicate= unique_table(session, create_table, select_tables, 0)))
570
 
          {
571
 
            my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
572
 
            res= 1;
573
 
            goto end_with_restore_list;
574
 
          }
575
 
        }
576
 
 
577
 
        /*
578
 
          select_create is currently not re-execution friendly and
579
 
          needs to be created for every execution of a PS/SP.
580
 
        */
581
 
        if ((result= new select_create(create_table,
582
 
                                       &create_info,
583
 
                                       lex->create_table_proto,
584
 
                                       &alter_info,
585
 
                                       select_lex->item_list,
586
 
                                       lex->duplicates,
587
 
                                       lex->ignore,
588
 
                                       select_tables)))
589
 
        {
590
 
          /*
591
 
            CREATE from SELECT give its Select_Lex for SELECT,
592
 
            and item_list belong to SELECT
593
 
          */
594
 
          res= handle_select(session, lex, result, 0);
595
 
          delete result;
596
 
        }
597
 
      }
598
 
      else if (!(create_info.options & HA_LEX_CREATE_TMP_TABLE))
599
 
        create_table= lex->unlink_first_table(&link_to_local);
600
 
 
601
 
    }
602
 
    else
603
 
    {
604
 
      /* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
605
 
      if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
606
 
        session->options|= OPTION_KEEP_LOG;
607
 
      /* regular create */
608
 
      if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
609
 
        res= mysql_create_like_table(session, create_table, select_tables,
610
 
                                     &create_info);
611
 
      else
612
 
      {
613
 
        res= mysql_create_table(session, create_table->db,
614
 
                                create_table->table_name, &create_info,
615
 
                                lex->create_table_proto,
616
 
                                &alter_info, 0, 0);
617
 
      }
618
 
      if (!res)
619
 
        session->my_ok();
620
 
    }
621
 
 
622
 
    /* put tables back for PS rexecuting */
623
 
end_with_restore_list:
624
 
    lex->link_first_table_back(create_table, link_to_local);
625
 
    break;
626
 
  }
627
 
  case SQLCOM_CREATE_INDEX:
628
 
    /* Fall through */
629
 
  case SQLCOM_DROP_INDEX:
630
 
  /*
631
 
    CREATE INDEX and DROP INDEX are implemented by calling ALTER
632
 
    TABLE with proper arguments.
633
 
 
634
 
    In the future ALTER TABLE will notice that the request is to
635
 
    only add indexes and create these one by one for the existing
636
 
    table without having to do a full rebuild.
637
 
  */
638
 
  {
639
 
    /* Prepare stack copies to be re-execution safe */
640
 
    HA_CREATE_INFO create_info;
641
 
    Alter_info alter_info(lex->alter_info, session->mem_root);
642
 
 
643
 
    if (session->is_fatal_error) /* out of memory creating a copy of alter_info */
644
 
      goto error;
645
 
 
646
 
    assert(first_table == all_tables && first_table != 0);
647
 
    if (! session->endActiveTransaction())
648
 
      goto error;
649
 
 
650
 
    memset(&create_info, 0, sizeof(create_info));
651
 
    create_info.db_type= 0;
652
 
    create_info.row_type= ROW_TYPE_NOT_USED;
653
 
    create_info.default_table_charset= get_default_db_collation(session->db);
654
 
 
655
 
    res= mysql_alter_table(session, first_table->db, first_table->table_name,
656
 
                           &create_info, lex->create_table_proto, first_table,
657
 
                           &alter_info,
658
 
                           0, (order_st*) 0, 0);
659
 
    break;
660
 
  }
661
 
  case SQLCOM_ALTER_TABLE:
662
 
    assert(first_table == all_tables && first_table != 0);
663
 
    {
664
 
      /*
665
 
        Code in mysql_alter_table() may modify its HA_CREATE_INFO argument,
666
 
        so we have to use a copy of this structure to make execution
667
 
        prepared statement- safe. A shallow copy is enough as no memory
668
 
        referenced from this structure will be modified.
669
 
      */
670
 
      HA_CREATE_INFO create_info(lex->create_info);
671
 
      Alter_info alter_info(lex->alter_info, session->mem_root);
672
 
 
673
 
      if (session->is_fatal_error) /* out of memory creating a copy of alter_info */
674
 
      {
675
 
        goto error;
676
 
      }
677
 
 
678
 
      /* Must be set in the parser */
679
 
      assert(select_lex->db);
680
 
 
681
 
      { // Rename of table
682
 
          TableList tmp_table;
683
 
          memset(&tmp_table, 0, sizeof(tmp_table));
684
 
          tmp_table.table_name= lex->name.str;
685
 
          tmp_table.db=select_lex->db;
686
 
      }
687
 
 
688
 
      /* ALTER TABLE ends previous transaction */
689
 
      if (! session->endActiveTransaction())
690
 
        goto error;
691
 
 
692
 
      if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
693
 
      {
694
 
        res= 1;
695
 
        break;
696
 
      }
697
 
 
698
 
      res= mysql_alter_table(session, select_lex->db, lex->name.str,
699
 
                             &create_info,
700
 
                             lex->create_table_proto,
701
 
                             first_table,
702
 
                             &alter_info,
703
 
                             select_lex->order_list.elements,
704
 
                             (order_st *) select_lex->order_list.first,
705
 
                             lex->ignore);
706
 
      break;
707
 
    }
708
 
  case SQLCOM_RENAME_TABLE:
709
 
  {
710
 
    assert(first_table == all_tables && first_table != 0);
711
 
    TableList *table;
712
 
    for (table= first_table; table; table= table->next_local->next_local)
713
 
    {
714
 
      TableList old_list, new_list;
715
 
      /*
716
 
        we do not need initialize old_list and new_list because we will
717
 
        come table[0] and table->next[0] there
718
 
      */
719
 
      old_list= table[0];
720
 
      new_list= table->next_local[0];
721
 
    }
722
 
 
723
 
    if (! session->endActiveTransaction() || drizzle_rename_tables(session, first_table))
724
 
    {
725
 
      goto error;
726
 
    }
727
 
    break;
728
 
  }
729
 
  case SQLCOM_REPLACE:
730
 
  case SQLCOM_INSERT:
731
 
  {
732
 
    assert(first_table == all_tables && first_table != 0);
733
 
    if ((res= insert_precheck(session, all_tables)))
734
 
      break;
735
 
 
736
 
    if (!(need_start_waiting= !wait_if_global_read_lock(session, 0, 1)))
737
 
    {
738
 
      res= 1;
739
 
      break;
740
 
    }
741
 
 
742
 
    res= mysql_insert(session, all_tables, lex->field_list, lex->many_values,
743
 
                      lex->update_list, lex->value_list,
744
 
                      lex->duplicates, lex->ignore);
745
 
 
746
 
    break;
747
 
  }
748
 
  case SQLCOM_REPLACE_SELECT:
749
 
  case SQLCOM_INSERT_SELECT:
750
 
  {
751
 
    select_result *sel_result;
752
 
    assert(first_table == all_tables && first_table != 0);
753
 
    if ((res= insert_precheck(session, all_tables)))
754
 
      break;
755
 
 
756
 
    /* Don't unlock tables until command is written to binary log */
757
 
    select_lex->options|= SELECT_NO_UNLOCK;
758
 
 
759
 
    unit->set_limit(select_lex);
760
 
 
761
 
    if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
762
 
    {
763
 
      res= 1;
764
 
      break;
765
 
    }
766
 
 
767
 
    if (!(res= session->openTablesLock(all_tables)))
768
 
    {
769
 
      /* Skip first table, which is the table we are inserting in */
770
 
      TableList *second_table= first_table->next_local;
771
 
      select_lex->table_list.first= (unsigned char*) second_table;
772
 
      select_lex->context.table_list=
773
 
        select_lex->context.first_name_resolution_table= second_table;
774
 
      res= mysql_insert_select_prepare(session);
775
 
      if (!res && (sel_result= new select_insert(first_table,
776
 
                                                 first_table->table,
777
 
                                                 &lex->field_list,
778
 
                                                 &lex->update_list,
779
 
                                                 &lex->value_list,
780
 
                                                 lex->duplicates,
781
 
                                                 lex->ignore)))
782
 
      {
783
 
        res= handle_select(session, lex, sel_result, OPTION_SETUP_TABLES_DONE);
784
 
        /*
785
 
          Invalidate the table in the query cache if something changed
786
 
          after unlocking when changes become visible.
787
 
          TODO: this is workaround. right way will be move invalidating in
788
 
          the unlock procedure.
789
 
        */
790
 
        if (first_table->lock_type ==  TL_WRITE_CONCURRENT_INSERT &&
791
 
            session->lock)
792
 
        {
793
 
          /* INSERT ... SELECT should invalidate only the very first table */
794
 
          TableList *save_table= first_table->next_local;
795
 
          first_table->next_local= 0;
796
 
          first_table->next_local= save_table;
797
 
        }
798
 
        delete sel_result;
799
 
      }
800
 
      /* revert changes for SP */
801
 
      select_lex->table_list.first= (unsigned char*) first_table;
802
 
    }
803
 
 
804
 
    break;
805
 
  }
806
 
  case SQLCOM_BEGIN:
807
 
    if (session->transaction.xid_state.xa_state != XA_NOTR)
808
 
    {
809
 
      my_error(ER_XAER_RMFAIL, MYF(0),
810
 
               xa_state_names[session->transaction.xid_state.xa_state]);
811
 
      break;
812
 
    }
813
 
    /*
814
 
      Breakpoints for backup testing.
815
 
    */
816
 
    if (! session->startTransaction())
817
 
      goto error;
818
 
    session->my_ok();
819
 
    break;
820
 
  case SQLCOM_RELEASE_SAVEPOINT:
821
 
  {
822
 
    SAVEPOINT *sv;
823
 
    for (sv=session->transaction.savepoints; sv; sv=sv->prev)
824
 
    {
825
 
      if (my_strnncoll(system_charset_info,
826
 
                       (unsigned char *)lex->ident.str, lex->ident.length,
827
 
                       (unsigned char *)sv->name, sv->length) == 0)
828
 
        break;
829
 
    }
830
 
    if (sv)
831
 
    {
832
 
      if (ha_release_savepoint(session, sv))
833
 
        res= true; // cannot happen
834
 
      else
835
 
        session->my_ok();
836
 
      session->transaction.savepoints=sv->prev;
837
 
    }
838
 
    else
839
 
      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
840
 
    break;
841
 
  }
842
 
  case SQLCOM_ROLLBACK_TO_SAVEPOINT:
843
 
  {
844
 
    SAVEPOINT *sv;
845
 
    for (sv=session->transaction.savepoints; sv; sv=sv->prev)
846
 
    {
847
 
      if (my_strnncoll(system_charset_info,
848
 
                       (unsigned char *)lex->ident.str, lex->ident.length,
849
 
                       (unsigned char *)sv->name, sv->length) == 0)
850
 
        break;
851
 
    }
852
 
    if (sv)
853
 
    {
854
 
      if (ha_rollback_to_savepoint(session, sv))
855
 
        res= true; // cannot happen
856
 
      else
857
 
      {
858
 
        if ((session->options & OPTION_KEEP_LOG) || session->transaction.all.modified_non_trans_table)
859
 
          push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
860
 
                       ER_WARNING_NOT_COMPLETE_ROLLBACK,
861
 
                       ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
862
 
        session->my_ok();
863
 
      }
864
 
      session->transaction.savepoints=sv;
865
 
    }
866
 
    else
867
 
      my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "SAVEPOINT", lex->ident.str);
868
 
    break;
869
 
  }
870
 
  case SQLCOM_SAVEPOINT:
871
 
    if (!(session->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
872
 
      session->my_ok();
873
 
    else
874
 
    {
875
 
      SAVEPOINT **sv, *newsv;
876
 
      for (sv=&session->transaction.savepoints; *sv; sv=&(*sv)->prev)
877
 
      {
878
 
        if (my_strnncoll(system_charset_info,
879
 
                         (unsigned char *)lex->ident.str, lex->ident.length,
880
 
                         (unsigned char *)(*sv)->name, (*sv)->length) == 0)
881
 
          break;
882
 
      }
883
 
      if (*sv) /* old savepoint of the same name exists */
884
 
      {
885
 
        newsv=*sv;
886
 
        ha_release_savepoint(session, *sv); // it cannot fail
887
 
        *sv=(*sv)->prev;
888
 
      }
889
 
      else if ((newsv=(SAVEPOINT *) alloc_root(&session->transaction.mem_root,
890
 
                                               savepoint_alloc_size)) == 0)
891
 
      {
892
 
        my_error(ER_OUT_OF_RESOURCES, MYF(0));
893
 
        break;
894
 
      }
895
 
      newsv->name=strmake_root(&session->transaction.mem_root,
896
 
                               lex->ident.str, lex->ident.length);
897
 
      newsv->length=lex->ident.length;
898
 
      /*
899
 
        if we'll get an error here, don't add new savepoint to the list.
900
 
        we'll lose a little bit of memory in transaction mem_root, but it'll
901
 
        be free'd when transaction ends anyway
902
 
      */
903
 
      if (ha_savepoint(session, newsv))
904
 
        res= true;
905
 
      else
906
 
      {
907
 
        newsv->prev=session->transaction.savepoints;
908
 
        session->transaction.savepoints=newsv;
909
 
        session->my_ok();
910
 
      }
911
 
    }
912
 
    break;
913
 
  default:
914
 
    /*
915
 
     * This occurs now because we have extracted some commands in
916
 
     * to their own classes and thus there is no matching case
917
 
     * label in this switch statement for those commands. Pretty soon
918
 
     * this entire switch statement will be gone along with this 
919
 
     * comment...
920
 
     */
921
 
    comm_not_executed= true;
922
 
    break;
923
 
  }
924
 
  /*
925
 
   * The following conditional statement is only temporary until
926
 
   * the mongo switch statement that occurs above has been
927
 
   * fully removed. Once that switch statement is gone, every
928
 
   * command will have its own class and we won't need this
929
 
   * check.
930
 
   */
931
 
  if (comm_not_executed)
932
 
  {
933
 
    /* now we are ready to execute the statement */
934
 
    res= lex->statement->execute();
935
 
  }
 
477
  /* now we are ready to execute the statement */
 
478
  res= lex->statement->execute();
936
479
 
937
480
  session->set_proc_info("query end");
938
481
 
947
490
    session->row_count_func= -1;
948
491
  }
949
492
 
950
 
  goto finish;
951
 
 
952
 
error:
953
 
  res= true;
954
 
 
955
 
finish:
956
 
  if (need_start_waiting)
957
 
  {
958
 
    /*
959
 
      Release the protection against the global read lock and wake
960
 
      everyone, who might want to set a global read lock.
961
 
    */
962
 
    start_waiting_global_read_lock(session);
963
 
  }
964
 
  return(res || session->is_error());
 
493
  return (res || session->is_error());
965
494
}
966
495
 
967
496
bool execute_sqlcom_select(Session *session, TableList *all_tables)