OmniSciDB  085a039ca4
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Parser::InsertValuesStmt Class Reference

#include <ParserNode.h>

+ Inheritance diagram for Parser::InsertValuesStmt:
+ Collaboration diagram for Parser::InsertValuesStmt:

Public Member Functions

 InsertValuesStmt (const rapidjson::Value &payload)
 
 InsertValuesStmt (std::string *t, std::list< std::string * > *c, std::list< Expr * > *v)
 
const std::vector
< std::unique_ptr< ValuesList > > & 
get_value_lists () const
 
void analyze (const Catalog_Namespace::Catalog &catalog, Analyzer::Query &query) const override
 
void execute (const Catalog_Namespace::SessionInfo &session)
 
- Public Member Functions inherited from Parser::InsertStmt
 InsertStmt (std::string *t, std::list< std::string * > *c)
 
const std::string * get_table () const
 
const std::list
< std::unique_ptr< std::string > > & 
get_column_list () const
 
- Public Member Functions inherited from Parser::Node
virtual ~Node ()
 

Public Attributes

Fragmenter_Namespace::InsertDataLoader::InsertConnectorleafs_connector_ = nullptr
 

Private Attributes

std::vector< std::unique_ptr
< ValuesList > > 
values_lists_
 

Additional Inherited Members

- Protected Attributes inherited from Parser::InsertStmt
std::unique_ptr< std::string > table_
 
std::list< std::unique_ptr
< std::string > > 
column_list_
 

Detailed Description

Definition at line 2103 of file ParserNode.h.

Constructor & Destructor Documentation

Parser::InsertValuesStmt::InsertValuesStmt ( const rapidjson::Value &  payload)

Definition at line 2395 of file ParserNode.cpp.

References CHECK, Parser::InsertStmt::column_list_, json_str(), Parser::anonymous_namespace{ParserNode.cpp}::parse_insert_array_literal(), Parser::anonymous_namespace{ParserNode.cpp}::parse_insert_literal(), Parser::InsertStmt::table_, and values_lists_.

2396  : InsertStmt(nullptr, nullptr) {
2397  CHECK(payload.HasMember("name"));
2398  table_ = std::make_unique<std::string>(json_str(payload["name"]));
2399 
2400  if (payload.HasMember("columns")) {
2401  CHECK(payload["columns"].IsArray());
2402  for (auto& column : payload["columns"].GetArray()) {
2403  std::string s = json_str(column);
2404  column_list_.emplace_back(std::make_unique<std::string>(s));
2405  }
2406  }
2407 
2408  CHECK(payload.HasMember("values") && payload["values"].IsArray());
2409  auto tuples = payload["values"].GetArray();
2410  if (tuples.Empty()) {
2411  throw std::runtime_error("Values statement cannot be empty");
2412  }
2413  values_lists_.reserve(tuples.Size());
2414  for (const auto& json_tuple : tuples) {
2415  auto values_list = std::make_unique<ValuesList>();
2416  CHECK(json_tuple.IsArray());
2417  auto tuple = json_tuple.GetArray();
2418  for (const auto& value : tuple) {
2419  CHECK(value.IsObject());
2420  if (value.HasMember("array")) {
2421  values_list->push_back(parse_insert_array_literal(value["array"]));
2422  } else {
2423  values_list->push_back(parse_insert_literal(value));
2424  }
2425  }
2426  values_lists_.push_back(std::move(values_list));
2427  }
2428 }
InsertStmt(std::string *t, std::list< std::string * > *c)
Definition: ParserNode.h:2060
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
std::unique_ptr< std::string > table_
Definition: ParserNode.h:2076
ArrayLiteral * parse_insert_array_literal(const rapidjson::Value &array)
Literal * parse_insert_literal(const rapidjson::Value &literal)
std::list< std::unique_ptr< std::string > > column_list_
Definition: ParserNode.h:2077
#define CHECK(condition)
Definition: Logger.h:223
std::vector< std::unique_ptr< ValuesList > > values_lists_
Definition: ParserNode.h:2123

+ Here is the call graph for this function:

Parser::InsertValuesStmt::InsertValuesStmt ( std::string *  t,
std::list< std::string * > *  c,
std::list< Expr * > *  v 
)
inline

Definition at line 2106 of file ParserNode.h.

References UNREACHABLE.

