OmniSciDB  f632821e96
Parser::AddColumnStmt Class Reference

#include <ParserNode.h>

+ Inheritance diagram for Parser::AddColumnStmt:
+ Collaboration diagram for Parser::AddColumnStmt:

Public Member Functions

 AddColumnStmt (std::string *tab, ColumnDef *coldef)
 
 AddColumnStmt (std::string *tab, std::list< ColumnDef *> *coldefs)
 
void execute (const Catalog_Namespace::SessionInfo &session) override
 
void check_executable (const Catalog_Namespace::SessionInfo &session, const TableDescriptor *td)
 
const std::string * get_table () const
 
- Public Member Functions inherited from Parser::DDLStmt
void setColumnDescriptor (ColumnDescriptor &cd, const ColumnDef *coldef)
 
- Public Member Functions inherited from Parser::Node
virtual ~Node ()
 

Private Attributes

std::unique_ptr< std::string > table
 
std::unique_ptr< ColumnDefcoldef
 
std::list< std::unique_ptr< ColumnDef > > coldefs
 

Detailed Description

Definition at line 1293 of file ParserNode.h.

Constructor & Destructor Documentation

◆ AddColumnStmt() [1/2]

Parser::AddColumnStmt::AddColumnStmt ( std::string *  tab,
ColumnDef coldef 
)
inline

Definition at line 1295 of file ParserNode.h.

1295 : table(tab), coldef(coldef) {}
std::unique_ptr< std::string > table
Definition: ParserNode.h:1308
std::unique_ptr< ColumnDef > coldef
Definition: ParserNode.h:1309

◆ AddColumnStmt() [2/2]

Parser::AddColumnStmt::AddColumnStmt ( std::string *  tab,
std::list< ColumnDef *> *  coldefs 
)
inline

Definition at line 1296 of file ParserNode.h.

1296  : table(tab) {
1297  for (const auto coldef : *coldefs) {
1298  this->coldefs.emplace_back(coldef);
1299  }
1300  delete coldefs;
1301  }
std::list< std::unique_ptr< ColumnDef > > coldefs
Definition: ParserNode.h:1310
std::unique_ptr< std::string > table
Definition: ParserNode.h:1308
std::unique_ptr< ColumnDef > coldef
Definition: ParserNode.h:1309

Member Function Documentation

◆ check_executable()

void Parser::AddColumnStmt::check_executable ( const Catalog_Namespace::SessionInfo session,
const TableDescriptor td 
)

Definition at line 3280 of file ParserNode.cpp.

References Parser::check_alter_table_privilege(), Catalog_Namespace::SessionInfo::getCatalog(), TableDescriptor::isView, table_is_temporary(), and TableDescriptor::tableId.

3281  {
3282  auto& catalog = session.getCatalog();
3283  if (!td) {
3284  throw std::runtime_error("Table " + *table + " does not exist.");
3285  } else {
3286  if (td->isView) {
3287  throw std::runtime_error("Adding columns to a view is not supported.");
3288  }
3289  if (table_is_temporary(td)) {
3290  throw std::runtime_error(
3291  "Adding columns to temporary tables is not yet supported.");
3292  }
3293  };
3294 
3295  check_alter_table_privilege(session, td);
3296 
3297  if (0 == coldefs.size()) {
3298  coldefs.push_back(std::move(coldef));
3299  }
3300 
3301  for (const auto& coldef : coldefs) {
3302  auto& new_column_name = *coldef->get_column_name();
3303  if (catalog.getMetadataForColumn(td->tableId, new_column_name) != nullptr) {
3304  throw std::runtime_error("Column " + new_column_name + " already exists.");
3305  }
3306  }
3307 }
std::list< std::unique_ptr< ColumnDef > > coldefs
Definition: ParserNode.h:1310
std::unique_ptr< std::string > table
Definition: ParserNode.h:1308
Catalog & getCatalog() const
Definition: SessionInfo.h:65
void check_alter_table_privilege(const Catalog_Namespace::SessionInfo &session, const TableDescriptor *td)
bool table_is_temporary(const TableDescriptor *const td)
std::unique_ptr< ColumnDef > coldef
Definition: ParserNode.h:1309
+ Here is the call graph for this function:

◆ execute()

void Parser::AddColumnStmt::execute ( const Catalog_Namespace::SessionInfo session)
overridevirtual

Implements Parser::DDLStmt.

Definition at line 3309 of file ParserNode.cpp.

