OmniSciDB  a987f07e93
 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 2123 of file ParserNode.h.

Constructor & Destructor Documentation

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

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

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

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

References UNREACHABLE.

2127  : InsertStmt(t, c) {
2128  UNREACHABLE() << "Legacy inserts should not be called anymore";
2129  }
InsertStmt(std::string *t, std::list< std::string * > *c)
Definition: ParserNode.h:2080
#define UNREACHABLE()
Definition: Logger.h:333

Member Function Documentation

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

Implements Parser::InsertStmt.

Definition at line 2450 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().

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

2675  {
2676  if (read_only_mode) {
2677  throw std::runtime_error("INSERT values invalid in read only mode.");
2678  }
2679  auto execute_read_lock =
2683  auto& catalog = session.getCatalog();
2684  const auto td_with_lock =
2686  catalog, *table_);
2689  *table_)) {
2690  throw std::runtime_error("User has no insert privileges on " + *table_ + ".");
2691  }
2692  Analyzer::Query query;
2693  analyze(catalog, query);
2694 
2695  // Take an insert data write lock, which prevents concurrent inserts.
2696  const auto insert_data_lock =
2698 
2699  // NOTE(max): we do the same checks as below just a few calls earlier in analyze().
2700  // Do we keep those intentionally to make sure nothing changed in between w/o
2701  // catalog locks or is it just a duplicate work?
2702  auto td = td_with_lock();
2703  CHECK(td);
2704  if (td->isView) {
2705  throw std::runtime_error("Singleton inserts on views is not supported.");
2706  }
2708 
2710  RelAlgExecutor ra_executor(executor.get(), catalog);
2711 
2712  if (!leafs_connector_) {
2713  leafs_connector_ = std::make_unique<Fragmenter_Namespace::LocalInsertConnector>();
2714  }
2716  try {
2717  ra_executor.executeSimpleInsert(query, insert_data_loader, session);
2718  } catch (...) {
2719  try {
2720  leafs_connector_->rollback(session, td->tableId);
2721  } catch (std::exception& e) {
2722  LOG(ERROR) << "An error occurred during insert rollback attempt. Table id: "
2723  << td->tableId << ", Error: " << e.what();
2724  }
2725  throw;
2726  }
2727  if (!td->isTemporaryTable()) {
2728  leafs_connector_->checkpoint(session, td->tableId);
2729  }
2730 }
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
static WriteLock getWriteLockForTable(Catalog_Namespace::Catalog &cat, const std::string &table_name)
Definition: LockMgrImpl.h:225
#define LOG(tag)
Definition: Logger.h:283
static const AccessPrivileges INSERT_INTO_TABLE
Definition: DBObject.h:161
std::unique_ptr< std::string > table_
Definition: ParserNode.h:2096
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:477
std::unique_ptr< Fragmenter_Namespace::InsertDataLoader::InsertConnector > leafs_connector_
Definition: ParserNode.h:2141
Catalog & getCatalog() const
Definition: SessionInfo.h:75
#define CHECK(condition)
Definition: Logger.h:289
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 2131 of file ParserNode.h.

References values_lists_.

2131  {
2132  return values_lists_;
2133  }
std::vector< std::unique_ptr< ValuesList > > values_lists_
Definition: ParserNode.h:2144

Member Data Documentation

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

Definition at line 2141 of file ParserNode.h.

Referenced by execute().

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

Definition at line 2144 of file ParserNode.h.

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


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