~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_base.cc

  • Committer: Brian Aker
  • Date: 2010-12-17 00:08:06 UTC
  • mfrom: (2002.1.4 clean)
  • Revision ID: brian@tangent.org-20101217000806-fa6kmggjnhsl4q85
Rollup for field encapsulation, monty fix for bzrignore, and Andrew bug
fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
/* Basic functions needed by many modules */
18
 
#include <config.h>
 
18
#include "config.h"
19
19
#include <assert.h>
20
20
 
21
21
#include <signal.h>
30
30
#  include <time.h>
31
31
# endif
32
32
#endif
33
 
#include <drizzled/internal/my_pthread.h>
34
 
#include <drizzled/internal/thread_var.h>
 
33
#include "drizzled/internal/my_pthread.h"
 
34
#include "drizzled/internal/thread_var.h"
35
35
 
36
36
#include <drizzled/sql_select.h>
37
37
#include <drizzled/error.h>
44
44
#include <drizzled/check_stack_overrun.h>
45
45
#include <drizzled/lock.h>
46
46
#include <drizzled/plugin/listen.h>
47
 
#include <drizzled/cached_directory.h>
48
 
#include <drizzled/field/epoch.h>
 
47
#include "drizzled/cached_directory.h"
 
48
#include <drizzled/field/timestamp.h>
49
49
#include <drizzled/field/null.h>
50
 
#include <drizzled/sql_table.h>
51
 
#include <drizzled/global_charset_info.h>
52
 
#include <drizzled/pthread_globals.h>
53
 
#include <drizzled/internal/iocache.h>
54
 
#include <drizzled/drizzled.h>
55
 
#include <drizzled/plugin/authorization.h>
56
 
#include <drizzled/table/temporary.h>
57
 
#include <drizzled/table/placeholder.h>
58
 
#include <drizzled/table/unused.h>
59
 
#include <drizzled/plugin/storage_engine.h>
60
 
#include <drizzled/session.h>
61
 
 
62
 
#include <drizzled/refresh_version.h>
 
50
#include "drizzled/sql_table.h"
 
51
#include "drizzled/global_charset_info.h"
 
52
#include "drizzled/pthread_globals.h"
 
53
#include "drizzled/internal/iocache.h"
 
54
#include "drizzled/drizzled.h"
 
55
#include "drizzled/plugin/authorization.h"
 
56
#include "drizzled/table/temporary.h"
 
57
#include "drizzled/table/placeholder.h"
 
58
#include "drizzled/table/unused.h"
63
59
 
64
60
using namespace std;
65
61
 
114
110
    This has to be done to ensure that the table share is removed from
115
111
    the table defintion cache as soon as the last instance is removed
116
112
  */
117
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), message::Table::INTERNAL);
118
 
  const identifier::Table::Key &key(identifier.getKey());
 
113
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName(), message::Table::INTERNAL);
 
114
  const TableIdentifier::Key &key(identifier.getKey());
119
115
  TableShare *share= new TableShare(identifier.getType(),
120
116
                                    identifier,
121
117
                                    const_cast<char *>(key.vector()),  static_cast<uint32_t>(table->getShare()->getCacheKeySize()));
122
118
 
123
119
  table->cursor->close();
124
120
  table->db_stat= 0;                            // Mark cursor closed
125
 
  table::instance::release(table->getMutableShare());
 
121
  TableShare::release(table->getMutableShare());
126
122
  table->setShare(share);
127
123
}
128
124
 
148
144
  if (sort.io_cache)
149
145
  {
150
146
    sort.io_cache->close_cached_file();
151
 
    safe_delete(sort.io_cache);
 
147
    delete sort.io_cache;
 
148
    sort.io_cache= 0;
152
149
  }
153
150
}
154
151
 
174
171
  Session *session= this;
175
172
 
176
173
  {
177
 
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* Optionally lock for remove tables from open_cahe if not in use */
 
174
    table::Cache::singleton().mutex().lock(); /* Optionally lock for remove tables from open_cahe if not in use */
178
175
 
179
176
    if (tables == NULL)
180
177
    {
236
233
      bool found= false;
237
234
      for (TableList *table= tables; table; table= table->next_local)
238
235
      {
239
 
        identifier::Table identifier(table->getSchemaName(), table->getTableName());
 
236
        TableIdentifier identifier(table->getSchemaName(), table->getTableName());
240
237
        if (table::Cache::singleton().removeTable(session, identifier,
241
238
                                    RTFC_OWNED_BY_Session_FLAG))
242
239
        {
290
287
                                                     (table->open_placeholder && wait_for_placeholders)))
291
288
          {
292
289
            found= true;
293
 
            COND_refresh.wait(scopedLock);
 
290
            boost_unique_lock_t scoped(table::Cache::singleton().mutex(), boost::adopt_lock_t());
 
291
            COND_refresh.wait(scoped);
 
292
            scoped.release();
294
293
            break;
295
294
          }
296
295
        }
300
299
        old locks. This should always succeed (unless some external process
301
300
        has removed the tables)
302
301
      */
303
 
      result= session->reopen_tables();
 
302
      result= session->reopen_tables(true, true);
304
303
 
305
304
      /* Set version for table */
306
305
      for (Table *table= session->open_tables; table ; table= table->getNext())
313
312
          table->getMutableShare()->refreshVersion();
314
313
      }
315
314
    }
 
315
 
 
316
    table::Cache::singleton().mutex().unlock();
316
317
  }
317
318
 
318
319
  if (wait_for_refresh)
331
332
  move one table to free list 
332
333
*/
333
334
 
334
 
bool Session::free_cached_table(boost::mutex::scoped_lock &scopedLock)
 
