OmniSciDB  c1a53651b2
 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, bool read_only_mode)
 
- 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

std::unique_ptr
< Fragmenter_Namespace::InsertDataLoader::InsertConnector
leafs_connector_
 

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 2079 of file ParserNode.h.

Constructor & Destructor Documentation

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

Definition at line 2423 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_.

2424  : InsertStmt(nullptr, nullptr) {
2425  CHECK(payload.HasMember("name"));
2426  table_ = std::make_unique<std::string>(json_str(payload["name"]));
2427 
2428  if (payload.HasMember("columns")) {
2429  CHECK(payload["columns"].IsArray());
2430  for (auto& column : payload["columns"].GetArray()) {
2431  std::string s = json_str(column);
2432  column_list_.emplace_back(std::make_unique<std::string>(s));
2433  }
2434  }
2435 
2436  CHECK(payload.HasMember("values") && payload["values"].IsArray());
2437  auto tuples = payload["values"].GetArray();
2438  if (tuples.Empty()) {
2439  throw std::runtime_error("Values statement cannot be empty");
2440  }
2441  values_lists_.reserve(tuples.Size());
2442  for (const auto& json_tuple : tuples) {
2443  auto values_list = std::make_unique<ValuesList>();
2444  CHECK(json_tuple.IsArray());
2445  auto tuple = json_tuple.GetArray();
2446  for (const auto& value : tuple) {
2447  CHECK(value.IsObject());
2448  if (value.HasMember("array")) {
2449  values_list->push_back(parse_insert_array_literal(value["array"]));
2450  } else {
2451  values_list->push_back(parse_insert_literal(value));
2452  }
2453  }
2454  values_lists_.push_back(std::move(values_list));
2455  }
2456 }
InsertStmt(std::string *t, std::list< std::string * > *c)
Definition: ParserNode.h:2036
const std::string json_str(const rapidjson::Value &obj) noexcept
Definition: JsonAccessors.h:44
std::unique_ptr< std::string > table_
Definition: ParserNode.h:2052
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:2053
#define CHECK(condition)
Definition: Logger.h:291
std::vector< std::unique_ptr< ValuesList > > values_lists_
Definition: ParserNode.h:2100

+ 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 2082 of file ParserNode.h.

References UNREACHABLE.

2083  : InsertStmt(t, c) {
2084  UNREACHABLE() << "Legacy inserts should not be called anymore";
2085  }
InsertStmt(std::string *t, std::list< std::string * > *c)
Definition: ParserNode.h:2036
#define UNREACHABLE()
Definition: Logger.h:337

Member Function Documentation

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

Implements Parser::InsertStmt.

Definition at line 2458 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, kMULTILINESTRING, kMULTIPOINT, kMULTIPOLYGON, kPOINT, kPOLYGON, kTINYINT, NULL_ARRAY_DOUBLE, NULL_DOUBLE, Datum::tinyintval, to_string(), and values_lists_.

Referenced by execute().

2459  {
2460  InsertStmt::analyze(catalog, query);
2461  size_t list_size = values_lists_[0]->get_value_list().size();
2462  if (!column_list_.empty()) {
2463  if (list_size != column_list_.size()) {
2464  throw std::runtime_error(
2465  "Numbers of columns and values don't match for the "
2466  "insert.");
2467  }
2468  } else {
2469  const auto tableId = query.get_result_table_id();
2470  const std::list<const ColumnDescriptor*> non_phys_cols =
2471  catalog.getAllColumnMetadataForTable(tableId, false, false, false);
2472  if (non_phys_cols.size() != list_size) {
2473  throw std::runtime_error(
2474  "Number of columns in table does not match the list of values given in the "
2475  "insert.");
2476  }
2477  }
2478  std::vector<const ColumnDescriptor*> cds;
2479  cds.reserve(query.get_result_col_list().size());
2480  for (auto id : query.get_result_col_list()) {
2481  const auto* cd = catalog.getMetadataForColumn(query.get_result_table_id(), id);
2482  CHECK(cd);
2483  cds.push_back(cd);
2484  }
2485  auto& query_values_lists = query.get_values_lists();
2486  query_values_lists.resize(values_lists_.size());
2487  for (size_t i = 0; i < values_lists_.size(); ++i) {
2488  const auto& values_list = values_lists_[i]->get_value_list();
2489  if (values_list.size() != list_size) {
2490  throw std::runtime_error(
2491  "Insert values lists should be of the same size. Expected: " +
2492  std::to_string(list_size) + ", Got: " + std::to_string(values_list.size()));
2493  }
2494  auto& query_values_list = query_values_lists[i];
2495  size_t cds_id = 0;
2496  for (auto& v : values_list) {
2497  auto e = v->analyze(catalog, query);
2498  const auto* cd = cds[cds_id];
2499  const auto& col_ti = cd->columnType;
2500  if (col_ti.get_notnull()) {
2501  auto c = std::dynamic_pointer_cast<Analyzer::Constant>(e);
2502  if (c != nullptr && c->get_is_null()) {
2503  throw std::runtime_error("Cannot insert NULL into column " + cd->columnName);
2504  }
2505  }
2506  e = e->add_cast(col_ti);
2507  query_values_list.emplace_back(new Analyzer::TargetEntry("", e, false));
2508  ++cds_id;
2509 
2510  if (col_ti.get_physical_cols() > 0) {
2511  CHECK(cd->columnType.is_geometry());
2512  auto c = dynamic_cast<const Analyzer::Constant*>(e.get());
2513  if (!c) {
2514  auto uoper = std::dynamic_pointer_cast<Analyzer::UOper>(e);
2515  if (uoper && uoper->get_optype() == kCAST) {
2516  c = dynamic_cast<const Analyzer::Constant*>(uoper->get_operand());
2517  }
2518  }
2519  bool is_null = false;
2520  std::string* geo_string{nullptr};
2521  if (c) {
2522  is_null = c->get_is_null();
2523  if (!is_null) {
2524  geo_string = c->get_constval().stringval;
2525  }
2526  }
2527  if (!is_null && !geo_string) {
2528  throw std::runtime_error("Expecting a WKT or WKB hex string for column " +
2529  cd->columnName);
2530  }
2531  std::vector<double> coords;
2532  std::vector<double> bounds;
2533  std::vector<int> ring_sizes;
2534  std::vector<int> poly_rings;
2535  int render_group =
2536  0; // @TODO simon.eves where to get render_group from in this context?!
2537  SQLTypeInfo import_ti{cd->columnType};
2538  if (!is_null) {
2540  *geo_string, import_ti, coords, bounds, ring_sizes, poly_rings)) {
2541  throw std::runtime_error("Cannot read geometry to insert into column " +
2542  cd->columnName);
2543  }
2544  if (coords.empty()) {
2545  // Importing from geo_string WKT resulted in empty coords: dealing with a NULL
2546  is_null = true;
2547  }
2548  if (cd->columnType.get_type() != import_ti.get_type()) {
2549  // allow POLYGON to be inserted into MULTIPOLYGON column
2550  if (!(import_ti.get_type() == SQLTypes::kPOLYGON &&
2551  cd->columnType.get_type() == SQLTypes::kMULTIPOLYGON)) {
2552  throw std::runtime_error(
2553  "Imported geometry doesn't match the type of column " + cd->columnName);
2554  }
2555  }
2556  } else {
2557  // Special case for NULL POINT, push NULL representation to coords
2558  if (cd->columnType.get_type() == kPOINT) {
2559  if (!coords.empty()) {
2560  throw std::runtime_error(
2561  "NULL POINT with unexpected coordinates in column " + cd->columnName);
2562  }
2563  coords.push_back(NULL_ARRAY_DOUBLE);
2564  coords.push_back(NULL_DOUBLE);
2565  }
2566  }
2567 
2568  // TODO: check if import SRID matches columns SRID, may need to transform before
2569  // inserting
2570 
2571  const auto* cd_coords = cds[cds_id];
2572  CHECK_EQ(cd_coords->columnType.get_type(), kARRAY);
2573  CHECK_EQ(cd_coords->columnType.get_subtype(), kTINYINT);
2574  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2575  if (!is_null || cd->columnType.get_type() == kPOINT) {
2576  auto compressed_coords = Geospatial::compress_coords(coords, col_ti);
2577  for (auto cc : compressed_coords) {
2578  Datum d;
2579  d.tinyintval = cc;
2580  auto e = makeExpr<Analyzer::Constant>(kTINYINT, false, d);
2581  value_exprs.push_back(e);
2582  }
2583  }
2584  query_values_list.emplace_back(new Analyzer::TargetEntry(
2585  "",
2586  makeExpr<Analyzer::Constant>(cd_coords->columnType, is_null, value_exprs),
2587  false));
2588  ++cds_id;
2589 
2590  if (cd->columnType.get_type() == kMULTILINESTRING ||
2591  cd->columnType.get_type() == kPOLYGON ||
2592  cd->columnType.get_type() == kMULTIPOLYGON) {
2593  // Put [linest]ring sizes array into separate physical column
2594  const auto* cd_ring_sizes = cds[cds_id];
2595  CHECK(cd_ring_sizes);
2596  CHECK_EQ(cd_ring_sizes->columnType.get_type(), kARRAY);
2597  CHECK_EQ(cd_ring_sizes->columnType.get_subtype(), kINT);
2598  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2599  if (!is_null) {
2600  for (auto c : ring_sizes) {
2601  Datum d;
2602  d.intval = c;
2603  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
2604  value_exprs.push_back(e);
2605  }
2606  }
2607  query_values_list.emplace_back(new Analyzer::TargetEntry(
2608  "",
2609  makeExpr<Analyzer::Constant>(
2610  cd_ring_sizes->columnType, is_null, value_exprs),
2611  false));
2612  ++cds_id;
2613 
2614  if (cd->columnType.get_type() == kMULTIPOLYGON) {
2615  // Put poly_rings array into separate physical column
2616  const auto* cd_poly_rings = cds[cds_id];
2617  CHECK(cd_poly_rings);
2618  CHECK_EQ(cd_poly_rings->columnType.get_type(), kARRAY);
2619  CHECK_EQ(cd_poly_rings->columnType.get_subtype(), kINT);
2620  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2621  if (!is_null) {
2622  for (auto c : poly_rings) {
2623  Datum d;
2624  d.intval = c;
2625  auto e = makeExpr<Analyzer::Constant>(kINT, false, d);
2626  value_exprs.push_back(e);
2627  }
2628  }
2629  query_values_list.emplace_back(new Analyzer::TargetEntry(
2630  "",
2631  makeExpr<Analyzer::Constant>(
2632  cd_poly_rings->columnType, is_null, value_exprs),
2633  false));
2634  ++cds_id;
2635  }
2636  }
2637 
2638  if (cd->columnType.get_type() == kMULTIPOINT ||
2639  cd->columnType.get_type() == kLINESTRING ||
2640  cd->columnType.get_type() == kMULTILINESTRING ||
2641  cd->columnType.get_type() == kPOLYGON ||
2642  cd->columnType.get_type() == kMULTIPOLYGON) {
2643  const auto* cd_bounds = cds[cds_id];
2644  CHECK(cd_bounds);
2645  CHECK_EQ(cd_bounds->columnType.get_type(), kARRAY);
2646  CHECK_EQ(cd_bounds->columnType.get_subtype(), kDOUBLE);
2647  std::list<std::shared_ptr<Analyzer::Expr>> value_exprs;
2648  if (!is_null) {
2649  for (auto b : bounds) {
2650  Datum d;
2651  d.doubleval = b;
2652  auto e = makeExpr<Analyzer::Constant>(kDOUBLE, false, d);
2653  value_exprs.push_back(e);
2654  }
2655  }
2656  query_values_list.emplace_back(new Analyzer::TargetEntry(
2657  "",
2658  makeExpr<Analyzer::Constant>(cd_bounds->columnType, is_null, value_exprs),
2659  false));
2660  ++cds_id;
2661  }
2662 
2663  if (cd->columnType.get_type() == kPOLYGON ||
2664  cd->columnType.get_type() == kMULTIPOLYGON) {
2665  // Put render group into separate physical column
2666  const auto* cd_render_group = cds[cds_id];
2667  CHECK(cd_render_group);
2668  CHECK_EQ(cd_render_group->columnType.get_type(), kINT);
2669  Datum d;
2670  d.intval = render_group;
2671  query_values_list.emplace_back(new Analyzer::TargetEntry(
2672  "",
2673  makeExpr<Analyzer::Constant>(cd_render_group->columnType, is_null, d),
2674  false));
2675  ++cds_id;
2676  }
2677  }
2678  }
2679  }
2680 }
int8_t tinyintval
Definition: Datum.h:69
#define CHECK_EQ(x, y)
Definition: Logger.h:301
#define NULL_DOUBLE
Definition: Analyzer.h:2752
const std::vector< std::vector< std::shared_ptr< TargetEntry > > > & get_values_lists() const
Definition: Analyzer.h:2801
Definition: sqldefs.h:48
void analyze(const Catalog_Namespace::Catalog &catalog, Analyzer::Query &query) const override=0
int32_t intval
Definition: Datum.h:71
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:2817
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:1079
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:2267
std::list< std::unique_ptr< std::string > > column_list_
Definition: ParserNode.h:2053
#define NULL_ARRAY_DOUBLE
#define CHECK(condition)
Definition: Logger.h:291
std::vector< std::unique_ptr< ValuesList > > values_lists_
Definition: ParserNode.h:2100
Definition: sqltypes.h:62
const std::list< int > & get_result_col_list() const
Definition: Analyzer.h:2818
Definition: Datum.h:67
double doubleval
Definition: Datum.h:74