2107  : InsertStmt(t, c) {
2108  UNREACHABLE() << "Legacy inserts should not be called anymore";
2109  }
InsertStmt(std::string *t, std::list< std::string * > *c)
Definition: ParserNode.h:2060
#define UNREACHABLE()
Definition: Logger.h:267

Member Function Documentation

void Parser::InsertValuesStmt::analyze ( const Catalog_Namespace::Catalog catalog,
Analyzer::Query query 
) const
overridevirtual

Implements Parser::InsertStmt.

Definition at line 2430 of file ParserNode.cpp.

References Parser::InsertStmt::analyze(), CHECK, CHECK_EQ, Parser::InsertStmt::column_list_, Geospatial::compress_coords(), Datum::doubleval, Analyzer::Query::get_result_col_list(), Analyzer::Query::get_result_table_id(), Analyzer::Query::get_values_lists(), Catalog_Namespace::Catalog::getAllColumnMetadataForTable(), Geospatial::GeoTypesFactory::getGeoColumns(), Catalog_Namespace::Catalog::getMetadataForColumn(), Datum::intval, is_null(), kARRAY, kCAST, kDOUBLE, kINT, kLINESTRING, kMULTIPOLYGON, kPOINT, kPOLYGON, kTINYINT, NULL_ARRAY_DOUBLE, NULL_DOUBLE, Datum::tinyintval, to_string(), and values_lists_.

Referenced by execute().

2431  {
2432  InsertStmt::analyze(catalog, query);
2433  size_t list_size = values_lists_[0]->get_value_list().size();
2434  if (!column_list_.empty()) {
2435  if (list_size != column_list_.size()) {
2436  throw std::runtime_error(
2437  "Numbers of columns and values don't match for the "
2438  "insert.");
2439  }
2440  } else {
2441  const auto tableId = query.get_result_table_id();
2442  const std::list<const ColumnDescriptor*> non_phys_cols =
2443  catalog.getAllColumnMetadataForTable(tableId, false, false, false);
2444  if (non_phys_cols.size() != list_size) {
2445  throw std::runtime_error(
2446  "Number of columns in table does not match the list of values given in the "
2447  "insert.");
2448  }
2449  }
2450  std::vector<const ColumnDescriptor*> cds;
2451  cds.reserve(query.get_result_col_list().size());
2452  for (auto id : query.get_result_col_list()) {
2453  const auto* cd = catalog.getMetadataForColumn(query.get_result_table_id(), id);
2454  CHECK(cd);
2455  cds.push_back(cd);
2456  }
2457  auto& query_values_lists = query.get_values_lists();
2458  query_values_lists.resize(values_lists_.size());
2459  for (size_t i = 0; i < values_lists_.size(); ++i) {
2460  const auto& values_list = values_lists_[i]->get_value_list();
2461  if (values_list.size() != list_size) {
2462  throw std::runtime_error(
2463  "Insert values lists should be of the same size. Expected: " +
2464  std::to_string(list_size) + ", Got: " + std::to_string(values_list.size()));
2465  }
2466  auto& query_values_list = query_values_lists[i];
2467  size_t cds_id = 0;
2468  for (auto& v : values_list) {
2469  auto e = v->analyze(catalog, query);
2470  const auto* cd = cds[cds_id];
2471  const auto& col_ti = cd->columnType;
2472  if (col_ti.get_notnull()) {
2473  auto c = std::dynamic_pointer_cast<Analyzer::Constant>(e);
2474  if (c != nullptr && c->get_is_null()) {
2475  throw std::runtime_error("Cannot insert NULL into column " + cd->columnName);
2476  }
2477  }
2478  e = e->add_cast(col_ti);
2479  query_values_list.emplace_back(new Analyzer::TargetEntry("", e, false));
2480  ++cds_id;
2481 
2482  if (col_ti.get_physical_cols() > 0) {
2483  CHECK(cd->columnType.is_geometry());
2484  auto c = dynamic_cast<const Analyzer::Constant*>(e.get());
2485  if (!c) {
2486  auto uoper = std::dynamic_pointer_cast<Analyzer::UOper>(e);
2487  if (uoper && uoper->get_optype() == kCAST) {
2488  c = dynamic_cast<const Analyzer::Constant*>(uoper->get_operand());
2489  }
2490  }
2491  bool is_null = false;
2492  std::string* geo_string{nullptr};
2493  if (c) {
2494  is_null = c->get_is_null();
2495  if (!is_null) {
2496  geo_string = c->get_constval().stringval;
2497  }
2498  }
2499  if (!is_null && !geo_string) {
2500  throw std::runtime_error("Expecting a WKT or WKB hex string for column " +
2501  cd->columnName);
2502  }
2503  std::vector<double> coords;
2504  std::vector<double> bounds;
2505  std::vector<int> ring_sizes;
2506  std::vector<int> poly_rings;
2507  int render_group =
2508  0; // @TODO simon.eves where to get render_group from in this context?!
2509  SQLTypeInfo import_ti{cd->columnType};
2510  if (!is_null) {
2512  *geo_string, import_ti, coords, bounds, ring_sizes, poly_rings)) {
2513  throw std::runtime_error("Cannot read geometry to insert into column " +
2514  cd->columnName);
2515  }
2516  if (coords.empty()) {
2517  // Importing from geo_string WKT resulted in empty coords: dealing with a NULL
2518  is_null = true;
2519  }
2520  if (cd->columnType.get_type() != import_ti.get_type()) {
2521  // allow POLYGON to be inserted into MULTIPOLYGON column
2522  if (!(import_ti.get_type() == SQLTypes::kPOLYGON &&
2523  cd->columnType.get_type() == SQLTypes::kMULTIPOLYGON)) {
2524  throw std::runtime_error(
2525  "Imported geometry doesn't match the type of column " + cd->columnName);
2526  }
2527  }
2528  } else {
2529  // Special case for NULL POINT, push NULL representation to coords
2530  if (cd->columnType.get_type() == kPOINT) {
2531  if (!coords.empty()) {
2532  throw std::runtime_error(
2533  "NULL POINT with unexpected coordinates in column " + cd->columnName);
2534  }
2535  coords.push_back(NULL_ARRAY_DOUBLE);
2536  coords.push_back(NULL_DOUBLE);
2537  }
2538  }
2539 
2540  // TODO: check if import SRID matches columns SRID, may need to transform before
2541  // inserting
2542 
2543  const auto* cd_coords = cds[cds_id];
2544  CHECK_EQ(cd_coords->columnType.get_type(), kARRAY);
2545  CHECK_EQ(cd_coords->columnType.get_subtype(), kTINYINT);
2546  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2547  if (!is_null || cd->columnType.get_type() == kPOINT) {
2548  auto compressed_coords = Geospatial::compress_coords(coords, col_ti);
2549  for (auto cc : compressed_coords) {
2550  Datum d;
2551  d.tinyintval = cc;
2552  auto e = makeExpr<Analyzer::Constant>(kTINYINT, false, d);
2553  value_exprs.push_back(e);
2554  }
2555  }
2556  query_values_list.emplace_back(new Analyzer::TargetEntry(
2557  "",
2558  makeExpr<Analyzer::Constant>(cd_coords->columnType, is_null, value_exprs),
2559  false));
2560  ++cds_id;
2561 
2562  if (cd->columnType.get_type() == kPOLYGON ||
2563  cd->columnType.get_type() == kMULTIPOLYGON) {
2564  // Put ring sizes array into separate physical column
2565  const auto* cd_ring_sizes = cds[cds_id];
2566  CHECK(cd_ring_sizes);
2567  CHECK_EQ(cd_ring_sizes->columnType.get_type(), kARRAY);
2568  CHECK_EQ(cd_ring_sizes->columnType.get_subtype(), kINT);
2569  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2570  if (!is_null) {
2571  for (auto c : ring_sizes) {
2572  Datum d;
2573  d.intval = c;
2574  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
2575  value_exprs.push_back(e);
2576  }
2577  }
2578  query_values_list.emplace_back(new Analyzer::TargetEntry(
2579  "",
2580  makeExpr<Analyzer::Constant>(
2581  cd_ring_sizes->columnType, is_null, value_exprs),
2582  false));
2583  ++cds_id;
2584 
2585  if (cd->columnType.get_type() == kMULTIPOLYGON) {
2586  // Put poly_rings array into separate physical column
2587  const auto* cd_poly_rings = cds[cds_id];
2588  CHECK(cd_poly_rings);
2589  CHECK_EQ(cd_poly_rings->columnType.get_type(), kARRAY);
2590  CHECK_EQ(cd_poly_rings->columnType.get_subtype(), kINT);
2591  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2592  if (!is_null) {
2593  for (auto c : poly_rings) {
2594  Datum d;
2595  d.intval = c;
2596  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
2597  value_exprs.push_back(e);
2598  }
2599  }
2600  query_values_list.emplace_back(new Analyzer::TargetEntry(
2601  "",
2602  makeExpr<Analyzer::Constant>(
2603  cd_poly_rings->columnType, is_null, value_exprs),
2604  false));
2605  ++cds_id;
2606  }
2607  }
2608 
2609  if (cd->columnType.get_type() == kLINESTRING ||
2610  cd->columnType.get_type() == kPOLYGON ||
2611  cd->columnType.get_type() == kMULTIPOLYGON) {
2612  const auto* cd_bounds = cds[cds_id];
2613  CHECK(cd_bounds);
2614  CHECK_EQ(cd_bounds->columnType.get_type(), kARRAY);
2615  CHECK_EQ(cd_bounds->columnType.get_subtype(), kDOUBLE);
2616  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2617  if (!is_null) {
2618  for (auto b : bounds) {
2619  Datum d;
2620  d.doubleval = b;
2621  auto e = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
2622  value_exprs.push_back(e);
2623  }
2624  }
2625  query_values_list.emplace_back(new Analyzer::TargetEntry(
2626  "",
2627  makeExpr<Analyzer::Constant>(cd_bounds->columnType, is_null, value_exprs),
2628  false));
2629  ++cds_id;
2630  }
2631 
2632  if (cd->columnType.get_type() == kPOLYGON ||
2633  cd->columnType.get_type() == kMULTIPOLYGON) {
2634  // Put render group into separate physical column
2635  const auto* cd_render_group = cds[cds_id];
2636  CHECK(cd_render_group);
2637  CHECK_EQ(cd_render_group->columnType.get_type(), kINT);
2638  Datum d;
2639  d.intval = render_group;
2640  query_values_list.emplace_back(new Analyzer::TargetEntry(
2641  "",
2642  makeExpr<Analyzer::Constant>(cd_render_group->columnType, is_null, d),
2643  false));
2644  ++cds_id;
2645  }
2646  }
2647  }
2648  }
2649 }
int8_t tinyintval
Definition: sqltypes.h:212
#define CHECK_EQ(x, y)
Definition: Logger.h:231
#define NULL_DOUBLE
Definition: Analyzer.h:2387
const std::vector< std::vector< std::shared_ptr< TargetEntry > > > & get_values_lists() const
Definition: Analyzer.h:2436
Definition: sqldefs.h:49
void analyze(const Catalog_Namespace::Catalog &catalog, Analyzer::Query &query) const override=0
int32_t intval
Definition: sqltypes.h:214
std::string to_string(char const *&&v)
std::vector< uint8_t > compress_coords(const std::vector< double > &coords, const SQLTypeInfo &ti)
Definition: Compression.cpp:52
CONSTEXPR DEVICE bool is_null(const T &value)
const ColumnDescriptor * getMetadataForColumn(int tableId, const std::string &colName) const
int get_result_table_id() const
Definition: Analyzer.h:2452
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:937
std::list< const ColumnDescriptor * > getAllColumnMetadataForTable(const int tableId, const bool fetchSystemColumns, const bool fetchVirtualColumns, const bool fetchPhysicalColumns) const
Returns a list of pointers to constant ColumnDescriptor structs for all the columns from a particular...
Definition: Catalog.cpp:1941
std::list< std::unique_ptr< std::string > > column_list_
Definition: ParserNode.h:2077
#define NULL_ARRAY_DOUBLE
#define CHECK(condition)
Definition: Logger.h:223
std::vector< std::unique_ptr< ValuesList > > values_lists_
Definition: ParserNode.h:2123
Definition: sqltypes.h:45
const std::list< int > & get_result_col_list() const
Definition: Analyzer.h:2453
double doubleval
Definition: sqltypes.h:217

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void Parser::InsertValuesStmt::execute ( const Catalog_Namespace::SessionInfo session)

