OmniSciDB  fe05a0c208
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
anonymous_namespace{DBHandler.cpp} Namespace Reference

Classes

struct  ForceDisconnect
 
struct  ProjectionTokensForCompletion
 

Functions

SessionMap::iterator get_session_from_map (const TSessionId &session, SessionMap &session_map)
 
ProjectionTokensForCompletion extract_projection_tokens_for_completion (const std::string &sql)
 
std::string dump_table_col_names (const std::map< std::string, std::vector< std::string >> &table_col_names)
 
void check_table_not_sharded (const TableDescriptor *td)
 
void check_valid_column_names (const std::list< const ColumnDescriptor * > &descs, const std::vector< std::string > &column_names)
 
std::vector< int > column_ids_by_names (const std::list< const ColumnDescriptor * > &descs, const std::vector< std::string > &column_names)
 
size_t get_column_size (const TColumn &column)
 
RecordBatchVector loadArrowStream (const std::string &stream)
 
void add_vsi_network_prefix (std::string &path)
 
void add_vsi_geo_prefix (std::string &path)
 
void add_vsi_archive_prefix (std::string &path)
 
std::string remove_vsi_prefixes (const std::string &path_in)
 
bool path_is_relative (const std::string &path)
 
bool path_has_valid_filename (const std::string &path)
 
bool is_a_supported_geo_file (const std::string &path, bool include_gz)
 
bool is_a_supported_archive_file (const std::string &path)
 
std::string find_first_geo_file_in_archive (const std::string &archive_path, const import_export::CopyParams &copy_params)
 
bool is_local_file (const std::string &file_path)
 
void validate_import_file_path_if_local (const std::string &file_path)
 
std::unique_ptr
< Catalog_Namespace::CustomExpression
create_custom_expr_from_thrift_obj (const TCustomExpression &t_custom_expr)
 
TCustomExpression create_thrift_obj_from_custom_expr (const CustomExpression &custom_expr)
 
bool TTypeInfo_IsGeo (const TDatumType::type &t)
 

Function Documentation

void anonymous_namespace{DBHandler.cpp}::add_vsi_archive_prefix ( std::string &  path)

Definition at line 3625 of file DBHandler.cpp.

Referenced by DBHandler::detect_column_types(), DBHandler::get_all_files_in_archive(), DBHandler::get_first_geo_file_in_archive(), DBHandler::get_layers_in_geo_file(), and DBHandler::import_geo_table().

3625  {
3626  // check for compressed file or file bundle
3627  if (boost::iends_with(path, ".zip")) {
3628  // zip archive
3629  path = "/vsizip/" + path;
3630  } else if (boost::iends_with(path, ".tar") || boost::iends_with(path, ".tgz") ||
3631  boost::iends_with(path, ".tar.gz")) {
3632  // tar archive (compressed or uncompressed)
3633  path = "/vsitar/" + path;
3634  }
3635 }

+ Here is the caller graph for this function:

void anonymous_namespace{DBHandler.cpp}::add_vsi_geo_prefix ( std::string &  path)

Definition at line 3618 of file DBHandler.cpp.

Referenced by DBHandler::detect_column_types(), DBHandler::get_layers_in_geo_file(), and DBHandler::import_geo_table().

3618  {
3619  // single gzip'd file (not an archive)?
3620  if (boost::iends_with(path, ".gz") && !boost::iends_with(path, ".tar.gz")) {
3621  path = "/vsigzip/" + path;
3622  }
3623 }

+ Here is the caller graph for this function:

void anonymous_namespace{DBHandler.cpp}::add_vsi_network_prefix ( std::string &  path)

Definition at line 3596 of file DBHandler.cpp.

References Geospatial::GDAL::supportsNetworkFileAccess(), and THROW_MAPD_EXCEPTION.

Referenced by DBHandler::detect_column_types(), DBHandler::get_all_files_in_archive(), DBHandler::get_first_geo_file_in_archive(), DBHandler::get_layers_in_geo_file(), and DBHandler::import_geo_table().