+ 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,
bool  read_only_mode 
)

Definition at line 2682 of file ParserNode.cpp.

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

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

2683  {
2684  if (read_only_mode) {
2685  throw std::runtime_error("INSERT values invalid in read only mode.");
2686  }
2687  auto execute_read_lock =
2691  auto& catalog = session.getCatalog();
2692  const auto td_with_lock =
2694  catalog, *table_);
2697  *table_)) {
2698  throw std::runtime_error("User has no insert privileges on " + *table_ + ".");
2699  }
2700  Analyzer::Query query;
2701  analyze(catalog, query);
2702 
2703  // Take an insert data write lock, which prevents concurrent inserts.
2704  const auto insert_data_lock =
2706 
2707  // NOTE(max): we do the same checks as below just a few calls earlier in analyze().
2708  // Do we keep those intentionally to make sure nothing changed in between w/o
2709  // catalog locks or is it just a duplicate work?
2710  auto td = td_with_lock();
2711  CHECK(td);
2712  if (td->isView) {
2713  throw std::runtime_error("Singleton inserts on views is not supported.");
2714  }
2716 
2718  RelAlgExecutor ra_executor(executor.get());
2719 
2720  if (!leafs_connector_) {
2721  leafs_connector_ = std::make_unique<Fragmenter_Namespace::LocalInsertConnector>();
2722  }
2724  try {
2725  ra_executor.executeSimpleInsert(query, insert_data_loader, session);
2726  } catch (...) {
2727  try {
2728  leafs_connector_->rollback(session, td->tableId);
2729  } catch (std::exception& e) {
2730  LOG(ERROR) << "An error occurred during insert rollback attempt. Table id: "
2731  << td->tableId << ", Error: " << e.what();
2732  }
2733  throw;
2734  }
2735  if (!td->isTemporaryTable()) {
2736  leafs_connector_->checkpoint(session, td->tableId);
2737  }
2738 }
static std::shared_ptr< WrapperType< MutexType > > getMutex(const LockType lockType, const KeyType &key)
void validate_non_foreign_table_write(const TableDescriptor *table_descriptor)
Definition: FsiUtils.h:22
#define LOG(tag)
Definition: Logger.h:285
static WriteLock getWriteLockForTable(const Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:225
static const AccessPrivileges INSERT_INTO_TABLE
Definition: DBObject.h:161
std::unique_ptr< std::string > table_
Definition: ParserNode.h:2052
std::shared_lock< T > shared_lock
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:475
std::unique_ptr< Fragmenter_Namespace::InsertDataLoader::InsertConnector > leafs_connector_
Definition: ParserNode.h:2097
Catalog & getCatalog() const
Definition: SessionInfo.h:75
#define CHECK(condition)
Definition: Logger.h:291
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:373

+ 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 2087 of file ParserNode.h.

References values_lists_.

2087  {
2088  return values_lists_;
2089  }
std::vector< std::unique_ptr< ValuesList > > values_lists_
Definition: ParserNode.h:2100

Member Data Documentation

std::unique_ptr<Fragmenter_Namespace::InsertDataLoader::InsertConnector> Parser::InsertValuesStmt::leafs_connector_

Definition at line 2097 of file ParserNode.h.

Referenced by execute().

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

Definition at line 2100 of file ParserNode.h.

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


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