335
bool Session::free_cached_table()
335
336
{
336
337
  bool found_old_table= false;
337
 
 
338
 
  (void)scopedLock;
339
 
 
340
338
  table::Concurrent *table= static_cast<table::Concurrent *>(open_tables);
341
339
 
342
340
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
388
386
 
389
387
  while (open_tables)
390
388
  {
391
 
    found_old_table|= free_cached_table(scoped_lock);
 
389
    found_old_table|= free_cached_table();
392
390
  }
393
391
  some_tables_deleted= false;
394
392
 
424
422
{
425
423
  for (; table; table= table->*link )
426
424
  {
427
 
    if ((table->table == 0 || table->table->getShare()->getType() == message::Table::STANDARD) and
428
 
        my_strcasecmp(system_charset_info, table->getSchemaName(), db_name) == 0 and
429
 
        my_strcasecmp(system_charset_info, table->getTableName(), table_name) == 0)
430
 
    {
 
425
    if ((table->table == 0 || table->table->getShare()->getType() == message::Table::STANDARD) &&
 
426
        strcasecmp(table->getSchemaName(), db_name) == 0 &&
 
427
        strcasecmp(table->getTableName(), table_name) == 0)
431
428
      break;
432
 
    }
433
429
  }
434
430
  return table;
435
431
}
521
517
}
522
518
 
523
519
 
524
 