3596  {
3597  // do we support network file access?
3598  bool gdal_network = Geospatial::GDAL::supportsNetworkFileAccess();
3599 
3600  // modify head of filename based on source location
3601  if (boost::istarts_with(path, "http://") || boost::istarts_with(path, "https://")) {
3602  if (!gdal_network) {
3604  "HTTP geo file import not supported! Update to GDAL 2.2 or later!");
3605  }
3606  // invoke GDAL CURL virtual file reader
3607  path = "/vsicurl/" + path;
3608  } else if (boost::istarts_with(path, "s3://")) {
3609  if (!gdal_network) {
3611  "S3 geo file import not supported! Update to GDAL 2.2 or later!");
3612  }
3613  // invoke GDAL S3 virtual file reader
3614  boost::replace_first(path, "s3://", "/vsis3/");
3615  }
3616 }
#define THROW_MAPD_EXCEPTION(errstr)
Definition: DBHandler.cpp:110
static bool supportsNetworkFileAccess()
Definition: GDAL.cpp:109

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void anonymous_namespace{DBHandler.cpp}::check_table_not_sharded ( const TableDescriptor td)

Definition at line 2752 of file DBHandler.cpp.

References TableDescriptor::nShards.

Referenced by DBHandler::prepare_loader_generic().

2752  {
2753  if (td && td->nShards) {
2754  throw std::runtime_error("Cannot import a sharded table directly to a leaf");
2755  }
2756 }

+ Here is the caller graph for this function:

void anonymous_namespace{DBHandler.cpp}::check_valid_column_names ( const std::list< const ColumnDescriptor * > &  descs,
const std::vector< std::string > &  column_names 
)

Definition at line 2758 of file DBHandler.cpp.

References setup::name, THROW_MAPD_EXCEPTION, and to_lower().

Referenced by DBHandler::prepare_loader_generic().

2759  {
2760  std::unordered_set<std::string> unique_names;
2761  for (const auto& name : column_names) {
2762  auto lower_name = to_lower(name);
2763  if (unique_names.find(lower_name) != unique_names.end()) {
2764  THROW_MAPD_EXCEPTION("Column " + name + " is mentioned multiple times");
2765  } else {
2766  unique_names.insert(lower_name);
2767  }
2768  }
2769  for (const auto& cd : descs) {
2770  auto iter = unique_names.find(to_lower(cd->columnName));
2771  if (iter != unique_names.end()) {
2772  unique_names.erase(iter);
2773  }
2774  }
2775  if (!unique_names.empty()) {
2776  THROW_MAPD_EXCEPTION("Column " + *unique_names.begin() + " does not exist");
2777  }
2778 }
std::string to_lower(const std::string &str)
string name
Definition: setup.in.py:72
#define THROW_MAPD_EXCEPTION(errstr)
Definition: DBHandler.cpp:110

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::vector<int> anonymous_namespace{DBHandler.cpp}::column_ids_by_names ( const std::list< const ColumnDescriptor * > &  descs,
const std::vector< std::string > &  column_names 
)

Definition at line 2784 of file DBHandler.cpp.

References generate_TableFunctionsFactory_init::j, THROW_MAPD_EXCEPTION, and to_lower().

Referenced by DBHandler::load_table(), DBHandler::load_table_binary(), DBHandler::load_table_binary_arrow(), and DBHandler::load_table_binary_columnar_internal().

2785  {
2786  std::vector<int> desc_to_column_ids;
2787  if (column_names.empty()) {
2788  int col_idx = 0;
2789  for (const auto& cd : descs) {
2790  if (!cd->isGeoPhyCol) {
2791  desc_to_column_ids.push_back(col_idx);
2792  ++col_idx;
2793  }
2794  }
2795  } else {
2796  for (const auto& cd : descs) {
2797  if (!cd->isGeoPhyCol) {
2798  bool found = false;
2799  for (size_t j = 0; j < column_names.size(); ++j) {
2800  if (to_lower(cd->columnName) == to_lower(column_names[j])) {
2801  found = true;
2802  desc_to_column_ids.push_back(j);
2803  break;
2804  }
2805  }
2806  if (!found) {
2807  if (!cd->columnType.get_notnull()) {
2808  desc_to_column_ids.push_back(-1);
2809  } else {
2810  THROW_MAPD_EXCEPTION("Column '" + cd->columnName +
2811  "' cannot be omitted due to NOT NULL constraint");
2812  }
2813  }
2814  }
2815  }
2816  }
2817  return desc_to_column_ids;
2818 }
std::string to_lower(const std::string &str)
#define THROW_MAPD_EXCEPTION(errstr)
Definition: DBHandler.cpp:110

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::unique_ptr<Catalog_Namespace::CustomExpression> anonymous_namespace{DBHandler.cpp}::create_custom_expr_from_thrift_obj ( const TCustomExpression &  t_custom_expr)

