<commit_before>/*-------------------------------------------------------------------------
 *
 * table.cpp
 * file description
 *
 * Copyright(c) 2015, CMU
 *
 * /n-store/src/storage/table.cpp
 *
 *-------------------------------------------------------------------------
 */

#include "backend/storage/data_table.h"
#include "backend/storage/database.h"

#include "backend/common/exception.h"
#include "backend/index/index.h"
#include "backend/common/logger.h"

#include <mutex>

namespace peloton {
namespace storage {

DataTable::DataTable(catalog::Schema *schema,
                     AbstractBackend *backend,
                     std::string table_name,
                     oid_t table_oid,
                     size_t tuples_per_tilegroup)
: AbstractTable(table_oid, table_name, schema),
  backend(backend),
  tuples_per_tilegroup(tuples_per_tilegroup) {

  // Create a tile group.
  AddDefaultTileGroup();

}

DataTable::~DataTable() {

  // clean up tile groups
  oid_t tile_group_count = GetTileGroupCount();
  for(oid_t tile_group_itr = 0 ; tile_group_itr < tile_group_count; tile_group_itr++){
    auto tile_group = GetTileGroup(tile_group_itr);
    delete tile_group;
  }

  // clean up indices
  for (auto index : indexes) {
    delete index;
  }

  // clean up foreign keys
  for (auto foreign_key : foreign_keys) {
    delete foreign_key;
  }

  // table owns its backend
  // TODO: Should we really be doing this here?
  delete backend;

  // AbstractTable cleans up the schema
}

//===--------------------------------------------------------------------===//
// TUPLE OPERATIONS
//===--------------------------------------------------------------------===//

ItemPointer DataTable::InsertTuple(txn_id_t transaction_id,
                                   const storage::Tuple *tuple,
                                   bool update) {

  assert(tuple);

  // (A) Not NULL checks
  if (CheckNulls(tuple) == false) {
    throw ConstraintException("Not NULL constraint violated : " + tuple->GetInfo());
    return ItemPointer();
  }

  TileGroup *tile_group = nullptr;
  oid_t tuple_slot = INVALID_OID;
  oid_t tile_group_offset = INVALID_OID;

  while (tuple_slot == INVALID_OID) {

    // (B) Figure out last tile group
    {
      std::lock_guard<std::mutex> lock(table_mutex);
      tile_group_offset = GetTileGroupCount()-1;
      LOG_TRACE("Tile group offset :: %d \n", tile_group_offset);
    }

    // (C) Try to insert
    tile_group = GetTileGroup(tile_group_offset);
    tuple_slot = tile_group->InsertTuple(transaction_id, tuple);
    if (tuple_slot == INVALID_OID) {
      AddDefaultTileGroup();
    }
  }

  // Return Location
  ItemPointer location = ItemPointer(tile_group->GetTileGroupId(), tuple_slot);

  // Index checks and updates
  if (update == false) {
    if (TryInsertInIndexes(tuple, location) == false) {

      // FIXME
      // Need to think about how we want to actually do this, because right
      // now there is no way to get back the target TileGroup and slot from
      // DataTable::InsertTuple
      // tile_group->ReclaimTuple(tuple_slot);

      throw ConstraintException("Index constraint violated : " + tuple->GetInfo());
      return INVALID_ITEMPOINTER;
    }
  }
  else {
    // just do a blind insert
    InsertInIndexes(tuple, location);
    return location;
  }

  return location;
}

void DataTable::InsertInIndexes(const storage::Tuple *tuple, ItemPointer location) {
  for (auto index : indexes) {
    if (index->InsertEntry(tuple, location) == false) {
      throw ExecutorException("Failed to insert tuple into index");
    }
  }
}

bool DataTable::TryInsertInIndexes(const storage::Tuple *tuple, ItemPointer location) {

  int index_count = GetIndexCount();
  for (int index_itr = index_count - 1; index_itr >= 0; --index_itr) {
    auto index = GetIndex(index_itr);

    // No need to check if it does not have unique keys
    if(index->HasUniqueKeys() == false) {
      bool status = index->InsertEntry(tuple, location);
      if (status == true)
        continue;<commit_msg>Fixed index constraint exception.<commit_after>/*-------------------------------------------------------------------------
 *
 * table.cpp
 * file description
 *
 * Copyright(c) 2015, CMU
 *
 * /n-store/src/storage/table.cpp
 *
 *-------------------------------------------------------------------------
 */

#include "backend/storage/data_table.h"
#include "backend/storage/database.h"

#include "backend/common/exception.h"
#include "backend/index/index.h"
#include "backend/common/logger.h"

#include <mutex>

namespace peloton {
namespace storage {

DataTable::DataTable(catalog::Schema *schema,
                     AbstractBackend *backend,
                     std::string table_name,
                     oid_t table_oid,
                     size_t tuples_per_tilegroup)
: AbstractTable(table_oid, table_name, schema),
  backend(backend),
  tuples_per_tilegroup(tuples_per_tilegroup) {

  // Create a tile group.
  AddDefaultTileGroup();

}

DataTable::~DataTable() {

  // clean up tile groups
  oid_t tile_group_count = GetTileGroupCount();
  for(oid_t tile_group_itr = 0 ; tile_group_itr < tile_group_count; tile_group_itr++){
    auto tile_group = GetTileGroup(tile_group_itr);
    delete tile_group;
  }

  // clean up indices
  for (auto index : indexes) {
    delete index;
  }

  // clean up foreign keys
  for (auto foreign_key : foreign_keys) {
    delete foreign_key;
  }

  // table owns its backend
  // TODO: Should we really be doing this here?
  delete backend;

  // AbstractTable cleans up the schema
}

//===--------------------------------------------------------------------===//
// TUPLE OPERATIONS
//===--------------------------------------------------------------------===//

ItemPointer DataTable::InsertTuple(txn_id_t transaction_id,
                                   const storage::Tuple *tuple,
                                   bool update) {

  assert(tuple);

  // (A) Not NULL checks
  if (CheckNulls(tuple) == false) {
    throw ConstraintException("Not NULL constraint violated : " + tuple->GetInfo());
    return ItemPointer();
  }

  TileGroup *tile_group = nullptr;
  oid_t tuple_slot = INVALID_OID;
  oid_t tile_group_offset = INVALID_OID;

  while (tuple_slot == INVALID_OID) {

    // (B) Figure out last tile group
    {
      std::lock_guard<std::mutex> lock(table_mutex);
      tile_group_offset = GetTileGroupCount()-1;
      LOG_TRACE("Tile group offset :: %d \n", tile_group_offset);
    }

    // (C) Try to insert
    tile_group = GetTileGroup(tile_group_offset);
    tuple_slot = tile_group->InsertTuple(transaction_id, tuple);
    if (tuple_slot == INVALID_OID) {
      AddDefaultTileGroup();
    }
  }

  // Return Location
  ItemPointer location = ItemPointer(tile_group->GetTileGroupId(), tuple_slot);

  // Index checks and updates
  if (update == false) {
    if (TryInsertInIndexes(tuple, location) == false) {
      tile_group->ReclaimTuple(tuple_slot);
      LOG_INFO("Index constraint violated : %s\n", tuple->GetInfo().c_str());
      return INVALID_ITEMPOINTER;
    }
  }
  else {
    // just do a blind insert
    InsertInIndexes(tuple, location);
    return location;
  }

  return location;
}

void DataTable::InsertInIndexes(const storage::Tuple *tuple, ItemPointer location) {
  for (auto index : indexes) {
    if (index->InsertEntry(tuple, location) == false) {
      location = INVALID_ITEMPOINTER;
      LOG_INFO("Failed to insert tuple into index : %s \n",  tuple->GetInfo().c_str());
    }
  }
}

bool DataTable::TryInsertInIndexes(const storage::Tuple *tuple, ItemPointer location) {

  int index_count = GetIndexCount();
  for (int index_itr = index_count - 1; index_itr >= 0; --index_itr) {
    auto index = GetIndex(index_itr);

    // No need to check if it does not have unique keys
    if(index->HasUniqueKeys() == false) {
      bool status = index->InsertEntry(tuple, location);
      if (status == true)
        continue;
{'fraction_non_alphanumeric': 0.1785983421250942, 'fraction_numerical': 0.002009545340366742, 'mean_word_length': 2.3082675529705026, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4313489', 'n_tokens_mistral': 2359, 'n_tokens_neox': 2283, 'n_words': 569}