void Open_tables_state::doGetTableNames(const identifier::Schema &schema_identifier,
 
520
void Open_tables_state::doGetTableNames(const SchemaIdentifier &schema_identifier,
525
521
                                        std::set<std::string>& set_of_names)
526
522
{
527
523
  for (Table *table= getTemporaryTables() ; table ; table= table->getNext())
534
530
}
535
531
 
536
532
void Open_tables_state::doGetTableNames(CachedDirectory &,
537
 
                                        const identifier::Schema &schema_identifier,
 
533
                                        const SchemaIdentifier &schema_identifier,
538
534
                                        std::set<std::string> &set_of_names)
539
535
{
540
536
  doGetTableNames(schema_identifier, set_of_names);
541
537
}
542
538
 
543
 
void Open_tables_state::doGetTableIdentifiers(const identifier::Schema &schema_identifier,
544
 
                                              identifier::Table::vector &set_of_identifiers)
 
539
void Open_tables_state::doGetTableIdentifiers(const SchemaIdentifier &schema_identifier,
 
540
                                              TableIdentifier::vector &set_of_identifiers)
545
541
{
546
542
  for (Table *table= getTemporaryTables() ; table ; table= table->getNext())
547
543
  {
548
544
    if (schema_identifier.compare(table->getShare()->getSchemaName()))
549
545
    {
550
 
      set_of_identifiers.push_back(identifier::Table(table->getShare()->getSchemaName(),
 
546
      set_of_identifiers.push_back(TableIdentifier(table->getShare()->getSchemaName(),
551
547
                                                   table->getShare()->getTableName(),
552
548
                                                   table->getShare()->getPath()));
553
549
    }
555
551
}
556
552
 
557
553
void Open_tables_state::doGetTableIdentifiers(CachedDirectory &,
558
 
                                              const identifier::Schema &schema_identifier,
559
 
                                              identifier::Table::vector &set_of_identifiers)
 
554
                                              const SchemaIdentifier &schema_identifier,
 
555
                                              TableIdentifier::vector &set_of_identifiers)
560
556
{
561
557
  doGetTableIdentifiers(schema_identifier, set_of_identifiers);
562
558
}
563
559
 
564
 
bool Open_tables_state::doDoesTableExist(const identifier::Table &identifier)
 
560
bool Open_tables_state::doDoesTableExist(const TableIdentifier &identifier)
565
561
{
566
562
  for (Table *table= getTemporaryTables() ; table ; table= table->getNext())
567
563
  {
577
573
  return false;
578
574
}
579
575
 
580
 
int Open_tables_state::doGetTableDefinition(const identifier::Table &identifier,
581
 
                                            message::Table &table_proto)
 
576
int Open_tables_state::doGetTableDefinition(const TableIdentifier &identifier,
 
577
                                  message::Table &table_proto)
582
578
{
583
579
  for (Table *table= getTemporaryTables() ; table ; table= table->getNext())
584
580
  {
586
582
    {
587
583
      if (identifier.getKey() == table->getShare()->getCacheKey())
588
584
      {
589
 
        table_proto.CopyFrom(*(table->getShare()->getTableMessage()));
 
585
        table_proto.CopyFrom(*(table->getShare()->getTableProto()));
590
586
 
591
587
        return EEXIST;
592
588
      }
596
592
  return ENOENT;
597
593
}
598
594
 
599
 
Table *Open_tables_state::find_temporary_table(const identifier::Table &identifier)
 
595
Table *Open_tables_state::find_temporary_table(const TableIdentifier &identifier)
600
596
{
601
597
  for (Table *table= temporary_tables ; table ; table= table->getNext())
602
598
  {
634
630
  @retval -1  the table is in use by a outer query
635
631
*/
636
632
 
637
 
int Open_tables_state::drop_temporary_table(const drizzled::identifier::Table &identifier)
 
633
int Open_tables_state::drop_temporary_table(const drizzled::TableIdentifier &identifier)
638
634
{
639
635
  Table *table;
640
636
 
666
662
 
667
663
void Session::unlink_open_table(Table *find)
668
664
{
669
 
  const identifier::Table::Key find_key(find->getShare()->getCacheKey());
 
665
  const TableIdentifier::Key find_key(find->getShare()->getCacheKey());
670
666
  Table **prev;
671
667
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
672
668
 
673
669
  /*
674
670
    Note that we need to hold table::Cache::singleton().mutex() while changing the
675
671
    open_tables list. Another thread may work on it.
676
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
672
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
677
673
    Closing a MERGE child before the parent would be fatal if the
678
674
    other thread tries to abort the MERGE lock in between.
679
675
  */
720
716
  table that was locked with LOCK TABLES.
721
717
*/
722
718
 
723
 
void Session::drop_open_table(Table *table, const identifier::Table &identifier)
 
719
void Session::drop_open_table(Table *table, const TableIdentifier &identifier)
724
720
{
725
721
  if (table->getShare()->getType())
726
722
  {
734
730
      that something has happened.
735
731
    */
736
732
    unlink_open_table(table);
737
 
    (void)plugin::StorageEngine::dropTable(*this, identifier);
 
733
    plugin::StorageEngine::dropTable(*this, identifier);
738
734
  }
739
735
}
740
736
 
795
791
  case of failure.
796
792
*/
797
793
 
798
 
table::Placeholder *Session::table_cache_insert_placeholder(const drizzled::identifier::Table &arg)
 
794
table::Placeholder *Session::table_cache_insert_placeholder(const drizzled::TableIdentifier &arg)
799
795
{
800
796
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
801
797
 
802
798
  /*
803
799
    Create a table entry with the right key and with an old refresh version
804
800
  */
805
 
  identifier::Table identifier(arg.getSchemaName(), arg.getTableName(), message::Table::INTERNAL);
 
801
  TableIdentifier identifier(arg.getSchemaName(), arg.getTableName(), message::Table::INTERNAL);
806
802
  table::Placeholder *table= new table::Placeholder(this, identifier);
807
803
 
808
804
  if (not table::Cache::singleton().insert(table))
809
805
  {
810
 
    safe_delete(table);
 
806
    delete table;
811
807
 
812
808
    return NULL;
813
809
  }
837
833
  @retval  true   Error occured (OOM)
838
834
  @retval  false  Success. 'table' parameter set according to above rules.
839
835
*/
840
 
bool Session::lock_table_name_if_not_cached(const identifier::Table &identifier, Table **table)
 
836
bool Session::lock_table_name_if_not_cached(const TableIdentifier &identifier, Table **table)
841
837
{
842
 
  const identifier::Table::Key &key(identifier.getKey());
 
838
  const TableIdentifier::Key &key(identifier.getKey());
843
839
 
844
840
  boost_unique_lock_t scope_lock(table::Cache::singleton().mutex()); /* Obtain a name lock even though table is not in cache (like for create table)  */
845
841
 
916
912
  if (getKilled())
917
913
    return NULL;
918
914
 
919
 
  identifier::Table identifier(table_list->getSchemaName(), table_list->getTableName());
920
 
  const identifier::Table::Key &key(identifier.getKey());
 
915
  TableIdentifier identifier(table_list->getSchemaName(), table_list->getTableName());
 
916
  const TableIdentifier::Key &key(identifier.getKey());
921
917
  table::CacheRange ppp;
922
918
 
923
919
  /*
953
949
  {
954
950
    if (flags & DRIZZLE_OPEN_TEMPORARY_ONLY)
955
951
    {
956
 
      my_error(ER_TABLE_UNKNOWN, identifier);
 
952
      my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->getSchemaName(), table_list->getTableName());
957
953
      return NULL;
958
954
    }
959
955
 
1004
1000
    */
1005
1001
 
1006
1002
    {
1007
 
      boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
1003
      table::Cache::singleton().mutex().lock(); /* Lock for FLUSH TABLES for open table */
1008
1004
 
1009
1005
      /*
1010
1006
        Actually try to find the table in the open_cache.
1056
1052
          /* Avoid self-deadlocks by detecting self-dependencies. */
1057
1053
          if (table->open_placeholder && table->in_use == this)
1058
1054
          {
 
1055
            table::Cache::singleton().mutex().unlock();
1059
1056
            my_error(ER_UPDATE_TABLE_USED, MYF(0), table->getShare()->getTableName());
1060
1057
            return NULL;
1061
1058
          }
1090
1087
          {
1091
1088
            /* wait_for_conditionwill unlock table::Cache::singleton().mutex() for us */
1092
1089
            wait_for_condition(table::Cache::singleton().mutex(), COND_refresh);
1093
 
            scopedLock.release();
1094
1090
          }
1095
1091
          else
1096
1092
          {
1097
 
            scopedLock.unlock();
 
1093
            table::Cache::singleton().mutex().unlock();
1098
1094
          }
1099
 
 
1100
1095
          /*
1101
1096
            There is a refresh in progress for this table.
1102
1097
            Signal the caller that it has to try again.
1103
1098
          */
1104
1099
          if (refresh)
1105
1100
            *refresh= true;
1106
 
 
1107
1101
          return NULL;
1108
1102
        }
1109
1103
      }
1110
 
 
1111
1104
      if (table)
1112
1105
      {
1113
1106
        table::getUnused().unlink(static_cast<table::Concurrent *>(table));
1122
1115
 
1123
1116
        if (table_list->isCreate())
1124
1117
        {
1125
 
          identifier::Table  lock_table_identifier(table_list->getSchemaName(), table_list->getTableName(), message::Table::STANDARD);
 
1118
          TableIdentifier  lock_table_identifier(table_list->getSchemaName(), table_list->getTableName(), message::Table::STANDARD);
1126
1119
 
1127
1120
          if (not plugin::StorageEngine::doesTableExist(*this, lock_table_identifier))
1128
1121
          {
1131
1124
            */
1132
1125
            if (!(table= table_cache_insert_placeholder(lock_table_identifier)))
1133
1126
            {
 
1127
              table::Cache::singleton().mutex().unlock();
1134
1128
              return NULL;
1135
1129
            }
1136
1130
            /*
1141
1135
            table->open_placeholder= true;
1142
1136
            table->setNext(open_tables);
1143
1137
            open_tables= table;
 
1138
            table::Cache::singleton().mutex().unlock();
1144
1139
 
1145
1140
            return table ;
1146
1141
          }
1153
1148
          table= new_table;
1154
1149
          if (new_table == NULL)
1155
1150
          {
 
1151
            table::Cache::singleton().mutex().unlock();
1156
1152
            return NULL;
1157
1153
          }
1158
1154
 
1160
1156
          if (error != 0)
1161
1157
          {
1162
1158
            delete new_table;
 
1159
            table::Cache::singleton().mutex().unlock();
1163
1160
            return NULL;
1164
1161
          }
1165
1162
          (void)table::Cache::singleton().insert(new_table);
1166
1163
        }
1167
1164
      }
 
1165
 
 
1166
      table::Cache::singleton().mutex().unlock();
1168
1167
    }
1169
 
 
1170
1168
    if (refresh)
1171
1169
    {
1172
1170
      table->setNext(open_tables); /* Link into simple list */
1224
1222
  the strings are used in a loop even after the share may be freed.
1225
1223
*/
1226
1224
 
1227
 
void Session::close_data_files_and_morph_locks(const identifier::Table &identifier)
 
1225
void Session::close_data_files_and_morph_locks(const TableIdentifier &identifier)
1228
1226
{
1229
1227
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle()); /* Adjust locks at the end of ALTER TABLEL */
1230
1228
 
1274
1272
  @return false in case of success, true - otherwise.
1275
1273
*/
1276
1274
 
1277
 
bool Session::reopen_tables()
 
1275
bool Session::reopen_tables(bool get_locks, bool)
1278
1276
{
1279
1277
  Table *table,*next,**prev;
1280
 
  Table **tables= 0;                    // For locks
1281
 
  Table **tables_ptr= 0;                        // For locks
1282
 
  bool error= false;
 
1278
  Table **tables,**tables_ptr;                  // For locks
 
1279
  bool error=0, not_used;
1283
1280
  const uint32_t flags= DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN |
1284
1281
    DRIZZLE_LOCK_IGNORE_GLOBAL_READ_LOCK |
1285
1282
    DRIZZLE_LOCK_IGNORE_FLUSH;
1288
1285
    return false;
1289
1286
 
1290
1287
  safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
 
1288
  if (get_locks)
1291
1289
  {
1292
1290
    /*
1293
1291
      The ptr is checked later
1301
1299
    }
1302
1300
    tables= new Table *[opens];
1303
1301
  }
1304
 
 
 
1302
  else
 
1303
  {
 
1304
    tables= &open_tables;
 
1305
  }
1305
1306
  tables_ptr =tables;
1306
1307
 
1307
1308
  prev= &open_tables;
1314
1315
    error= 1;
1315
1316
  }
1316
1317
  *prev=0;
1317
 
 
1318
1318
  if (tables != tables_ptr)                     // Should we get back old locks
1319
1319
  {
1320
1320
    DrizzleLock *local_lock;
1325
1325
    */
1326
1326
    some_tables_deleted= false;
1327
1327
 
1328
 
    if ((local_lock= lockTables(tables, (uint32_t) (tables_ptr - tables), flags)))
 
1328
    if ((local_lock= lockTables(tables, (uint32_t) (tables_ptr - tables),
 
1329
                                       flags, &not_used)))
1329
1330
    {
1330
1331
      /* unused */
1331
1332
    }
1341
1342
    }
1342
1343
  }
1343
1344
 
1344
 
  delete [] tables;
 
1345
  if (get_locks && tables)
 
1346
    delete [] tables;
1345
1347
 
1346
1348
  locking::broadcast_refresh();
1347
1349
 
1348
 
  return error;
 
1350
  return(error);
1349
1351
}
1350
1352
 
1351
1353
 
1376
1378
    */
1377
1379
    if (table->needs_reopen_or_name_lock())
1378
1380
    {
1379
 
      found= true;
 
1381
      found=1;
1380
1382
      if (table->db_stat)
1381
1383
      {
1382
1384
        if (morph_locks)
1435
1437
}
1436
1438
 
1437
1439
 
 
1440
/* Wait until all used tables are refreshed */
 
1441
 
 
1442
bool wait_for_tables(Session *session)
 
1443
{
 
1444
  bool result;
 
1445
 
 
1446
  session->set_proc_info("Waiting for tables");
 
1447
  {
 
1448
    boost_unique_lock_t lock(table::Cache::singleton().mutex());
 
1449
    while (not session->getKilled())
 
1450
    {
 
1451
      session->some_tables_deleted= false;
 
1452
      session->close_old_data_files(false, dropping_tables != 0);
 
1453
      if (not table::Cache::singleton().areTablesUsed(session->open_tables, 1))
 
1454
      {
 
1455
        break;
 
1456
      }
 
1457
      COND_refresh.wait(lock);
 
1458
    }
 
1459
    if (session->getKilled())
 
1460
      result= true;                                     // aborted
 
1461
    else
 
1462
    {
 
1463
      /* Now we can open all tables without any interference */
 
1464
      session->set_proc_info("Reopen tables");
 
1465
      session->version= refresh_version;
 
1466
      result= session->reopen_tables(false, false);
 
1467
    }
 
1468
  }
 
1469
  session->set_proc_info(0);
 
1470
 
 
1471
  return result;
 
1472
}
 
1473
 
 
1474
 
1438
1475
/*
1439
1476
  drop tables from locked list
1440
1477
 
1459
1496
*/
1460
1497
 
1461
1498
 
1462
 
Table *drop_locked_tables(Session *session, const drizzled::identifier::Table &identifier)
 
1499
Table *drop_locked_tables(Session *session, const drizzled::TableIdentifier &identifier)
1463
1500
{
1464
1501
  Table *table,*next,**prev, *found= 0;
1465
1502
  prev= &session->open_tables;
1467
1504
  /*
1468
1505
    Note that we need to hold table::Cache::singleton().mutex() while changing the
1469
1506
    open_tables list. Another thread may work on it.
1470
 
    (See: table::Cache::singleton().removeTable(), wait_completed_table())
 
1507
    (See: table::Cache::singleton().removeTable(), mysql_wait_completed_table())
1471
1508
    Closing a MERGE child before the parent would be fatal if the
1472
1509
    other thread tries to abort the MERGE lock in between.
1473
1510
  */
1501
1538
    }
1502
1539
  }
1503
1540
  *prev=0;
1504
 
 
1505
1541
  if (found)
1506
1542
    locking::broadcast_refresh();
1507
1543
 
1508
 
  return found;
 
1544
  return(found);
1509
1545
}
1510
1546
 
1511
1547
 
1515
1551
  other threads trying to get the lock.
1516
1552
*/
1517
1553
 
1518
 
void abort_locked_tables(Session *session, const drizzled::identifier::Table &identifier)
 
1554
void abort_locked_tables(Session *session, const drizzled::TableIdentifier &identifier)
1519
1555
{
1520
1556
  Table *table;
1521
1557
  for (table= session->open_tables; table ; table= table->getNext())
1524
1560
    {
1525
1561
      /* If MERGE child, forward lock handling to parent. */
1526
1562
      session->abortLock(table);
1527
 
      assert(0);
1528
1563
      break;
1529
1564
    }
1530
1565
  }
1597
1632
     * to see if it exists so that an unauthorized user cannot phish for
1598
1633
     * table/schema information via error messages
1599
1634
     */
1600
 
    identifier::Table the_table(tables->getSchemaName(), tables->getTableName());
1601
 
    if (not plugin::Authorization::isAuthorized(*user(), the_table))
 
1635
    TableIdentifier the_table(tables->getSchemaName(), tables->getTableName());
 
1636
    if (not plugin::Authorization::isAuthorized(getSecurityContext(),
 
1637
                                                the_table))
1602
1638
    {
1603
1639
      result= -1;                               // Fatal error
1604
1640
      break;
1695
1731
 
1696
1732
  set_proc_info("Opening table");
1697
1733
  current_tablenr= 0;
1698
 
  while (!(table= openTable(table_list, &refresh)) && refresh) ;
 
1734
  while (!(table= openTable(table_list, &refresh)) &&
 
1735
         refresh)
 
1736
    ;
1699
1737
 
1700
1738
  if (table)
1701
1739
  {
1704
1742
 
1705
1743
    assert(lock == 0);  // You must lock everything at once
1706
1744
    if ((table->reginfo.lock_type= lock_type) != TL_UNLOCK)
1707
 
    {
1708
 
      if (not (lock= lockTables(&table_list->table, 1, 0)))
1709
 
        table= NULL;
1710
 
    }
 
1745
      if (! (lock= lockTables(&table_list->table, 1, 0, &refresh)))
 
1746
        table= 0;
1711
1747
  }
1712
1748
 
1713
1749
  set_proc_info(0);
1761
1797
  Table **start,**ptr;
1762
1798
  uint32_t lock_flag= DRIZZLE_LOCK_NOTIFY_IF_NEED_REOPEN;
1763
1799
 
1764
 
  if (!(ptr=start=(Table**) session->getMemRoot()->allocate(sizeof(Table*)*count)))
 
1800
  if (!(ptr=start=(Table**) session->alloc(sizeof(Table*)*count)))
1765
1801
    return -1;
1766
 
 
1767
1802
  for (table= tables; table; table= table->next_global)
1768
1803
  {
1769
1804
    if (!table->placeholder())
1770
1805
      *(ptr++)= table->table;
1771
1806
  }
1772
1807
 
1773
 
  if (not (session->lock= session->lockTables(start, (uint32_t) (ptr - start), lock_flag)))
 
1808
  if (!(session->lock= session->lockTables(start, (uint32_t) (ptr - start), lock_flag, need_reopen)))
1774
1809
  {
1775
1810
    return -1;
1776
1811
  }
1799
1834
#  Table object
1800
1835
*/
1801
1836
 
1802
 
Table *Open_tables_state::open_temporary_table(const identifier::Table &identifier,
 
1837
Table *Open_tables_state::open_temporary_table(const TableIdentifier &identifier,
1803
1838
                                               bool link_in_list)
1804
1839
{
1805
1840
  assert(identifier.isTmp());
1807
1842
 
1808
1843
  table::Temporary *new_tmp_table= new table::Temporary(identifier.getType(),
1809
1844
                                                        identifier,
1810
 
                                                        const_cast<char *>(const_cast<identifier::Table&>(identifier).getPath().c_str()),
 
1845
                                                        const_cast<char *>(const_cast<TableIdentifier&>(identifier).getPath().c_str()),
1811
1846
                                                        static_cast<uint32_t>(identifier.getPath().length()));
1812
1847
  if (not new_tmp_table)
1813
1848
    return NULL;
1929
1964
                           const char *name, uint32_t , Item **,
1930
1965
                           bool, TableList **actual_table)
1931
1966
{
1932
 
  List<Natural_join_column>::iterator
1933
 
    field_it(table_ref->join_columns->begin());
 
1967
  List_iterator_fast<Natural_join_column>
 
1968
    field_it(*(table_ref->join_columns));
1934
1969
  Natural_join_column *nj_col, *curr_nj_col;
1935
1970
  Field *found_field;
1936
1971
 
1944
1979
    {
1945
1980
      if (nj_col)
1946
1981
      {
1947
 
        my_error(ER_NON_UNIQ_ERROR, MYF(0), name, session->where());
 
1982
        my_error(ER_NON_UNIQ_ERROR, MYF(0), name, session->where);
1948
1983
        return NULL;
1949
1984
      }
1950
1985
      nj_col= curr_nj_col;
2145
2180
    */
2146
2181
    if (table_name && table_name[0])
2147
2182
    {
2148
 
      List<TableList>::iterator it(table_list->getNestedJoin()->join_list.begin());
 
2183
      List_iterator<TableList> it(table_list->getNestedJoin()->join_list);
2149
2184
      TableList *table;
2150
2185
      while ((table= it++))
2151
2186
      {
2295
2330
        fields.
2296
2331
      */
2297
2332
      {
2298
 
        Select_Lex *current_sel= session->getLex()->current_select;
 
2333
        Select_Lex *current_sel= session->lex->current_select;
2299
2334
        Select_Lex *last_select= table_ref->select_lex;
2300
2335
        /*
2301
2336
          If the field was an outer referencee, mark all selects using this
2341
2376
      */
2342
2377
      item->cached_table= found ?  0 : actual_table;
2343
2378
 
2344
 
      assert(session->where());
 
2379
      assert(session->where);
2345
2380
      /*
2346
2381
        If we found a fully qualified field we return it directly as it can't
2347
2382
        have duplicates.
2354
2389
        if (report_error == REPORT_ALL_ERRORS ||
2355
2390
            report_error == IGNORE_EXCEPT_NON_UNIQUE)
2356
2391
          my_error(ER_NON_UNIQ_ERROR, MYF(0),
2357
 
                   table_name ? item->full_name() : name, session->where());
 
2392
                   table_name ? item->full_name() : name, session->where);
2358
2393
        return (Field*) 0;
2359
2394
      }
2360
2395
      found= cur_field;
2387
2422
      strcat(buff, table_name);
2388
2423
      table_name=buff;
2389
2424
    }
2390
 
    my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, session->where());
 
2425
    my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, session->where);
2391
2426
  }
2392
2427
  else
2393
2428
  {
2394
2429
    if (report_error == REPORT_ALL_ERRORS ||
2395
2430
        report_error == REPORT_EXCEPT_NON_UNIQUE)
2396
 
      my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), session->where());
 
2431
      my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), session->where);
2397
2432
    else
2398
2433
      found= not_found_field;
2399
2434
  }
2444
2479
                  find_item_error_report_type report_error,
2445
2480
                  enum_resolution_type *resolution)
2446
2481
{
2447
 
  List<Item>::iterator li(items.begin());
 
2482
  List_iterator<Item> li(items);
2448
2483
  Item **found=0, **found_unaliased= 0, *item;
2449
2484
  const char *db_name=0;
2450
2485
  const char *field_name=0;
2520
2555
            */
2521
2556
            if (report_error != IGNORE_ERRORS)
2522
2557
              my_error(ER_NON_UNIQ_ERROR, MYF(0),
2523
 
                       find->full_name(), session->where());
 
2558
                       find->full_name(), session->where);
2524
2559
            return (Item**) 0;
2525
2560
          }
2526
2561
          found_unaliased= li.ref();
2551
2586
              continue;                           // Same field twice
2552
2587
            if (report_error != IGNORE_ERRORS)
2553
2588
              my_error(ER_NON_UNIQ_ERROR, MYF(0),
2554
 
                       find->full_name(), session->where());
 
2589
                       find->full_name(), session->where);
2555
2590
            return (Item**) 0;
2556
2591
          }
2557
2592
          found= li.ref();
2603
2638
    {
2604
2639
      if (report_error != IGNORE_ERRORS)
2605
2640
        my_error(ER_NON_UNIQ_ERROR, MYF(0),
2606
 
                 find->full_name(), session->where());
 
2641
                 find->full_name(), session->where);
2607
2642
      return (Item **) 0;
2608
2643
    }
2609
2644
    if (found_unaliased)
2619
2654
  {
2620
2655
    if (report_error == REPORT_ALL_ERRORS)
2621
2656
      my_error(ER_BAD_FIELD_ERROR, MYF(0),
2622
 
               find->full_name(), session->where());
 
2657
               find->full_name(), session->where);
2623
2658
    return (Item **) 0;
2624
2659
  }
2625
2660
  else
2647
2682
static bool
2648
2683
test_if_string_in_list(const char *find, List<String> *str_list)
2649
2684
{
2650
 
  List<String>::iterator str_list_it(str_list->begin());
 
2685
  List_iterator<String> str_list_it(*str_list);
2651
2686
  String *curr_str;
2652
2687
  size_t find_length= strlen(find);
2653
2688
  while ((curr_str= str_list_it++))
2790
2825
        if (cur_nj_col_2->is_common ||
2791
2826
            (found && (!using_fields || is_using_column_1)))
2792
2827
        {
2793
 
          my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, session->where());
 
2828
          my_error(ER_NON_UNIQ_ERROR, MYF(0), field_name_1, session->where);
2794
2829
          return(result);
2795
2830
        }
2796
2831
        nj_col_2= cur_nj_col_2;
2981
3016
  if (using_fields && found_using_fields < using_fields->elements)
2982
3017
  {
2983
3018
    String *using_field_name;
2984
 
    List<String>::iterator using_fields_it(using_fields->begin());
 
3019
    List_iterator_fast<String> using_fields_it(*using_fields);
2985
3020
    while ((using_field_name= using_fields_it++))
2986
3021
    {
2987
3022
      const char *using_field_name_ptr= using_field_name->c_ptr();
2988
 
      List<Natural_join_column>::iterator
2989
 
        it(natural_using_join->join_columns->begin());
 
3023
      List_iterator_fast<Natural_join_column>
 
3024
        it(*(natural_using_join->join_columns));
2990
3025
      Natural_join_column *common_field;
2991
3026
 
2992
3027
      for (;;)
2995
3030
        if (!(common_field= it++))
2996
3031
        {
2997
3032
          my_error(ER_BAD_FIELD_ERROR, MYF(0), using_field_name_ptr,
2998
 
                   session->where());
 
3033
                   session->where);
2999
3034
          return(result);
3000
3035
        }
3001
3036
        if (!my_strcasecmp(system_charset_info,
3068
3103
  /* Call the procedure recursively for each nested table reference. */
3069
3104
  if (table_ref->getNestedJoin())
3070
3105
  {
3071
 
    List<TableList>::iterator nested_it(table_ref->getNestedJoin()->join_list.begin());
 
3106
    List_iterator_fast<TableList> nested_it(table_ref->getNestedJoin()->join_list);
3072
3107
    TableList *same_level_left_neighbor= nested_it++;
3073
3108
    TableList *same_level_right_neighbor= NULL;
3074
3109
    /* Left/right-most neighbors, possibly at higher levels in the join tree. */
3122
3157
  {
3123
3158
    assert(table_ref->getNestedJoin() &&
3124
3159
           table_ref->getNestedJoin()->join_list.elements == 2);
3125
 
    List<TableList>::iterator operand_it(table_ref->getNestedJoin()->join_list.begin());
 
3160
    List_iterator_fast<TableList> operand_it(table_ref->getNestedJoin()->join_list);
3126
3161
    /*
3127
3162
      Notice that the order of join operands depends on whether table_ref
3128
3163
      represents a LEFT or a RIGHT join. In a RIGHT join, the operands are
3218
3253
                                         List<TableList> *from_clause,
3219
3254
                                         Name_resolution_context *context)
3220
3255
{
3221
 
  session->setWhere("from clause");
 
3256
  session->where= "from clause";
3222
3257
  if (from_clause->elements == 0)
3223
3258
    return false; /* We come here in the case of UNIONs. */
3224
3259
 
3225
 
  List<TableList>::iterator table_ref_it(from_clause->begin());
 
3260
  List_iterator_fast<TableList> table_ref_it(*from_clause);
3226
3261
  TableList *table_ref; /* Current table reference. */
3227
3262
  /* Table reference to the left of the current. */
3228
3263
  TableList *left_neighbor;
3272
3307
    return 0;
3273
3308
 
3274
3309
  Item *item;
3275
 
  List<Item>::iterator it(fields.begin());
 
3310
  List_iterator<Item> it(fields);
3276
3311
 
3277
 
  session->getLex()->current_select->cur_pos_in_select_list= 0;
 
3312
  session->lex->current_select->cur_pos_in_select_list= 0;
3278
3313
  while (wild_num && (item= it++))
3279
3314
  {
3280
3315
    if (item->type() == Item::FIELD_ITEM &&
3284
3319
    {
3285
3320
      uint32_t elem= fields.elements;
3286
3321
      bool any_privileges= ((Item_field *) item)->any_privileges;
3287
 
      Item_subselect *subsel= session->getLex()->current_select->master_unit()->item;
 
3322
      Item_subselect *subsel= session->lex->current_select->master_unit()->item;
3288
3323
      if (subsel &&
3289
3324
          subsel->substype() == Item_subselect::EXISTS_SUBS)
3290
3325
      {
3315
3350
      wild_num--;
3316
3351
    }
3317
3352
    else
3318
 
      session->getLex()->current_select->cur_pos_in_select_list++;
 
3353
      session->lex->current_select->cur_pos_in_select_list++;
3319
3354
  }
3320
 
  session->getLex()->current_select->cur_pos_in_select_list= UNDEF_POS;
 
3355
  session->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
3321
3356
 
3322
3357
  return 0;
3323
3358
}
3332
3367
{
3333
3368
  register Item *item;
3334
3369
  enum_mark_columns save_mark_used_columns= session->mark_used_columns;
3335
 
  nesting_map save_allow_sum_func= session->getLex()->allow_sum_func;
3336
 
  List<Item>::iterator it(fields.begin());
 
3370
  nesting_map save_allow_sum_func= session->lex->allow_sum_func;
 
3371
  List_iterator<Item> it(fields);
3337
3372
  bool save_is_item_list_lookup;
3338
3373
 
3339
3374
  session->mark_used_columns= mark_used_columns;
3340
3375
  if (allow_sum_func)
3341
 
    session->getLex()->allow_sum_func|= 1 << session->getLex()->current_select->nest_level;
3342
 
  session->setWhere(Session::DEFAULT_WHERE);
3343
 
  save_is_item_list_lookup= session->getLex()->current_select->is_item_list_lookup;
3344
 
  session->getLex()->current_select->is_item_list_lookup= 0;
 
3376
    session->lex->allow_sum_func|= 1 << session->lex->current_select->nest_level;
 
3377
  session->where= Session::DEFAULT_WHERE;
 
3378
  save_is_item_list_lookup= session->lex->current_select->is_item_list_lookup;
 
3379
  session->lex->current_select->is_item_list_lookup= 0;
3345
3380
 
3346
3381
  /*
3347
3382
    To prevent fail on forward lookup we fill it with zerows,
3351
3386
    There is other way to solve problem: fill array with pointers to list,
3352
3387
    but it will be slower.
3353
3388
 
3354
 
    TODO-> remove it when (if) we made one list for allfields and ref_pointer_array
 
3389
TODO: remove it when (if) we made one list for allfields and
 
3390
ref_pointer_array
3355
3391
  */
3356
3392
  if (ref_pointer_array)
3357
 
  {
3358
3393
    memset(ref_pointer_array, 0, sizeof(Item *) * fields.elements);
3359
 
  }
3360
3394
 
3361
3395
  Item **ref= ref_pointer_array;
3362
 
  session->getLex()->current_select->cur_pos_in_select_list= 0;
 
3396
  session->lex->current_select->cur_pos_in_select_list= 0;
3363
3397
  while ((item= it++))
3364
3398
  {
3365
3399
    if ((!item->fixed && item->fix_fields(session, it.ref())) || (item= *(it.ref()))->check_cols(1))
3366
3400
    {
3367
 
      session->getLex()->current_select->is_item_list_lookup= save_is_item_list_lookup;
3368
 
      session->getLex()->allow_sum_func= save_allow_sum_func;
 
3401
      session->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
 
3402
      session->lex->allow_sum_func= save_allow_sum_func;
3369
3403
      session->mark_used_columns= save_mark_used_columns;
3370
3404
      return true;
3371
3405
    }
3375
3409
        sum_func_list)
3376
3410
      item->split_sum_func(session, ref_pointer_array, *sum_func_list);
3377
3411
    session->used_tables|= item->used_tables();
3378
 
    session->getLex()->current_select->cur_pos_in_select_list++;
 
3412
    session->lex->current_select->cur_pos_in_select_list++;
3379
3413
  }
3380
 
  session->getLex()->current_select->is_item_list_lookup= save_is_item_list_lookup;
3381
 
  session->getLex()->current_select->cur_pos_in_select_list= UNDEF_POS;
 
3414
  session->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
 
3415
  session->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
3382
3416
 
3383
 
  session->getLex()->allow_sum_func= save_allow_sum_func;
 
3417
  session->lex->allow_sum_func= save_allow_sum_func;
3384
3418
  session->mark_used_columns= save_mark_used_columns;
3385
3419
  return(test(session->is_error()));
3386
3420
}
3549
3583
 
3550
3584
bool
3551
3585
insert_fields(Session *session, Name_resolution_context *context, const char *db_name,
3552
 
              const char *table_name, List<Item>::iterator *it,
 
3586
              const char *table_name, List_iterator<Item> *it,
3553
3587
              bool )
3554
3588
{
3555
3589
  Field_iterator_table_ref field_iterator;
3588
3622
    assert(tables->is_leaf_for_name_resolution());
3589
3623
 
3590
3624
    if ((table_name && my_strcasecmp(table_alias_charset, table_name, tables->alias)) ||
3591
 
        (db_name && my_strcasecmp(system_charset_info, tables->getSchemaName(),db_name)))
 
3625
        (db_name && strcasecmp(tables->getSchemaName(),db_name)))
3592
3626
      continue;
3593
3627
 
3594
3628
    /*
3652
3686
        }
3653
3687
      }
3654
3688
      else
3655
 
      {
3656
3689
        session->used_tables|= item->used_tables();
3657
 
      }
3658
 
 
3659
 
      session->getLex()->current_select->cur_pos_in_select_list++;
 
3690
      session->lex->current_select->cur_pos_in_select_list++;
3660
3691
    }
3661
3692
    /*
3662
3693
      In case of stored tables, all fields are considered as used,
3675
3706
    qualified '*', and all columns were coalesced, we have to give a more
3676
3707
    meaningful message than ER_BAD_TABLE_ERROR.
3677
3708
  */
3678
 
  if (not table_name)
3679
 
  {
 
3709
  if (!table_name)
3680
3710
    my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0));
3681
 
  }
3682
3711
  else
3683
 
  {
3684
3712
    my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name);
3685
 
  }
3686
3713
 
3687
3714
  return true;
3688
3715
}
3709
3736
int Session::setup_conds(TableList *leaves, COND **conds)
3710
3737
{
3711
3738
  Session *session= this;
3712
 
  Select_Lex *select_lex= session->getLex()->current_select;
 
3739
  Select_Lex *select_lex= session->lex->current_select;
3713
3740
  TableList *table= NULL;       // For HP compilers
3714
3741
  void *save_session_marker= session->session_marker;
3715
3742
  /*
3731
3758
  session->session_marker= (void*)1;
3732
3759
  if (*conds)
3733
3760
  {
3734
 
    session->setWhere("where clause");
 
3761
    session->where="where clause";
3735
3762
    if ((!(*conds)->fixed && (*conds)->fix_fields(session, conds)) ||
3736
3763
        (*conds)->check_cols(1))
3737
3764
      goto err_no_arena;
3753
3780
      {
3754
3781
        /* Make a join an a expression */
3755
3782
        session->session_marker= (void*)embedded;
3756
 
        session->setWhere("on clause");
 
3783
        session->where="on clause";
3757
3784
        if ((!embedded->on_expr->fixed && embedded->on_expr->fix_fields(session, &embedded->on_expr)) ||
3758
3785
            embedded->on_expr->check_cols(1))
3759
3786
          goto err_no_arena;
3767
3794
  }
3768
3795
  session->session_marker= save_session_marker;
3769
3796
 
3770
 
  session->getLex()->current_select->is_item_list_lookup= save_is_item_list_lookup;
 
3797
  session->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
3771
3798
  return(test(session->is_error()));
3772
3799
 
3773
3800
err_no_arena:
3805
3832
bool
3806
3833
fill_record(Session *session, List<Item> &fields, List<Item> &values, bool ignore_errors)
3807
3834
{
3808
 
  List<Item>::iterator f(fields.begin());
3809
 
  List<Item>::iterator v(values.begin());
 
3835
  List_iterator_fast<Item> f(fields),v(values);
3810
3836
  Item *value;
3811
3837
  Item_field *field;
3812
3838
  Table *table;
3824
3850
    field= static_cast<Item_field *>(f++);
3825
3851
    table= field->field->getTable();
3826
3852
    table->auto_increment_field_not_null= false;
3827
 
    f= fields.begin();
 
3853
    f.rewind();
3828
3854
  }
3829
3855
 
3830
3856
  while ((field= static_cast<Item_field *>(f++)))
3871
3897
 
3872
3898
bool fill_record(Session *session, Field **ptr, List<Item> &values, bool)
3873
3899
{
3874
 
  List<Item>::iterator v(values.begin());
 
3900
  List_iterator_fast<Item> v(values);
3875
3901
  Item *value;
3876
3902
  Table *table= 0;
3877
3903
  Field *field;
3889
3915
    table= (*ptr)->getTable();
3890
3916
    table->auto_increment_field_not_null= false;
3891
3917
  }
3892
 
 
3893
3918
  while ((field = *ptr++) && ! session->is_error())
3894
3919
  {
3895
3920
    value=v++;
3896
3921
    table= field->getTable();
3897
 
 
3898
3922
    if (field == table->next_number_field)
3899
3923
      table->auto_increment_field_not_null= true;
3900
 
 
3901
3924
    if (value->save_in_field(field, 0) < 0)
3902
3925
    {
3903
3926
      if (table)
3913
3936
 
3914
3937
bool drizzle_rm_tmp_tables()
3915
3938
{
 
3939
  Session *session;
3916
3940
 
3917
3941
  assert(drizzle_tmpdir.size());
3918
 
  Session::shared_ptr session= Session::make_shared(plugin::Listen::getNullClient(), catalog::local());
3919
3942
 
3920
 
  if (not session)
 
3943
  if (!(session= new Session(plugin::Listen::getNullClient())))
3921
3944
    return true;
3922
 
  session->thread_stack= (char*) session.get();
 
3945
  session->thread_stack= (char*) &session;
3923
3946
  session->storeGlobals();
3924
3947
 
3925
3948
  plugin::StorageEngine::removeLostTemporaryTables(*session, drizzle_tmpdir.c_str());
3926
3949
 
 
3950
  delete session;
 
3951
 
3927
3952
  return false;
3928
3953
}
3929
3954