Definition at line 3960 of file DBHandler.cpp.

References CHECK.

Referenced by DBHandler::create_custom_expression().

3961  {
3962  CHECK(t_custom_expr.data_source_type == TDataSourceType::type::TABLE)
3963  << "Unexpected data source type: "
3964  << static_cast<int>(t_custom_expr.data_source_type);
3965  DataSourceType data_source_type = DataSourceType::TABLE;
3966  return std::make_unique<CustomExpression>(t_custom_expr.name,
3967  t_custom_expr.expression_json,
3968  data_source_type,
3969  t_custom_expr.data_source_id);
3970 }
#define CHECK(condition)
Definition: Logger.h:203

+ Here is the caller graph for this function:

TCustomExpression anonymous_namespace{DBHandler.cpp}::create_thrift_obj_from_custom_expr ( const CustomExpression &  custom_expr)

Definition at line 3972 of file DBHandler.cpp.

References CHECK, Catalog_Namespace::CustomExpression::data_source_id, Catalog_Namespace::CustomExpression::data_source_type, Catalog_Namespace::CustomExpression::expression_json, Catalog_Namespace::CustomExpression::id, Catalog_Namespace::CustomExpression::is_deleted, and Catalog_Namespace::CustomExpression::name.

Referenced by DBHandler::get_custom_expressions().

3973  {
3974  TCustomExpression t_custom_expr;
3975  t_custom_expr.id = custom_expr.id;
3976  t_custom_expr.name = custom_expr.name;
3977  t_custom_expr.expression_json = custom_expr.expression_json;
3978  t_custom_expr.data_source_id = custom_expr.data_source_id;
3979  t_custom_expr.is_deleted = custom_expr.is_deleted;
3980  CHECK(custom_expr.data_source_type == DataSourceType::TABLE)
3981  << "Unexpected data source type: "
3982  << static_cast<int>(custom_expr.data_source_type);
3983  t_custom_expr.data_source_type = TDataSourceType::type::TABLE;
3984  return t_custom_expr;
3985 }
#define CHECK(condition)
Definition: Logger.h:203

+ Here is the caller graph for this function:

std::string anonymous_namespace{DBHandler.cpp}::dump_table_col_names ( const std::map< std::string, std::vector< std::string >> &  table_col_names)

Definition at line 2145 of file DBHandler.cpp.

Referenced by DBHandler::get_result_row_for_pixel().

2146  {
2147  std::ostringstream oss;
2148  for (const auto& [table_name, col_names] : table_col_names) {
2149  oss << ":" << table_name;
2150  for (const auto& col_name : col_names) {
2151  oss << "," << col_name;
2152  }
2153  }
2154  return oss.str();
2155 }

+ Here is the caller graph for this function:

ProjectionTokensForCompletion anonymous_namespace{DBHandler.cpp}::extract_projection_tokens_for_completion ( const std::string &  sql)

Definition at line 1545 of file DBHandler.cpp.

References split(), and to_upper().

Referenced by DBHandler::get_completion_hints().

1546  {
1547  boost::regex id_regex{R"(([[:alnum:]]|_|\.)+)",
1548  boost::regex::extended | boost::regex::icase};
1549  boost::sregex_token_iterator tok_it(sql.begin(), sql.end(), id_regex, 0);
1550  boost::sregex_token_iterator end;
1551  std::unordered_set<std::string> uc_column_names;
1552  std::unordered_set<std::string> uc_column_table_qualifiers;
1553  for (; tok_it != end; ++tok_it) {
1554  std::string column_name = *tok_it;
1555  std::vector<std::string> column_tokens;
1556  boost::split(column_tokens, column_name, boost::is_any_of("."));
1557  if (column_tokens.size() == 2) {
1558  // If the column name is qualified, take user's word.
1559  uc_column_table_qualifiers.insert(to_upper(column_tokens.front()));
1560  } else {
1561  uc_column_names.insert(to_upper(column_name));
1562  }
1563  }
1564  return {uc_column_names, uc_column_table_qualifiers};
1565 }
std::vector< std::string > split(std::string_view str, std::string_view delim, std::optional< size_t > maxsplit)
split apart a string into a vector of substrings
std::string to_upper(const std::string &str)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