References CHECK, ColumnDescriptor::columnId, ColumnDescriptor::columnName, ColumnDescriptor::columnType, legacylockmgr::ExecutorOuterLock, Parser::StringLiteral::get_stringval(), Catalog_Namespace::SessionInfo::getCatalog(), Geospatial::GeoTypesFactory::getGeoColumns(), legacylockmgr::LockMgr< MutexType, KeyType >::getMutex(), SQLTypeInfo::is_geometry(), import_export::Importer::set_geo_physical_import_buffer(), and import_export::setup_column_loaders().

3309  {
3310  auto& catalog = session.getCatalog();
3311 
3312  // TODO(adb): the catalog should be handling this locking.
3313  const auto execute_write_lock = mapd_unique_lock<mapd_shared_mutex>(
3316 
3317  const auto td_with_lock =
3319  catalog, *table, true);
3320  const auto td = td_with_lock();
3321 
3322  check_executable(session, td);
3323 
3324  CHECK(td->fragmenter);
3325  if (std::dynamic_pointer_cast<Fragmenter_Namespace::SortedOrderFragmenter>(
3326  td->fragmenter)) {
3327  throw std::runtime_error(
3328  "Adding columns to a table is not supported when using the \"sort_column\" "
3329  "option.");
3330  }
3331 
3332  // Do not take a data write lock, as the fragmenter may call `deleteFragments` during
3333  // a cap operation. Note that the schema write lock will prevent concurrent inserts
3334  // along with all other queries.
3335 
3336  catalog.getSqliteConnector().query("BEGIN TRANSACTION");
3337  try {
3338  std::map<const std::string, const ColumnDescriptor> cds;
3339  std::map<const int, const ColumnDef*> cid_coldefs;
3340  for (const auto& coldef : coldefs) {
3341  ColumnDescriptor cd;
3342  setColumnDescriptor(cd, coldef.get());
3343  catalog.addColumn(*td, cd);
3344  cds.emplace(*coldef->get_column_name(), cd);
3345  cid_coldefs.emplace(cd.columnId, coldef.get());
3346 
3347  // expand geo column to phy columns
3348  if (cd.columnType.is_geometry()) {
3349  std::list<ColumnDescriptor> phy_geo_columns;
3350  catalog.expandGeoColumn(cd, phy_geo_columns);
3351  for (auto& cd : phy_geo_columns) {
3352  catalog.addColumn(*td, cd);
3353  cds.emplace(cd.columnName, cd);
3354  cid_coldefs.emplace(cd.columnId, nullptr);
3355  }
3356  }
3357  }
3358 
3359  std::unique_ptr<import_export::Loader> loader(new import_export::Loader(catalog, td));
3360  auto import_buffers = import_export::setup_column_loaders(td, loader.get());
3361  loader->setReplicating(true);
3362 
3363  // set_geo_physical_import_buffer below needs a sorted import_buffers
3364  std::sort(import_buffers.begin(),
3365  import_buffers.end(),
3366  [](decltype(import_buffers[0])& a, decltype(import_buffers[0])& b) {
3367  return a->getColumnDesc()->columnId < b->getColumnDesc()->columnId;
3368  });
3369 
3370  size_t nrows = td->fragmenter->getNumRows();
3371  // if sharded, get total nrows from all sharded tables
3372  if (td->nShards > 0) {
3373  const auto physical_tds = catalog.getPhysicalTablesDescriptors(td);
3374  nrows = 0;
3375  std::for_each(physical_tds.begin(), physical_tds.end(), [&nrows](const auto& td) {
3376  nrows += td->fragmenter->getNumRows();
3377  });
3378  }
3379  if (nrows > 0) {
3380  int skip_physical_cols = 0;
3381  for (const auto cit : cid_coldefs) {
3382  const auto cd = catalog.getMetadataForColumn(td->tableId, cit.first);
3383  const auto coldef = cit.second;
3384  const auto column_constraint = coldef ? coldef->get_column_constraint() : nullptr;
3385  std::string defaultval = "";
3386  if (column_constraint) {
3387  auto defaultlp = column_constraint->get_defaultval();
3388  auto defaultsp = dynamic_cast<const StringLiteral*>(defaultlp);
3389  defaultval = defaultsp ? *defaultsp->get_stringval()
3390  : defaultlp ? defaultlp->to_string() : "";
3391  }
3392  bool isnull = column_constraint ? (0 == defaultval.size()) : true;
3393  if (boost::to_upper_copy<std::string>(defaultval) == "NULL") {
3394  isnull = true;
3395  }
3396 
3397  if (isnull) {
3398  if (column_constraint && column_constraint->get_notnull()) {
3399  throw std::runtime_error("Default value required for column " +
3400  cd->columnName + " (NULL value not supported)");
3401  }
3402  }
3403 
3404  for (auto it = import_buffers.begin(); it < import_buffers.end(); ++it) {
3405  auto& import_buffer = *it;
3406  if (cd->columnId == import_buffer->getColumnDesc()->columnId) {
3407  if (coldef != nullptr ||
3408  skip_physical_cols-- <= 0) { // skip non-null phy col
3409  import_buffer->add_value(
3410  cd, defaultval, isnull, import_export::CopyParams(), nrows);
3411  if (cd->columnType.is_geometry()) {
3412  std::vector<double> coords, bounds;
3413  std::vector<int> ring_sizes, poly_rings;
3414  int render_group = 0;
3415  SQLTypeInfo tinfo{cd->columnType};
3417  tinfo,
3418  coords,
3419  bounds,
3420  ring_sizes,
3421  poly_rings,
3422  false)) {
3423  throw std::runtime_error("Bad geometry data: '" + defaultval + "'");
3424  }
3425  size_t col_idx = 1 + std::distance(import_buffers.begin(), it);
3427  cd,
3428  import_buffers,
3429  col_idx,
3430  coords,
3431  bounds,
3432  ring_sizes,
3433  poly_rings,
3434  render_group,
3435  nrows);
3436  // skip following phy cols
3437  skip_physical_cols = cd->columnType.get_physical_cols();
3438  }
3439  }
3440  break;
3441  }
3442  }
3443  }
3444  }
3445 
3446  if (!loader->loadNoCheckpoint(import_buffers, nrows)) {
3447  throw std::runtime_error("loadNoCheckpoint failed!");
3448  }
3449  catalog.roll(true);
3450  loader->checkpoint();
3451  catalog.getSqliteConnector().query("END TRANSACTION");
3452  } catch (...) {
3453  catalog.roll(false);
3454  catalog.getSqliteConnector().query("ROLLBACK TRANSACTION");
3455  throw;
3456  }
3457 }
std::list< std::unique_ptr< ColumnDef > > coldefs
Definition: ParserNode.h:1310
void setColumnDescriptor(ColumnDescriptor &cd, const ColumnDef *coldef)
std::unique_ptr< std::string > table
Definition: ParserNode.h:1308
std::vector< std::unique_ptr< TypedImportBuffer > > setup_column_loaders(const TableDescriptor *td, Loader *loader)
Definition: Importer.cpp:5149
static void set_geo_physical_import_buffer(const Catalog_Namespace::Catalog &catalog, const ColumnDescriptor *cd, std::vector< std::unique_ptr< TypedImportBuffer >> &import_buffers, size_t &col_idx, std::vector< double > &coords, std::vector< double > &bounds, std::vector< int > &ring_sizes, std::vector< int > &poly_rings, int render_group, const int64_t replicate_count=0)
Definition: Importer.cpp:1421
Catalog & getCatalog() const
Definition: SessionInfo.h:65
int get_physical_cols() const
Definition: sqltypes.h:280
specifies the content in-memory of a row in the column metadata table
void check_executable(const Catalog_Namespace::SessionInfo &session, const TableDescriptor *td)
static bool getGeoColumns(const std::string &wkt_or_wkb_hex, SQLTypeInfo &ti, std::vector< double > &coords, std::vector< double > &bounds, std::vector< int > &ring_sizes, std::vector< int > &poly_rings, const bool promote_poly_to_mpoly=false)
Definition: Types.cpp:701
bool is_geometry() const
Definition: sqltypes.h:429
static std::shared_ptr< MutexType > getMutex(const LockType lockType, const KeyType &key)
Definition: LegacyLockMgr.h:51
std::unique_ptr< ColumnDef > coldef
Definition: ParserNode.h:1309
#define CHECK(condition)
Definition: Logger.h:197
SQLTypeInfo columnType
std::string columnName
+ Here is the call graph for this function:

◆ get_table()

const std::string* Parser::AddColumnStmt::get_table ( ) const
inline

Definition at line 1305 of file ParserNode.h.

1305 { return table.get(); }
std::unique_ptr< std::string > table
Definition: ParserNode.h:1308

Member Data Documentation

◆ coldef

std::unique_ptr<ColumnDef> Parser::AddColumnStmt::coldef
private

Definition at line 1309 of file ParserNode.h.

◆ coldefs

std::list<std::unique_ptr<ColumnDef> > Parser::AddColumnStmt::coldefs
private

Definition at line 1310 of file ParserNode.h.

◆ table

std::unique_ptr<std::string> Parser::AddColumnStmt::table
private

Definition at line 1308 of file ParserNode.h.


The documentation for this class was generated from the following files: