Beispiel #1
0
Status getQueryColumnsExternal(const std::string& manager_path,
                               const std::string& query,
                               TableColumns& columns) {
  // Make sure the extension path exists, and is writable.
  auto status = extensionPathActive(manager_path);
  if (!status.ok()) {
    return status;
  }

  ExtensionResponse response;
  try {
    auto client = EXManagerClient(manager_path);
    client.get()->getQueryColumns(response, query);
  } catch (const std::exception& e) {
    return Status(1, "Extension call failed: " + std::string(e.what()));
  }

  // Translate response map: {string: string} to a vector: pair(name, type).
  for (const auto& column : response.response) {
    for (const auto& col : column) {
      columns.push_back(
          std::make_tuple(col.first, columnTypeName(col.second), DEFAULT));
    }
  }

  return Status(response.status.code, response.status.message);
}
Beispiel #2
0
std::string columnDefinition(const PluginResponse& response) {
  TableColumns columns;
  for (const auto& column : response) {
    columns.push_back(make_pair(column.at("name"), column.at("type")));
  }
  return columnDefinition(columns);
}
Beispiel #3
0
 TableColumns columns() const {
   TableColumns cols;
   for (int i = 0; i < 20; i++) {
     cols.push_back({"test_" + std::to_string(i), INTEGER_TYPE});
   }
   return cols;
 }
Status getQueryColumnsInternal(const std::string& q,
                               TableColumns& columns,
                               sqlite3* db) {
  // Turn the query into a prepared statement
  sqlite3_stmt* stmt{nullptr};
  auto rc = sqlite3_prepare_v2(
      db, q.c_str(), static_cast<int>(q.length() + 1), &stmt, nullptr);
  if (rc != SQLITE_OK || stmt == nullptr) {
    if (stmt != nullptr) {
      sqlite3_finalize(stmt);
    }
    return Status(1, sqlite3_errmsg(db));
  }

  // Get column count
  auto num_columns = sqlite3_column_count(stmt);
  TableColumns results;
  results.reserve(num_columns);

  // Get column names and types
  Status status = Status();
  bool unknown_type = false;
  for (int i = 0; i < num_columns; ++i) {
    auto col_name = sqlite3_column_name(stmt, i);
    auto col_type = sqlite3_column_decltype(stmt, i);

    if (col_name == nullptr) {
      status = Status(1, "Could not get column type");
      break;
    }

    if (col_type == nullptr) {
      // Types are only returned for table columns (not expressions).
      col_type = "UNKNOWN";
      unknown_type = true;
    }
    results.push_back(std::make_tuple(
        col_name, columnTypeName(col_type), ColumnOptions::DEFAULT));
  }

  // An unknown type means we have to parse the plan and SQLite opcodes.
  if (unknown_type) {
    QueryPlanner planner(q, db);
    planner.applyTypes(results);
  }

  if (status.ok()) {
    columns = std::move(results);
  }

  sqlite3_finalize(stmt);
  return status;
}
Status ATCConfigParserPlugin::update(const std::string& source,
                                     const ParserConfig& config) {
  auto cv = config.find(kParserKey);
  if (cv == config.end()) {
    return Status(1, "No configuration for ATC (Auto Table Construction)");
  }
  auto obj = data_.getObject();

  data_.copyFrom(cv->second.doc(), obj);
  data_.add(kParserKey, obj);

  const auto& ac_tables = data_.doc()[kParserKey];
  auto tables = RegistryFactory::get().registry("table");
  auto registered = registeredATCTables();

  for (const auto& ac_table : ac_tables.GetObject()) {
    std::string table_name{ac_table.name.GetString()};
    auto params = ac_table.value.GetObject();

    std::string query{params.HasMember("query") && params["query"].IsString()
                          ? params["query"].GetString()
                          : ""};
    std::string path{params.HasMember("path") && params["path"].IsString()
                         ? params["path"].GetString()
                         : ""};
    std::string platform{params.HasMember("platform") &&
                                 params["platform"].IsString()
                             ? params["platform"].GetString()
                             : ""};

    if (query.empty() || path.empty()) {
      LOG(WARNING) << "ATC Table: " << table_name << " is misconfigured";
      continue;
    }

    if (!checkPlatform(platform)) {
      VLOG(1) << "Skipping ATC table: " << table_name
              << " because platform doesn't match";
      continue;
    }

    TableColumns columns;
    std::string columns_value;
    columns_value.reserve(256);

    for (const auto& column : params["columns"].GetArray()) {
      columns.push_back(make_tuple(
          std::string(column.GetString()), TEXT_TYPE, ColumnOptions::DEFAULT));
      columns_value += std::string(column.GetString()) + ",";
    }

    registered.erase(table_name);
    std::string table_settings{table_name + query + columns_value + path};
    std::string old_setting;
    auto s = getDatabaseValue(
        kPersistentSettings, kDatabaseKeyPrefix + table_name, old_setting);

    // The ATC table hasn't changed so we skip ahead
    if (table_settings == old_setting) {
      continue;
    }

    // Remove the old table to replace with the new one
    s = removeATCTables({table_name});
    if (!s.ok()) {
      LOG(WARNING) << "ATC table overrides core table; Refusing registration";
      continue;
    }

    s = setDatabaseValue(
        kPersistentSettings, kDatabaseKeyPrefix + table_name, table_settings);

    if (!s.ok()) {
      LOG(WARNING) << "Could not write to database";
      continue;
    }

    s = tables->add(
        table_name, std::make_shared<ATCPlugin>(path, columns, query), true);

    if (!s.ok()) {
      LOG(WARNING) << s.getMessage();
      deleteDatabaseValue(kPersistentSettings, kDatabaseKeyPrefix + table_name);
      continue;
    }

    PluginResponse resp;
    Registry::call(
        "sql", "sql", {{"action", "attach"}, {"table", table_name}}, resp);
    LOG(INFO) << "Registered ATC table: " << table_name;
  }

  if (registered.size() > 0) {
    VLOG(1)
        << "Removing any ATC tables that were removed in this configuration "
           "change";
    removeATCTables(registered);
  }
  return Status();
}