std::string anonymous_namespace{DBHandler.cpp}::find_first_geo_file_in_archive ( const std::string &  archive_path,
const import_export::CopyParams copy_params 
)

Definition at line 3706 of file DBHandler.cpp.

References import_export::Importer::gdalGetAllFilesInArchive(), logger::INFO, is_a_supported_geo_file(), LOG, and remove_vsi_prefixes().

Referenced by DBHandler::detect_column_types(), DBHandler::get_first_geo_file_in_archive(), DBHandler::get_layers_in_geo_file(), and DBHandler::import_geo_table().

3707  {
3708  // get the recursive list of all files in the archive
3709  std::vector<std::string> files =
3710  import_export::Importer::gdalGetAllFilesInArchive(archive_path, copy_params);
3711 
3712  // report the list
3713  LOG(INFO) << "Found " << files.size() << " files in Archive "
3714  << remove_vsi_prefixes(archive_path);
3715  for (const auto& file : files) {
3716  LOG(INFO) << " " << file;
3717  }
3718 
3719  // scan the list for the first candidate file
3720  bool found_suitable_file = false;
3721  std::string file_name;
3722  for (const auto& file : files) {
3723  if (is_a_supported_geo_file(file, false)) {
3724  file_name = file;
3725  found_suitable_file = true;
3726  break;
3727  }
3728  }
3729 
3730  // if we didn't find anything
3731  if (!found_suitable_file) {
3732  LOG(INFO) << "Failed to find any supported geo files in Archive: " +
3733  remove_vsi_prefixes(archive_path);
3734  file_name.clear();
3735  }
3736 
3737  // done
3738  return file_name;
3739 }
#define LOG(tag)
Definition: Logger.h:194
std::string remove_vsi_prefixes(const std::string &path_in)
Definition: DBHandler.cpp:3637
static std::vector< std::string > gdalGetAllFilesInArchive(const std::string &archive_path, const CopyParams &copy_params)
Definition: Importer.cpp:4814
bool is_a_supported_geo_file(const std::string &path, bool include_gz)
Definition: DBHandler.cpp:3675

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

size_t anonymous_namespace{DBHandler.cpp}::get_column_size ( const TColumn &  column)

Definition at line 2944 of file DBHandler.cpp.

Referenced by DBHandler::load_table_binary_columnar_internal().

2944  {
2945  if (!column.nulls.empty()) {
2946  return column.nulls.size();
2947  } else {
2948  // it is a very bold estimate but later we check it against REAL data
2949  // and if this function returns a wrong result (e.g. both int and string
2950  // vectors are filled with values), we get an error
2951  return column.data.int_col.size() + column.data.arr_col.size() +
2952  column.data.real_col.size() + column.data.str_col.size();
2953  }
2954 }

+ Here is the caller graph for this function:

SessionMap::iterator anonymous_namespace{DBHandler.cpp}::get_session_from_map ( const TSessionId &  session,
SessionMap session_map 
)

Definition at line 123 of file DBHandler.cpp.

References THROW_MAPD_EXCEPTION.

Referenced by DBHandler::expire_idle_sessions_unsafe(), and DBHandler::get_session_it_unsafe().

124  {
125  auto session_it = session_map.find(session);
126  if (session_it == session_map.end()) {
127  THROW_MAPD_EXCEPTION("Session not valid.");
128  }
129  return session_it;
130 }
#define THROW_MAPD_EXCEPTION(errstr)
Definition: DBHandler.cpp:110

+ Here is the caller graph for this function:

bool anonymous_namespace{DBHandler.cpp}::is_a_supported_archive_file ( const std::string &  path)

Definition at line 3693 of file DBHandler.cpp.