Definition at line 2651 of file ParserNode.cpp.

References analyze(), CHECK, Catalog_Namespace::SessionInfo::checkDBAccessPrivileges(), Fragmenter_Namespace::InsertDataLoader::InsertConnector::checkpoint(), logger::ERROR, legacylockmgr::ExecutorOuterLock, Catalog_Namespace::SessionInfo::getCatalog(), Executor::getExecutor(), legacylockmgr::LockMgr< MutexType, KeyType >::getMutex(), lockmgr::TableLockMgrImpl< InsertDataLockMgr >::getWriteLockForTable(), AccessPrivileges::INSERT_INTO_TABLE, leafs_connector_, LOG, Fragmenter_Namespace::InsertDataLoader::InsertConnector::rollback(), Parser::InsertStmt::table_, TableDBObjectType, Executor::UNITARY_EXECUTOR_ID, and foreign_storage::validate_non_foreign_table_write().

Referenced by heavydb.cursor.Cursor::executemany().

2651  {
2652  auto execute_read_lock = mapd_shared_lock<mapd_shared_mutex>(
2655  auto& catalog = session.getCatalog();
2656  const auto td_with_lock =
2658  catalog, *table_);
2661  *table_)) {
2662  throw std::runtime_error("User has no insert privileges on " + *table_ + ".");
2663  }
2664  Analyzer::Query query;
2665  analyze(catalog, query);
2666 
2667  // Take an insert data write lock, which prevents concurrent inserts.
2668  const auto insert_data_lock =
2670 
2671  // NOTE(max): we do the same checks as below just a few calls earlier in analyze().
2672  // Do we keep those intentionally to make sure nothing changed in between w/o
2673  // catalog locks or is it just a duplicate work?
2674  auto td = td_with_lock();
2675  CHECK(td);
2676  if (td->isView) {
2677  throw std::runtime_error("Singleton inserts on views is not supported.");
2678  }
2680 
2682  RelAlgExecutor ra_executor(executor.get(), catalog);
2683 
2685  if (!leafs_connector_) {
2686  leafs_connector_ = &local_connector;
2687  }
2689  try {
2690  ra_executor.executeSimpleInsert(query, insert_data_loader, session);
2691  } catch (...) {
2692  try {
2693  leafs_connector_->rollback(session, td->tableId);
2694  } catch (std::exception& e) {
2695  LOG(ERROR) << "An error occurred during insert rollback attempt. Table id: "
2696  << td->tableId << ", Error: " << e.what();
2697  }
2698  throw;
2699  }
2700  if (!td->isTemporaryTable()) {
2701  leafs_connector_->checkpoint(session, td->tableId);
2702  }
2703 }
void validate_non_foreign_table_write(const TableDescriptor *table_descriptor)
Definition: FsiUtils.h:22
#define LOG(tag)
Definition: Logger.h:217
static WriteLock getWriteLockForTable(const Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:155
static const AccessPrivileges INSERT_INTO_TABLE
Definition: DBObject.h:163
Fragmenter_Namespace::InsertDataLoader::InsertConnector * leafs_connector_
Definition: ParserNode.h:2120
std::unique_ptr< std::string > table_
Definition: ParserNode.h:2076
static std::shared_ptr< Executor > getExecutor(const ExecutorId id, const std::string &debug_dir="", const std::string &debug_file="", const SystemParameters &system_parameters=SystemParameters())
Definition: Execute.cpp:483
virtual void checkpoint(const Catalog_Namespace::SessionInfo &parent_session_info, int tableId)=0
Catalog & getCatalog() const
Definition: SessionInfo.h:65
static std::shared_ptr< MutexType > getMutex(const LockType lockType, const KeyType &key)
Definition: LegacyLockMgr.h:51
#define CHECK(condition)
Definition: Logger.h:223
virtual void rollback(const Catalog_Namespace::SessionInfo &parent_session_info, int tableId)=0
bool checkDBAccessPrivileges(const DBObjectType &permissionType, const AccessPrivileges &privs, const std::string &objectName="") const
Definition: SessionInfo.cpp:24
void analyze(const Catalog_Namespace::Catalog &catalog, Analyzer::Query &query) const override
static const ExecutorId UNITARY_EXECUTOR_ID
Definition: Execute.h:376

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

const std::vector<std::unique_ptr<ValuesList> >& Parser::InsertValuesStmt::get_value_lists ( ) const
inline

Definition at line 2111 of file ParserNode.h.

References values_lists_.

2111  {
2112  return values_lists_;
2113  }
std::vector< std::unique_ptr< ValuesList > > values_lists_
Definition: ParserNode.h:2123

Member Data Documentation

Fragmenter_Namespace::InsertDataLoader::InsertConnector* Parser::InsertValuesStmt::leafs_connector_ = nullptr

Definition at line 2120 of file ParserNode.h.

Referenced by execute().

std::vector<std::unique_ptr<ValuesList> > Parser::InsertValuesStmt::values_lists_
private

Definition at line 2123 of file ParserNode.h.

Referenced by analyze(), get_value_lists(), and InsertValuesStmt().


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