References path_has_valid_filename().

Referenced by DBHandler::detect_column_types(), DBHandler::get_all_files_in_archive(), DBHandler::get_first_geo_file_in_archive(), DBHandler::get_layers_in_geo_file(), and DBHandler::import_geo_table().

3693  {
3694  if (!path_has_valid_filename(path)) {
3695  return false;
3696  }
3697  if (boost::iends_with(path, ".zip") && !boost::iends_with(path, ".gdb.zip")) {
3698  return true;
3699  } else if (boost::iends_with(path, ".tar") || boost::iends_with(path, ".tgz") ||
3700  boost::iends_with(path, ".tar.gz")) {
3701  return true;
3702  }
3703  return false;
3704 }
bool path_has_valid_filename(const std::string &path)
Definition: DBHandler.cpp:3667

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool anonymous_namespace{DBHandler.cpp}::is_a_supported_geo_file ( const std::string &  path,
bool  include_gz 
)

Definition at line 3675 of file DBHandler.cpp.

References path_has_valid_filename().

Referenced by DBHandler::detect_column_types(), find_first_geo_file_in_archive(), DBHandler::get_layers_in_geo_file(), and DBHandler::import_geo_table().

3675  {
3676  if (!path_has_valid_filename(path)) {
3677  return false;
3678  }
3679  if (include_gz) {
3680  if (boost::iends_with(path, ".geojson.gz") || boost::iends_with(path, ".json.gz")) {
3681  return true;
3682  }
3683  }
3684  if (boost::iends_with(path, ".shp") || boost::iends_with(path, ".geojson") ||
3685  boost::iends_with(path, ".json") || boost::iends_with(path, ".kml") ||
3686  boost::iends_with(path, ".kmz") || boost::iends_with(path, ".gdb") ||
3687  boost::iends_with(path, ".gdb.zip")) {
3688  return true;
3689  }
3690  return false;
3691 }
bool path_has_valid_filename(const std::string &path)
Definition: DBHandler.cpp:3667

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool anonymous_namespace{DBHandler.cpp}::is_local_file ( const std::string &  file_path)

Definition at line 3741 of file DBHandler.cpp.

Referenced by validate_import_file_path_if_local().

3741  {
3742  return (!boost::istarts_with(file_path, "s3://") &&
3743  !boost::istarts_with(file_path, "http://") &&
3744  !boost::istarts_with(file_path, "https://"));
3745 }

+ Here is the caller graph for this function:

RecordBatchVector anonymous_namespace{DBHandler.cpp}::loadArrowStream ( const std::string &  stream)

Definition at line 3182 of file DBHandler.cpp.

References ARROW_ASSIGN_OR_THROW, ARROW_THRIFT_THROW_NOT_OK, logger::ERROR, and LOG.

Referenced by DBHandler::load_table_binary_arrow().

3182  {
3183  RecordBatchVector batches;
3184  try {
3185  // TODO(wesm): Make this simpler in general, see ARROW-1600
3186  auto stream_buffer =
3187  std::make_shared<arrow::Buffer>(reinterpret_cast<const uint8_t*>(stream.c_str()),
3188  static_cast<int64_t>(stream.size()));
3189 
3190  arrow::io::BufferReader buf_reader(stream_buffer);
3191  std::shared_ptr<arrow::RecordBatchReader> batch_reader;
3192  ARROW_ASSIGN_OR_THROW(batch_reader,
3193  arrow::ipc::RecordBatchStreamReader::Open(&buf_reader));
3194 
3195  while (true) {
3196  std::shared_ptr<arrow::RecordBatch> batch;
3197  // Read batch (zero-copy) from the stream
3198  ARROW_THRIFT_THROW_NOT_OK(batch_reader->ReadNext(&batch));
3199  if (batch == nullptr) {
3200  break;
3201  }
3202  batches.emplace_back(std::move(batch));
3203  }
3204  } catch (const std::exception& e) {
3205  LOG(ERROR) << "Error parsing Arrow stream: " << e.what() << ". Import aborted";
3206  }
3207  return batches;
3208 }
#define LOG(tag)
Definition: Logger.h:194
#define ARROW_ASSIGN_OR_THROW(lhs, rexpr)
Definition: ArrowUtil.h:60
std::vector< std::shared_ptr< arrow::RecordBatch >> RecordBatchVector
Definition: DBHandler.cpp:3167
#define ARROW_THRIFT_THROW_NOT_OK(s)
Definition: DBHandler.cpp:3169

+ Here is the caller graph for this function:

bool anonymous_namespace{DBHandler.cpp}::path_has_valid_filename ( const std::string &  path)

Definition at line 3667 of file DBHandler.cpp.

References logger::filename().

Referenced by is_a_supported_archive_file(), and is_a_supported_geo_file().

3667  {
3668  auto filename = boost::filesystem::path(path).filename().string();
3669  if (filename.size() == 0 || filename[0] == '.' || filename[0] == '/') {
3670  return false;
3671  }
3672  return true;
3673 }
std::string filename(char const *path)
Definition: Logger.cpp:62

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool anonymous_namespace{DBHandler.cpp}::path_is_relative ( const std::string &  path)

Definition at line 3659 of file DBHandler.cpp.

Referenced by DBHandler::detect_column_types(), DBHandler::get_all_files_in_archive(), DBHandler::get_first_geo_file_in_archive(), DBHandler::get_layers_in_geo_file(), and DBHandler::import_geo_table().

3659  {
3660  if (boost::istarts_with(path, "s3://") || boost::istarts_with(path, "http://") ||
3661  boost::istarts_with(path, "https://")) {
3662  return false;
3663  }
3664  return !boost::filesystem::path(path).is_absolute();
3665 }

+ Here is the caller graph for this function:

std::string anonymous_namespace{DBHandler.cpp}::remove_vsi_prefixes ( const std::string &  path_in)

Definition at line 3637 of file DBHandler.cpp.

Referenced by find_first_geo_file_in_archive().

3637  {
3638  std::string path(path_in);
3639 
3640  // these will be first
3641  if (boost::istarts_with(path, "/vsizip/")) {
3642  boost::replace_first(path, "/vsizip/", "");
3643  } else if (boost::istarts_with(path, "/vsitar/")) {
3644  boost::replace_first(path, "/vsitar/", "");
3645  } else if (boost::istarts_with(path, "/vsigzip/")) {
3646  boost::replace_first(path, "/vsigzip/", "");
3647  }
3648 
3649  // then these
3650  if (boost::istarts_with(path, "/vsicurl/")) {
3651  boost::replace_first(path, "/vsicurl/", "");
3652  } else if (boost::istarts_with(path, "/vsis3/")) {
3653  boost::replace_first(path, "/vsis3/", "s3://");
3654  }
3655 
3656  return path;
3657 }

+ Here is the caller graph for this function:

bool anonymous_namespace{DBHandler.cpp}::TTypeInfo_IsGeo ( const TDatumType::type &  t)

Definition at line 4662 of file DBHandler.cpp.

References LINESTRING, MULTIPOLYGON, POINT, and POLYGON.

Referenced by DBHandler::import_geo_table().

4662  {
4663  return (t == TDatumType::POLYGON || t == TDatumType::MULTIPOLYGON ||
4665 }
#define LINESTRING
#define MULTIPOLYGON
#define POINT
char * t
#define POLYGON

+ Here is the caller graph for this function:

void anonymous_namespace{DBHandler.cpp}::validate_import_file_path_if_local ( const std::string &  file_path)

Definition at line 3747 of file DBHandler.cpp.

References ddl_utils::IMPORT, is_local_file(), and ddl_utils::validate_allowed_file_path().

Referenced by DBHandler::detect_column_types(), DBHandler::get_all_files_in_archive(), DBHandler::get_first_geo_file_in_archive(), DBHandler::get_layers_in_geo_file(), DBHandler::import_geo_table(), and DBHandler::import_table().

3747  {
3748  if (is_local_file(file_path)) {
3750  }
3751 }
void validate_allowed_file_path(const std::string &file_path, const DataTransferType data_transfer_type, const bool allow_wildcards)
Definition: DdlUtils.cpp:634
bool is_local_file(const std::string &file_path)
Definition: DBHandler.cpp:3741

+ Here is the call graph for this function:

+ Here is the caller graph for this function: