diff options
Diffstat (limited to 'src/rgw/driver/dbstore/sqlite')
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/CMakeLists.txt | 16 | ||||
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/connection.cc | 34 | ||||
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/connection.h | 64 | ||||
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/error.cc | 37 | ||||
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/error.h | 81 | ||||
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/sqliteDB.cc | 2996 | ||||
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/sqliteDB.h | 551 | ||||
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/statement.cc | 196 | ||||
-rw-r--r-- | src/rgw/driver/dbstore/sqlite/statement.h | 83 |
9 files changed, 4058 insertions, 0 deletions
diff --git a/src/rgw/driver/dbstore/sqlite/CMakeLists.txt b/src/rgw/driver/dbstore/sqlite/CMakeLists.txt new file mode 100644 index 000000000..909765e30 --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/CMakeLists.txt @@ -0,0 +1,16 @@ +cmake_minimum_required(VERSION 3.14.0) +project(sqlite_db) + +find_package(SQLite3 REQUIRED) + +set(sqlite_db_srcs + sqliteDB.h + sqliteDB.cc) + +include_directories(${CMAKE_INCLUDE_DIR}) + +set(SQLITE_COMPILE_FLAGS "-DSQLITE_THREADSAFE=1") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${SQLITE_COMPILE_FLAGS}") + +add_library(sqlite_db STATIC ${sqlite_db_srcs}) +target_link_libraries(sqlite_db sqlite3 dbstore_lib rgw_common) diff --git a/src/rgw/driver/dbstore/sqlite/connection.cc b/src/rgw/driver/dbstore/sqlite/connection.cc new file mode 100644 index 000000000..143a3a0d5 --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/connection.cc @@ -0,0 +1,34 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include "common/dout.h" +#include "connection.h" +#include "error.h" + +namespace rgw::dbstore::sqlite { + +db_ptr open_database(const char* filename, int flags) +{ + sqlite3* db = nullptr; + const int result = ::sqlite3_open_v2(filename, &db, flags, nullptr); + if (result != SQLITE_OK) { + throw std::system_error(result, sqlite::error_category()); + } + // request extended result codes + (void) ::sqlite3_extended_result_codes(db, 1); + return db_ptr{db}; +} + +} // namespace rgw::dbstore::sqlite diff --git a/src/rgw/driver/dbstore/sqlite/connection.h b/src/rgw/driver/dbstore/sqlite/connection.h new file mode 100644 index 000000000..6088763fd --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/connection.h @@ -0,0 +1,64 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#pragma once + +#include <memory> +#include <sqlite3.h> + +#include <fmt/format.h> + +#include "sqlite/statement.h" + +class DoutPrefixProvider; + +namespace rgw::dbstore::sqlite { + +// owning sqlite3 pointer +struct db_deleter { + void operator()(sqlite3* p) const { ::sqlite3_close(p); } +}; +using db_ptr = std::unique_ptr<sqlite3, db_deleter>; + + +// open the database file or throw on error +db_ptr open_database(const char* filename, int flags); + + +struct Connection { + db_ptr db; + // map of statements, prepared on first use + std::map<std::string_view, stmt_ptr> statements; + + explicit Connection(db_ptr db) : db(std::move(db)) {} +}; + +// sqlite connection factory for ConnectionPool +class ConnectionFactory { + std::string uri; + int flags; + public: + ConnectionFactory(std::string uri, int flags) + : uri(std::move(uri)), flags(flags) {} + + auto operator()(const DoutPrefixProvider* dpp) + -> std::unique_ptr<Connection> + { + auto db = open_database(uri.c_str(), flags); + return std::make_unique<Connection>(std::move(db)); + } +}; + +} // namespace rgw::dbstore::sqlite diff --git a/src/rgw/driver/dbstore/sqlite/error.cc b/src/rgw/driver/dbstore/sqlite/error.cc new file mode 100644 index 000000000..5fe9eb0ae --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/error.cc @@ -0,0 +1,37 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include "error.h" + +namespace rgw::dbstore::sqlite { + +const std::error_category& error_category() +{ + struct category : std::error_category { + const char* name() const noexcept override { + return "dbstore:sqlite"; + } + std::string message(int ev) const override { + return ::sqlite3_errstr(ev); + } + std::error_condition default_error_condition(int code) const noexcept override { + return {code & 0xFF, category()}; + } + }; + static category instance; + return instance; +} + +} // namespace rgw::dbstore::sqlite diff --git a/src/rgw/driver/dbstore/sqlite/error.h b/src/rgw/driver/dbstore/sqlite/error.h new file mode 100644 index 000000000..15396d8ca --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/error.h @@ -0,0 +1,81 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#pragma once + +#include <system_error> +#include <sqlite3.h> + +namespace rgw::dbstore::sqlite { + +// error category for sqlite extended result codes: +// https://www.sqlite.org/rescode.html +const std::error_category& error_category(); + + +// sqlite exception type that carries the extended error code and message +class error : public std::runtime_error { + std::error_code ec; + public: + error(const char* errmsg, std::error_code ec) + : runtime_error(errmsg), ec(ec) {} + error(sqlite3* db, std::error_code ec) : error(::sqlite3_errmsg(db), ec) {} + error(sqlite3* db, int result) : error(db, {result, error_category()}) {} + error(sqlite3* db) : error(db, ::sqlite3_extended_errcode(db)) {} + std::error_code code() const { return ec; } +}; + + +// sqlite error conditions for primary and extended result codes +// +// 'primary' error_conditions will match 'primary' error_codes as well as any +// 'extended' error_codes whose lowest 8 bits match that primary code. for +// example, the error_condition for SQLITE_CONSTRAINT will match the error_codes +// SQLITE_CONSTRAINT and SQLITE_CONSTRAINT_* +enum class errc { + // primary result codes + ok = SQLITE_OK, + busy = SQLITE_BUSY, + constraint = SQLITE_CONSTRAINT, + row = SQLITE_ROW, + done = SQLITE_DONE, + + // extended result codes + primary_key_constraint = SQLITE_CONSTRAINT_PRIMARYKEY, + foreign_key_constraint = SQLITE_CONSTRAINT_FOREIGNKEY, + unique_constraint = SQLITE_CONSTRAINT_UNIQUE, + + // ..add conditions as needed +}; + +inline std::error_code make_error_code(errc e) +{ + return {static_cast<int>(e), error_category()}; +} + +inline std::error_condition make_error_condition(errc e) +{ + return {static_cast<int>(e), error_category()}; +} + +} // namespace rgw::dbstore::sqlite + +namespace std { + +// enable implicit conversions from sqlite::errc to std::error_condition +template<> struct is_error_condition_enum< + rgw::dbstore::sqlite::errc> : public true_type {}; + +} // namespace std diff --git a/src/rgw/driver/dbstore/sqlite/sqliteDB.cc b/src/rgw/driver/dbstore/sqlite/sqliteDB.cc new file mode 100644 index 000000000..dc244c07b --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/sqliteDB.cc @@ -0,0 +1,2996 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#include "sqliteDB.h" + +using namespace std; + +#define SQL_PREPARE(dpp, params, sdb, stmt, ret, Op) \ + do { \ + string schema; \ + schema = Schema(params); \ + sqlite3_prepare_v2 (*sdb, schema.c_str(), \ + -1, &stmt , NULL); \ + if (!stmt) { \ + ldpp_dout(dpp, 0) <<"failed to prepare statement " \ + <<"for Op("<<Op<<"); Errmsg -"\ + <<sqlite3_errmsg(*sdb)<< dendl;\ + ret = -1; \ + goto out; \ + } \ + ldpp_dout(dpp, 20)<<"Successfully Prepared stmt for Op("<<Op \ + <<") schema("<<schema<<") stmt("<<stmt<<")"<< dendl; \ + ret = 0; \ + } while(0); + +#define SQL_BIND_INDEX(dpp, stmt, index, str, sdb) \ + do { \ + index = sqlite3_bind_parameter_index(stmt, str); \ + \ + if (index <=0) { \ + ldpp_dout(dpp, 0) <<"failed to fetch bind parameter"\ + " index for str("<<str<<") in " \ + <<"stmt("<<stmt<<"); Errmsg -" \ + <<sqlite3_errmsg(*sdb)<< dendl; \ + rc = -1; \ + goto out; \ + } \ + ldpp_dout(dpp, 20)<<"Bind parameter index for str(" \ + <<str<<") in stmt("<<stmt<<") is " \ + <<index<< dendl; \ + }while(0); + +#define SQL_BIND_TEXT(dpp, stmt, index, str, sdb) \ + do { \ + rc = sqlite3_bind_text(stmt, index, str, -1, SQLITE_TRANSIENT); \ + if (rc != SQLITE_OK) { \ + ldpp_dout(dpp, 0)<<"sqlite bind text failed for index(" \ + <<index<<"), str("<<str<<") in stmt(" \ + <<stmt<<"); Errmsg - "<<sqlite3_errmsg(*sdb) \ + << dendl; \ + rc = -1; \ + goto out; \ + } \ + ldpp_dout(dpp, 20)<<"Bind parameter text for index(" \ + <<index<<") in stmt("<<stmt<<") is " \ + <<str<< dendl; \ + }while(0); + +#define SQL_BIND_INT(dpp, stmt, index, num, sdb) \ + do { \ + rc = sqlite3_bind_int(stmt, index, num); \ + \ + if (rc != SQLITE_OK) { \ + ldpp_dout(dpp, 0)<<"sqlite bind int failed for index(" \ + <<index<<"), num("<<num<<") in stmt(" \ + <<stmt<<"); Errmsg - "<<sqlite3_errmsg(*sdb) \ + << dendl; \ + rc = -1; \ + goto out; \ + } \ + ldpp_dout(dpp, 20)<<"Bind parameter int for index(" \ + <<index<<") in stmt("<<stmt<<") is " \ + <<num<< dendl; \ + }while(0); + +#define SQL_BIND_BLOB(dpp, stmt, index, blob, size, sdb) \ + do { \ + rc = sqlite3_bind_blob(stmt, index, blob, size, SQLITE_TRANSIENT); \ + \ + if (rc != SQLITE_OK) { \ + ldpp_dout(dpp, 0)<<"sqlite bind blob failed for index(" \ + <<index<<"), blob("<<blob<<") in stmt(" \ + <<stmt<<"); Errmsg - "<<sqlite3_errmsg(*sdb) \ + << dendl; \ + rc = -1; \ + goto out; \ + } \ + }while(0); + +#define SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, param, sdb) \ + do { \ + bufferlist b; \ + encode(param, b); \ + SQL_BIND_BLOB(dpp, stmt, index, b.c_str(), b.length(), sdb); \ + }while(0); + +#define SQL_READ_BLOB(dpp, stmt, index, void_ptr, len) \ + do { \ + void_ptr = NULL; \ + void_ptr = (void *)sqlite3_column_blob(stmt, index); \ + len = sqlite3_column_bytes(stmt, index); \ + \ + if (!void_ptr || len == 0) { \ + ldpp_dout(dpp, 20)<<"Null value for blob index(" \ + <<index<<") in stmt("<<stmt<<") "<< dendl; \ + } \ + }while(0); + +#define SQL_DECODE_BLOB_PARAM(dpp, stmt, index, param, sdb) \ + do { \ + bufferlist b; \ + void *blob; \ + int blob_len = 0; \ + \ + SQL_READ_BLOB(dpp, stmt, index, blob, blob_len); \ + \ + b.append(reinterpret_cast<char *>(blob), blob_len); \ + \ + decode(param, b); \ + }while(0); + +#define SQL_EXECUTE(dpp, params, stmt, cbk, args...) \ + do{ \ + const std::lock_guard<std::mutex> lk(((DBOp*)(this))->mtx); \ + if (!stmt) { \ + ret = Prepare(dpp, params); \ + } \ + \ + if (!stmt) { \ + ldpp_dout(dpp, 0) <<"No prepared statement "<< dendl; \ + goto out; \ + } \ + \ + ret = Bind(dpp, params); \ + if (ret) { \ + ldpp_dout(dpp, 0) <<"Bind parameters failed for stmt(" <<stmt<<") "<< dendl; \ + goto out; \ + } \ + \ + ret = Step(dpp, params->op, stmt, cbk); \ + \ + Reset(dpp, stmt); \ + \ + if (ret) { \ + ldpp_dout(dpp, 0) <<"Execution failed for stmt(" <<stmt<<")"<< dendl; \ + goto out; \ + } \ + }while(0); + +int SQLiteDB::InitPrepareParams(const DoutPrefixProvider *dpp, + DBOpPrepareParams &p_params, + DBOpParams* params) +{ + std::string bucket; + + if (!params) + return -1; + + if (params->user_table.empty()) { + params->user_table = getUserTable(); + } + if (params->user_table.empty()) { + params->user_table = getUserTable(); + } + if (params->bucket_table.empty()) { + params->bucket_table = getBucketTable(); + } + if (params->quota_table.empty()) { + params->quota_table = getQuotaTable(); + } + if (params->lc_entry_table.empty()) { + params->lc_entry_table = getLCEntryTable(); + } + if (params->lc_head_table.empty()) { + params->lc_head_table = getLCHeadTable(); + } + + p_params.user_table = params->user_table; + p_params.bucket_table = params->bucket_table; + p_params.quota_table = params->quota_table; + p_params.lc_entry_table = params->lc_entry_table; + p_params.lc_head_table = params->lc_head_table; + + p_params.op.query_str = params->op.query_str; + + bucket = params->op.bucket.info.bucket.name; + + if (!bucket.empty()) { + if (params->object_table.empty()) { + params->object_table = getObjectTable(bucket); + } + if (params->objectdata_table.empty()) { + params->objectdata_table = getObjectDataTable(bucket); + } + if (params->object_view.empty()) { + params->object_view = getObjectView(bucket); + } + if (params->object_trigger.empty()) { + params->object_trigger = getObjectTrigger(bucket); + } + p_params.object_table = params->object_table; + p_params.objectdata_table = params->objectdata_table; + p_params.object_view = params->object_view; + } + + return 0; +} + +static int list_callback(void *None, int argc, char **argv, char **aname) +{ + int i; + for(i=0; i < argc; i++) { + string arg = argv[i] ? argv[i] : "NULL"; + cout<<aname[i]<<" = "<<arg<<"\n"; + } + return 0; +} + +enum GetUser { + UserID = 0, + Tenant, + NS, + DisplayName, + UserEmail, + AccessKeysID, + AccessKeysSecret, + AccessKeys, + SwiftKeys, + SubUsers, + Suspended, + MaxBuckets, + OpMask, + UserCaps, + Admin, + System, + PlacementName, + PlacementStorageClass, + PlacementTags, + BucketQuota, + TempURLKeys, + UserQuota, + TYPE, + MfaIDs, + AssumedRoleARN, + UserAttrs, + UserVersion, + UserVersionTag, +}; + +enum GetBucket { + BucketName = 0, + Bucket_Tenant, //Tenant + Marker, + BucketID, + Size, + SizeRounded, + CreationTime, + Count, + Bucket_PlacementName, + Bucket_PlacementStorageClass, + OwnerID, + Flags, + Zonegroup, + HasInstanceObj, + Quota, + RequesterPays, + HasWebsite, + WebsiteConf, + SwiftVersioning, + SwiftVerLocation, + MdsearchConfig, + NewBucketInstanceID, + ObjectLock, + SyncPolicyInfoGroups, + BucketAttrs, + BucketVersion, + BucketVersionTag, + Mtime, + Bucket_User_NS +}; + +enum GetObject { + ObjName, + ObjInstance, + ObjNS, + ObjBucketName, + ACLs, + IndexVer, + Tag, + ObjFlags, + VersionedEpoch, + ObjCategory, + Etag, + Owner, + OwnerDisplayName, + StorageClass, + Appendable, + ContentType, + IndexHashSource, + ObjSize, + AccountedSize, + ObjMtime, + Epoch, + ObjTag, + TailTag, + WriteTag, + FakeTag, + ShadowObj, + HasData, + IsVersioned, + VersionNum, + PGVer, + ZoneShortID, + ObjVersion, + ObjVersionTag, + ObjAttrs, + HeadSize, + MaxHeadSize, + ObjID, + TailInstance, + HeadPlacementRuleName, + HeadPlacementRuleStorageClass, + TailPlacementRuleName, + TailPlacementStorageClass, + ManifestPartObjs, + ManifestPartRules, + Omap, + IsMultipart, + MPPartsList, + HeadData, + Versions +}; + +enum GetObjectData { + ObjDataName, + ObjDataInstance, + ObjDataNS, + ObjDataBucketName, + ObjDataID, + MultipartPartStr, + PartNum, + Offset, + ObjDataSize, + ObjDataMtime, + ObjData +}; + +enum GetLCEntry { + LCEntryIndex, + LCEntryBucketName, + LCEntryStartTime, + LCEntryStatus +}; + +enum GetLCHead { + LCHeadIndex, + LCHeadMarker, + LCHeadStartDate +}; + +static int list_user(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) { + if (!stmt) + return -1; + + op.user.uinfo.user_id.tenant = (const char*)sqlite3_column_text(stmt, Tenant); + op.user.uinfo.user_id.id = (const char*)sqlite3_column_text(stmt, UserID); + op.user.uinfo.user_id.ns = (const char*)sqlite3_column_text(stmt, NS); + op.user.uinfo.display_name = (const char*)sqlite3_column_text(stmt, DisplayName); // user_name + op.user.uinfo.user_email = (const char*)sqlite3_column_text(stmt, UserEmail); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, SwiftKeys, op.user.uinfo.swift_keys, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, SubUsers, op.user.uinfo.subusers, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, AccessKeys, op.user.uinfo.access_keys, sdb); + + op.user.uinfo.suspended = sqlite3_column_int(stmt, Suspended); + op.user.uinfo.max_buckets = sqlite3_column_int(stmt, MaxBuckets); + op.user.uinfo.op_mask = sqlite3_column_int(stmt, OpMask); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, UserCaps, op.user.uinfo.caps, sdb); + + op.user.uinfo.admin = sqlite3_column_int(stmt, Admin); + op.user.uinfo.system = sqlite3_column_int(stmt, System); + + op.user.uinfo.default_placement.name = (const char*)sqlite3_column_text(stmt, PlacementName); + + op.user.uinfo.default_placement.storage_class = (const char*)sqlite3_column_text(stmt, PlacementStorageClass); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, PlacementTags, op.user.uinfo.placement_tags, sdb); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, BucketQuota, op.user.uinfo.quota.bucket_quota, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, TempURLKeys, op.user.uinfo.temp_url_keys, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, UserQuota, op.user.uinfo.quota.user_quota, sdb); + + op.user.uinfo.type = sqlite3_column_int(stmt, TYPE); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, MfaIDs, op.user.uinfo.mfa_ids, sdb); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, UserAttrs, op.user.user_attrs, sdb); + op.user.user_version.ver = sqlite3_column_int(stmt, UserVersion); + op.user.user_version.tag = (const char*)sqlite3_column_text(stmt, UserVersionTag); + + return 0; +} + +static int list_bucket(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) { + if (!stmt) + return -1; + + op.bucket.ent.bucket.name = (const char*)sqlite3_column_text(stmt, BucketName); + op.bucket.ent.bucket.tenant = (const char*)sqlite3_column_text(stmt, Bucket_Tenant); + op.bucket.ent.bucket.marker = (const char*)sqlite3_column_text(stmt, Marker); + op.bucket.ent.bucket.bucket_id = (const char*)sqlite3_column_text(stmt, BucketID); + op.bucket.ent.size = sqlite3_column_int(stmt, Size); + op.bucket.ent.size_rounded = sqlite3_column_int(stmt, SizeRounded); + SQL_DECODE_BLOB_PARAM(dpp, stmt, CreationTime, op.bucket.ent.creation_time, sdb); + op.bucket.ent.count = sqlite3_column_int(stmt, Count); + op.bucket.ent.placement_rule.name = (const char*)sqlite3_column_text(stmt, Bucket_PlacementName); + op.bucket.ent.placement_rule.storage_class = (const char*)sqlite3_column_text(stmt, Bucket_PlacementStorageClass); + + op.bucket.info.bucket = op.bucket.ent.bucket; + op.bucket.info.placement_rule = op.bucket.ent.placement_rule; + op.bucket.info.creation_time = op.bucket.ent.creation_time; + + op.bucket.info.owner.id = (const char*)sqlite3_column_text(stmt, OwnerID); + op.bucket.info.owner.tenant = op.bucket.ent.bucket.tenant; + + if (op.name == "GetBucket") { + op.bucket.info.owner.ns = (const char*)sqlite3_column_text(stmt, Bucket_User_NS); + } + + op.bucket.info.flags = sqlite3_column_int(stmt, Flags); + op.bucket.info.zonegroup = (const char*)sqlite3_column_text(stmt, Zonegroup); + op.bucket.info.has_instance_obj = sqlite3_column_int(stmt, HasInstanceObj); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, Quota, op.bucket.info.quota, sdb); + op.bucket.info.requester_pays = sqlite3_column_int(stmt, RequesterPays); + op.bucket.info.has_website = sqlite3_column_int(stmt, HasWebsite); + SQL_DECODE_BLOB_PARAM(dpp, stmt, WebsiteConf, op.bucket.info.website_conf, sdb); + op.bucket.info.swift_versioning = sqlite3_column_int(stmt, SwiftVersioning); + op.bucket.info.swift_ver_location = (const char*)sqlite3_column_text(stmt, SwiftVerLocation); + SQL_DECODE_BLOB_PARAM(dpp, stmt, MdsearchConfig, op.bucket.info.mdsearch_config, sdb); + op.bucket.info.new_bucket_instance_id = (const char*)sqlite3_column_text(stmt, NewBucketInstanceID); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ObjectLock, op.bucket.info.obj_lock, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, SyncPolicyInfoGroups, op.bucket.info.sync_policy, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, BucketAttrs, op.bucket.bucket_attrs, sdb); + op.bucket.bucket_version.ver = sqlite3_column_int(stmt, BucketVersion); + op.bucket.bucket_version.tag = (const char*)sqlite3_column_text(stmt, BucketVersionTag); + + /* Read bucket version into info.objv_tracker.read_ver. No need + * to set write_ver as its not used anywhere. Still keeping its + * value same as read_ver */ + op.bucket.info.objv_tracker.read_version = op.bucket.bucket_version; + op.bucket.info.objv_tracker.write_version = op.bucket.bucket_version; + + SQL_DECODE_BLOB_PARAM(dpp, stmt, Mtime, op.bucket.mtime, sdb); + + op.bucket.list_entries.push_back(op.bucket.ent); + + return 0; +} + +static int list_object(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) { + if (!stmt) + return -1; + + //cout<<sqlite3_column_text(stmt, 0)<<", "; + //cout<<sqlite3_column_text(stmt, 1) << "\n"; + + op.obj.state.exists = true; + op.obj.state.obj.key.name = (const char*)sqlite3_column_text(stmt, ObjName); + op.bucket.info.bucket.name = (const char*)sqlite3_column_text(stmt, ObjBucketName); + op.obj.state.obj.key.instance = (const char*)sqlite3_column_text(stmt, ObjInstance); + op.obj.state.obj.key.ns = (const char*)sqlite3_column_text(stmt, ObjNS); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ACLs, op.obj.acls, sdb); + op.obj.index_ver = sqlite3_column_int(stmt, IndexVer); + op.obj.tag = (const char*)sqlite3_column_text(stmt, Tag); + op.obj.flags = sqlite3_column_int(stmt, ObjFlags); + op.obj.versioned_epoch = sqlite3_column_int(stmt, VersionedEpoch); + op.obj.category = (RGWObjCategory)sqlite3_column_int(stmt, ObjCategory); + op.obj.etag = (const char*)sqlite3_column_text(stmt, Etag); + op.obj.owner = (const char*)sqlite3_column_text(stmt, Owner); + op.obj.owner_display_name = (const char*)sqlite3_column_text(stmt, OwnerDisplayName); + op.obj.storage_class = (const char*)sqlite3_column_text(stmt, StorageClass); + op.obj.appendable = sqlite3_column_int(stmt, Appendable); + op.obj.content_type = (const char*)sqlite3_column_text(stmt, ContentType); + op.obj.state.obj.index_hash_source = (const char*)sqlite3_column_text(stmt, IndexHashSource); + op.obj.state.size = sqlite3_column_int(stmt, ObjSize); + op.obj.state.accounted_size = sqlite3_column_int(stmt, AccountedSize); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ObjMtime, op.obj.state.mtime, sdb); + op.obj.state.epoch = sqlite3_column_int(stmt, Epoch); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ObjTag, op.obj.state.obj_tag, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, TailTag, op.obj.state.tail_tag, sdb); + op.obj.state.write_tag = (const char*)sqlite3_column_text(stmt, WriteTag); + op.obj.state.fake_tag = sqlite3_column_int(stmt, FakeTag); + op.obj.state.shadow_obj = (const char*)sqlite3_column_text(stmt, ShadowObj); + op.obj.state.has_data = sqlite3_column_int(stmt, HasData); + op.obj.is_versioned = sqlite3_column_int(stmt, IsVersioned); + op.obj.version_num = sqlite3_column_int(stmt, VersionNum); + op.obj.state.pg_ver = sqlite3_column_int(stmt, PGVer); + op.obj.state.zone_short_id = sqlite3_column_int(stmt, ZoneShortID); + op.obj.state.objv_tracker.read_version.ver = sqlite3_column_int(stmt, ObjVersion); + op.obj.state.objv_tracker.read_version.tag = (const char*)sqlite3_column_text(stmt, ObjVersionTag); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ObjAttrs, op.obj.state.attrset, sdb); + op.obj.head_size = sqlite3_column_int(stmt, HeadSize); + op.obj.max_head_size = sqlite3_column_int(stmt, MaxHeadSize); + op.obj.obj_id = (const char*)sqlite3_column_text(stmt, ObjID); + op.obj.tail_instance = (const char*)sqlite3_column_text(stmt, TailInstance); + op.obj.head_placement_rule.name = (const char*)sqlite3_column_text(stmt, HeadPlacementRuleName); + op.obj.head_placement_rule.storage_class = (const char*)sqlite3_column_text(stmt, HeadPlacementRuleStorageClass); + op.obj.tail_placement.placement_rule.name = (const char*)sqlite3_column_text(stmt, TailPlacementRuleName); + op.obj.tail_placement.placement_rule.storage_class = (const char*)sqlite3_column_text(stmt, TailPlacementStorageClass); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ManifestPartObjs, op.obj.objs, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ManifestPartRules, op.obj.rules, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, Omap, op.obj.omap, sdb); + op.obj.is_multipart = sqlite3_column_int(stmt, IsMultipart); + SQL_DECODE_BLOB_PARAM(dpp, stmt, MPPartsList, op.obj.mp_parts, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, HeadData, op.obj.head_data, sdb); + op.obj.state.data = op.obj.head_data; + + rgw_bucket_dir_entry dent; + dent.key.name = op.obj.state.obj.key.name; + dent.key.instance = op.obj.state.obj.key.instance; + dent.tag = op.obj.tag; + dent.flags = op.obj.flags; + dent.versioned_epoch = op.obj.versioned_epoch; + dent.index_ver = op.obj.index_ver; + dent.exists = true; + dent.meta.category = op.obj.category; + dent.meta.size = op.obj.state.size; + dent.meta.accounted_size = op.obj.state.accounted_size; + dent.meta.mtime = op.obj.state.mtime; + dent.meta.etag = op.obj.etag; + dent.meta.owner = op.obj.owner; + dent.meta.owner_display_name = op.obj.owner_display_name; + dent.meta.content_type = op.obj.content_type; + dent.meta.storage_class = op.obj.storage_class; + dent.meta.appendable = op.obj.appendable; + + op.obj.list_entries.push_back(dent); + return 0; +} + +static int get_objectdata(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) { + if (!stmt) + return -1; + + op.obj.state.obj.key.name = (const char*)sqlite3_column_text(stmt, ObjName); + op.bucket.info.bucket.name = (const char*)sqlite3_column_text(stmt, ObjBucketName); + op.obj.state.obj.key.instance = (const char*)sqlite3_column_text(stmt, ObjInstance); + op.obj.state.obj.key.ns = (const char*)sqlite3_column_text(stmt, ObjNS); + op.obj.obj_id = (const char*)sqlite3_column_text(stmt, ObjDataID); + op.obj_data.part_num = sqlite3_column_int(stmt, PartNum); + op.obj_data.offset = sqlite3_column_int(stmt, Offset); + op.obj_data.size = sqlite3_column_int(stmt, ObjDataSize); + op.obj_data.multipart_part_str = (const char*)sqlite3_column_text(stmt, MultipartPartStr); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ObjDataMtime, op.obj.state.mtime, sdb); + SQL_DECODE_BLOB_PARAM(dpp, stmt, ObjData, op.obj_data.data, sdb); + + return 0; +} + +static int list_lc_entry(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) { + if (!stmt) + return -1; + + op.lc_entry.index = (const char*)sqlite3_column_text(stmt, LCEntryIndex); + op.lc_entry.entry.set_bucket((const char*)sqlite3_column_text(stmt, LCEntryBucketName)); + op.lc_entry.entry.set_start_time(sqlite3_column_int(stmt, LCEntryStartTime)); + op.lc_entry.entry.set_status(sqlite3_column_int(stmt, LCEntryStatus)); + + op.lc_entry.list_entries.push_back(op.lc_entry.entry); + + return 0; +} + +static int list_lc_head(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt) { + if (!stmt) + return -1; + + int64_t start_date; + + op.lc_head.index = (const char*)sqlite3_column_text(stmt, LCHeadIndex); + op.lc_head.head.set_marker((const char*)sqlite3_column_text(stmt, LCHeadMarker)); + + SQL_DECODE_BLOB_PARAM(dpp, stmt, LCHeadStartDate, start_date, sdb); + op.lc_head.head.get_start_date() = start_date; + + return 0; +} + +int SQLiteDB::InitializeDBOps(const DoutPrefixProvider *dpp) +{ + (void)createTables(dpp); + dbops.InsertUser = make_shared<SQLInsertUser>(&this->db, this->getDBname(), cct); + dbops.RemoveUser = make_shared<SQLRemoveUser>(&this->db, this->getDBname(), cct); + dbops.GetUser = make_shared<SQLGetUser>(&this->db, this->getDBname(), cct); + dbops.InsertBucket = make_shared<SQLInsertBucket>(&this->db, this->getDBname(), cct); + dbops.UpdateBucket = make_shared<SQLUpdateBucket>(&this->db, this->getDBname(), cct); + dbops.RemoveBucket = make_shared<SQLRemoveBucket>(&this->db, this->getDBname(), cct); + dbops.GetBucket = make_shared<SQLGetBucket>(&this->db, this->getDBname(), cct); + dbops.ListUserBuckets = make_shared<SQLListUserBuckets>(&this->db, this->getDBname(), cct); + dbops.InsertLCEntry = make_shared<SQLInsertLCEntry>(&this->db, this->getDBname(), cct); + dbops.RemoveLCEntry = make_shared<SQLRemoveLCEntry>(&this->db, this->getDBname(), cct); + dbops.GetLCEntry = make_shared<SQLGetLCEntry>(&this->db, this->getDBname(), cct); + dbops.ListLCEntries = make_shared<SQLListLCEntries>(&this->db, this->getDBname(), cct); + dbops.InsertLCHead = make_shared<SQLInsertLCHead>(&this->db, this->getDBname(), cct); + dbops.RemoveLCHead = make_shared<SQLRemoveLCHead>(&this->db, this->getDBname(), cct); + dbops.GetLCHead = make_shared<SQLGetLCHead>(&this->db, this->getDBname(), cct); + + return 0; +} + +void *SQLiteDB::openDB(const DoutPrefixProvider *dpp) +{ + string dbname; + int rc = 0; + + dbname = getDBfile(); + if (dbname.empty()) { + ldpp_dout(dpp, 0)<<"dbname is NULL" << dendl; + goto out; + } + + rc = sqlite3_open_v2(dbname.c_str(), (sqlite3**)&db, + SQLITE_OPEN_READWRITE | + SQLITE_OPEN_CREATE | + SQLITE_OPEN_FULLMUTEX, + NULL); + + if (rc) { + ldpp_dout(dpp, 0) <<"Cant open "<<dbname<<"; Errmsg - "\ + <<sqlite3_errmsg((sqlite3*)db) << dendl; + } else { + ldpp_dout(dpp, 0) <<"Opened database("<<dbname<<") successfully" << dendl; + } + + exec(dpp, "PRAGMA foreign_keys=ON", NULL); + +out: + return db; +} + +int SQLiteDB::closeDB(const DoutPrefixProvider *dpp) +{ + if (db) + sqlite3_close((sqlite3 *)db); + + db = NULL; + + return 0; +} + +int SQLiteDB::Reset(const DoutPrefixProvider *dpp, sqlite3_stmt *stmt) +{ + int ret = -1; + + if (!stmt) { + return -1; + } + sqlite3_clear_bindings(stmt); + ret = sqlite3_reset(stmt); + + return ret; +} + +int SQLiteDB::Step(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt, + int (*cbk)(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt)) +{ + int ret = -1; + + if (!stmt) { + return -1; + } + +again: + ret = sqlite3_step(stmt); + + if ((ret != SQLITE_DONE) && (ret != SQLITE_ROW)) { + ldpp_dout(dpp, 0)<<"sqlite step failed for stmt("<<stmt \ + <<"); Errmsg - "<<sqlite3_errmsg((sqlite3*)db) << dendl; + return -1; + } else if (ret == SQLITE_ROW) { + if (cbk) { + (*cbk)(dpp, op, stmt); + } else { + } + goto again; + } + + ldpp_dout(dpp, 20)<<"sqlite step successfully executed for stmt(" \ + <<stmt<<") ret = " << ret << dendl; + + return 0; +} + +int SQLiteDB::exec(const DoutPrefixProvider *dpp, const char *schema, + int (*callback)(void*,int,char**,char**)) +{ + int ret = -1; + char *errmsg = NULL; + + if (!db) + goto out; + + ret = sqlite3_exec((sqlite3*)db, schema, callback, 0, &errmsg); + if (ret != SQLITE_OK) { + ldpp_dout(dpp, 0) <<"sqlite exec failed for schema("<<schema \ + <<"); Errmsg - "<<errmsg << dendl; + sqlite3_free(errmsg); + goto out; + } + ret = 0; + ldpp_dout(dpp, 10) <<"sqlite exec successfully processed for schema(" \ + <<schema<<")" << dendl; +out: + return ret; +} + +int SQLiteDB::createTables(const DoutPrefixProvider *dpp) +{ + int ret = -1; + int cu = 0, cb = 0, cq = 0; + DBOpParams params = {}; + + params.user_table = getUserTable(); + params.bucket_table = getBucketTable(); + + if ((cu = createUserTable(dpp, ¶ms))) + goto out; + + if ((cb = createBucketTable(dpp, ¶ms))) + goto out; + + if ((cq = createQuotaTable(dpp, ¶ms))) + goto out; + + ret = 0; +out: + if (ret) { + if (cu) + DeleteUserTable(dpp, ¶ms); + if (cb) + DeleteBucketTable(dpp, ¶ms); + ldpp_dout(dpp, 0)<<"Creation of tables failed" << dendl; + } + + return ret; +} + +int SQLiteDB::createUserTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = CreateTableSchema("User", params); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"CreateUserTable failed" << dendl; + + ldpp_dout(dpp, 20)<<"CreateUserTable suceeded" << dendl; + + return ret; +} + +int SQLiteDB::createBucketTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = CreateTableSchema("Bucket", params); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"CreateBucketTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"CreateBucketTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::createObjectTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = CreateTableSchema("Object", params); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"CreateObjectTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"CreateObjectTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::createObjectTableTrigger(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = CreateTableSchema("ObjectTrigger", params); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"CreateObjectTableTrigger failed " << dendl; + + ldpp_dout(dpp, 20)<<"CreateObjectTableTrigger suceeded " << dendl; + + return ret; +} + +int SQLiteDB::createObjectView(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = CreateTableSchema("ObjectView", params); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"CreateObjectView failed " << dendl; + + ldpp_dout(dpp, 20)<<"CreateObjectView suceeded " << dendl; + + return ret; +} + +int SQLiteDB::createQuotaTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = CreateTableSchema("Quota", params); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"CreateQuotaTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"CreateQuotaTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::createObjectDataTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = CreateTableSchema("ObjectData", params); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"CreateObjectDataTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"CreateObjectDataTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::createLCTables(const DoutPrefixProvider *dpp) +{ + int ret = -1; + string schema; + DBOpParams params = {}; + + params.lc_entry_table = getLCEntryTable(); + params.lc_head_table = getLCHeadTable(); + params.bucket_table = getBucketTable(); + + schema = CreateTableSchema("LCEntry", ¶ms); + ret = exec(dpp, schema.c_str(), NULL); + if (ret) { + ldpp_dout(dpp, 0)<<"CreateLCEntryTable failed" << dendl; + return ret; + } + ldpp_dout(dpp, 20)<<"CreateLCEntryTable suceeded" << dendl; + + schema = CreateTableSchema("LCHead", ¶ms); + ret = exec(dpp, schema.c_str(), NULL); + if (ret) { + ldpp_dout(dpp, 0)<<"CreateLCHeadTable failed" << dendl; + (void)DeleteLCEntryTable(dpp, ¶ms); + } + ldpp_dout(dpp, 20)<<"CreateLCHeadTable suceeded" << dendl; + + return ret; +} + +int SQLiteDB::DeleteUserTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = DeleteTableSchema(params->user_table); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"DeleteUserTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"DeleteUserTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::DeleteBucketTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = DeleteTableSchema(params->bucket_table); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"DeletebucketTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"DeletebucketTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::DeleteObjectTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = DeleteTableSchema(params->object_table); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"DeleteObjectTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"DeleteObjectTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::DeleteObjectDataTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = DeleteTableSchema(params->objectdata_table); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"DeleteObjectDataTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"DeleteObjectDataTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::DeleteQuotaTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = DeleteTableSchema(params->quota_table); + + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"DeleteQuotaTable failed " << dendl; + + ldpp_dout(dpp, 20)<<"DeleteQuotaTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::DeleteLCEntryTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = DeleteTableSchema(params->lc_entry_table); + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"DeleteLCEntryTable failed " << dendl; + ldpp_dout(dpp, 20)<<"DeleteLCEntryTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::DeleteLCHeadTable(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = DeleteTableSchema(params->lc_head_table); + ret = exec(dpp, schema.c_str(), NULL); + if (ret) + ldpp_dout(dpp, 0)<<"DeleteLCHeadTable failed " << dendl; + ldpp_dout(dpp, 20)<<"DeleteLCHeadTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::ListAllUsers(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = ListTableSchema(params->user_table); + ret = exec(dpp, schema.c_str(), &list_callback); + if (ret) + ldpp_dout(dpp, 0)<<"GetUsertable failed " << dendl; + + ldpp_dout(dpp, 20)<<"GetUserTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::ListAllBuckets(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + + schema = ListTableSchema(params->bucket_table); + + ret = exec(dpp, schema.c_str(), &list_callback); + if (ret) + ldpp_dout(dpp, 0)<<"Listbuckettable failed " << dendl; + + ldpp_dout(dpp, 20)<<"ListbucketTable suceeded " << dendl; + + return ret; +} + +int SQLiteDB::ListAllObjects(const DoutPrefixProvider *dpp, DBOpParams *params) +{ + int ret = -1; + string schema; + map<string, class ObjectOp*>::iterator iter; + map<string, class ObjectOp*> objectmap; + string bucket; + + objectmap = getObjectMap(); + + if (objectmap.empty()) + ldpp_dout(dpp, 20)<<"objectmap empty " << dendl; + + for (iter = objectmap.begin(); iter != objectmap.end(); ++iter) { + bucket = iter->first; + params->object_table = getObjectTable(bucket); + schema = ListTableSchema(params->object_table); + + ret = exec(dpp, schema.c_str(), &list_callback); + if (ret) + ldpp_dout(dpp, 0)<<"ListObjecttable failed " << dendl; + + ldpp_dout(dpp, 20)<<"ListObjectTable suceeded " << dendl; + } + + return ret; +} + +int SQLObjectOp::InitializeObjectOps(string db_name, const DoutPrefixProvider *dpp) +{ + PutObject = make_shared<SQLPutObject>(sdb, db_name, cct); + DeleteObject = make_shared<SQLDeleteObject>(sdb, db_name, cct); + GetObject = make_shared<SQLGetObject>(sdb, db_name, cct); + UpdateObject = make_shared<SQLUpdateObject>(sdb, db_name, cct); + ListBucketObjects = make_shared<SQLListBucketObjects>(sdb, db_name, cct); + ListVersionedObjects = make_shared<SQLListVersionedObjects>(sdb, db_name, cct); + PutObjectData = make_shared<SQLPutObjectData>(sdb, db_name, cct); + UpdateObjectData = make_shared<SQLUpdateObjectData>(sdb, db_name, cct); + GetObjectData = make_shared<SQLGetObjectData>(sdb, db_name, cct); + DeleteObjectData = make_shared<SQLDeleteObjectData>(sdb, db_name, cct); + DeleteStaleObjectData = make_shared<SQLDeleteStaleObjectData>(sdb, db_name, cct); + + return 0; +} + +int SQLInsertUser::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLInsertUser - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareInsertUser"); +out: + return ret; +} + +int SQLInsertUser::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.tenant, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_id.tenant.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.ns, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_id.ns.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.display_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.display_name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_email, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_email.c_str(), sdb); + + if (!params->op.user.uinfo.access_keys.empty()) { + string access_key; + string key; + map<string, RGWAccessKey>::const_iterator it = + params->op.user.uinfo.access_keys.begin(); + const RGWAccessKey& k = it->second; + access_key = k.id; + key = k.key; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.access_keys_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, access_key.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.access_keys_secret, sdb); + SQL_BIND_TEXT(dpp, stmt, index, key.c_str(), sdb); + + } + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.access_keys, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.access_keys, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.swift_keys, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.swift_keys, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.subusers, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.subusers, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.suspended, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.user.uinfo.suspended, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.max_buckets, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.user.uinfo.max_buckets, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.op_mask, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.user.uinfo.op_mask, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_caps, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.caps, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.admin, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.user.uinfo.admin, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.system, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.user.uinfo.system, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.placement_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.default_placement.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.placement_storage_class, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.default_placement.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.placement_tags, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.placement_tags, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.bucket_quota, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.quota.bucket_quota, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.temp_url_keys, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.temp_url_keys, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_quota, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.quota.user_quota, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.type, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.user.uinfo.type, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.mfa_ids, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.uinfo.mfa_ids, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_attrs, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.user.user_attrs, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_ver, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.user.user_version.ver, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_ver_tag, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.user_version.tag.c_str(), sdb); + +out: + return rc; +} + +int SQLInsertUser::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLRemoveUser::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLRemoveUser - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareRemoveUser"); +out: + return ret; +} + +int SQLRemoveUser::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + +out: + return rc; +} + +int SQLRemoveUser::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLGetUser::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLGetUser - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + if (params->op.query_str == "email") { + SQL_PREPARE(dpp, p_params, sdb, email_stmt, ret, "PrepareGetUser"); + } else if (params->op.query_str == "access_key") { + SQL_PREPARE(dpp, p_params, sdb, ak_stmt, ret, "PrepareGetUser"); + } else if (params->op.query_str == "user_id") { + SQL_PREPARE(dpp, p_params, sdb, userid_stmt, ret, "PrepareGetUser"); + } else { // by default by userid + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareGetUser"); + } +out: + return ret; +} + +int SQLGetUser::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.query_str == "email") { + SQL_BIND_INDEX(dpp, email_stmt, index, p_params.op.user.user_email, sdb); + SQL_BIND_TEXT(dpp, email_stmt, index, params->op.user.uinfo.user_email.c_str(), sdb); + } else if (params->op.query_str == "access_key") { + if (!params->op.user.uinfo.access_keys.empty()) { + string access_key; + map<string, RGWAccessKey>::const_iterator it = + params->op.user.uinfo.access_keys.begin(); + const RGWAccessKey& k = it->second; + access_key = k.id; + + SQL_BIND_INDEX(dpp, ak_stmt, index, p_params.op.user.access_keys_id, sdb); + SQL_BIND_TEXT(dpp, ak_stmt, index, access_key.c_str(), sdb); + } + } else if (params->op.query_str == "user_id") { + SQL_BIND_INDEX(dpp, userid_stmt, index, p_params.op.user.user_id, sdb); + SQL_BIND_TEXT(dpp, userid_stmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + } else { // by default by userid + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + } + +out: + return rc; +} + +int SQLGetUser::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + if (params->op.query_str == "email") { + SQL_EXECUTE(dpp, params, email_stmt, list_user); + } else if (params->op.query_str == "access_key") { + SQL_EXECUTE(dpp, params, ak_stmt, list_user); + } else if (params->op.query_str == "user_id") { + SQL_EXECUTE(dpp, params, userid_stmt, list_user); + } else { // by default by userid + SQL_EXECUTE(dpp, params, stmt, list_user); + } + +out: + return ret; +} + +int SQLInsertBucket::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLInsertBucket - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareInsertBucket"); + +out: + return ret; +} + +int SQLInsertBucket::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + // user_id here is copied as OwnerID in the bucket table. + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.user.user_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.tenant, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.tenant.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.marker, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.marker.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.bucket_id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.size, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.ent.size, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.size_rounded, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.ent.size_rounded, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.creation_time, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.bucket.info.creation_time, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.count, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.ent.count, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.placement_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.placement_rule.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.placement_storage_class, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.placement_rule.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.flags, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.info.flags, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.zonegroup, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.zonegroup.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.has_instance_obj, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.info.has_instance_obj, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.quota, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.bucket.info.quota, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.requester_pays, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.info.requester_pays, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.has_website, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.info.has_website, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.website_conf, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.bucket.info.website_conf, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.swift_versioning, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.info.swift_versioning, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.swift_ver_location, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.swift_ver_location.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.mdsearch_config, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.bucket.info.mdsearch_config, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.new_bucket_instance_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.new_bucket_instance_id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.obj_lock, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.bucket.info.obj_lock, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.sync_policy_info_groups, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.bucket.info.sync_policy, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_attrs, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.bucket.bucket_attrs, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_ver, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.bucket.bucket_version.ver, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_ver_tag, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.bucket_version.tag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.mtime, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.bucket.mtime, sdb); + +out: + return rc; +} + +int SQLInsertBucket::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + class SQLObjectOp *ObPtr = NULL; + string bucket_name = params->op.bucket.info.bucket.name; + struct DBOpPrepareParams p_params = PrepareParams; + + ObPtr = new SQLObjectOp(sdb, ctx()); + + objectmapInsert(dpp, bucket_name, ObPtr); + + SQL_EXECUTE(dpp, params, stmt, NULL); + + /* Once Bucket is inserted created corresponding object(&data) tables + */ + InitPrepareParams(dpp, p_params, params); + + (void)createObjectTable(dpp, params); + (void)createObjectDataTable(dpp, params); + (void)createObjectTableTrigger(dpp, params); +out: + return ret; +} + +int SQLUpdateBucket::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLUpdateBucket - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + if (params->op.query_str == "attrs") { + SQL_PREPARE(dpp, p_params, sdb, attrs_stmt, ret, "PrepareUpdateBucket"); + } else if (params->op.query_str == "owner") { + SQL_PREPARE(dpp, p_params, sdb, owner_stmt, ret, "PrepareUpdateBucket"); + } else if (params->op.query_str == "info") { + SQL_PREPARE(dpp, p_params, sdb, info_stmt, ret, "PrepareUpdateBucket"); + } else { + ldpp_dout(dpp, 0)<<"In SQLUpdateBucket invalid query_str:" << + params->op.query_str << "" << dendl; + goto out; + } + +out: + return ret; +} + +int SQLUpdateBucket::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + sqlite3_stmt** stmt = NULL; // Prepared statement + + /* All below fields for attrs */ + if (params->op.query_str == "attrs") { + stmt = &attrs_stmt; + } else if (params->op.query_str == "owner") { + stmt = &owner_stmt; + } else if (params->op.query_str == "info") { + stmt = &info_stmt; + } else { + ldpp_dout(dpp, 0)<<"In SQLUpdateBucket invalid query_str:" << + params->op.query_str << "" << dendl; + goto out; + } + + if (params->op.query_str == "attrs") { + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.bucket_attrs, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.bucket_attrs, sdb); + } else if (params->op.query_str == "owner") { + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.creation_time, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.info.creation_time, sdb); + } else if (params->op.query_str == "info") { + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.tenant, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.bucket.tenant.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.marker, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.bucket.marker.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.bucket_id, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.bucket.bucket_id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.creation_time, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.info.creation_time, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.count, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.bucket.ent.count, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.placement_name, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.placement_rule.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.placement_storage_class, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.placement_rule.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.flags, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.bucket.info.flags, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.zonegroup, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.zonegroup.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.has_instance_obj, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.bucket.info.has_instance_obj, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.quota, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.info.quota, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.requester_pays, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.bucket.info.requester_pays, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.has_website, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.bucket.info.has_website, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.website_conf, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.info.website_conf, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.swift_versioning, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.bucket.info.swift_versioning, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.swift_ver_location, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.swift_ver_location.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.mdsearch_config, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.info.mdsearch_config, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.new_bucket_instance_id, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.new_bucket_instance_id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.obj_lock, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.info.obj_lock, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.sync_policy_info_groups, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.info.sync_policy, sdb); + } + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.user.user_id, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.bucket_ver, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.bucket.bucket_version.ver, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.mtime, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.bucket.mtime, sdb); + +out: + return rc; +} + +int SQLUpdateBucket::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + sqlite3_stmt** stmt = NULL; // Prepared statement + + if (params->op.query_str == "attrs") { + stmt = &attrs_stmt; + } else if (params->op.query_str == "owner") { + stmt = &owner_stmt; + } else if (params->op.query_str == "info") { + stmt = &info_stmt; + } else { + ldpp_dout(dpp, 0)<<"In SQLUpdateBucket invalid query_str:" << + params->op.query_str << "" << dendl; + goto out; + } + + SQL_EXECUTE(dpp, params, *stmt, NULL); +out: + return ret; +} + +int SQLRemoveBucket::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLRemoveBucket - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareRemoveBucket"); + +out: + return ret; +} + +int SQLRemoveBucket::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + +out: + return rc; +} + +int SQLRemoveBucket::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + objectmapDelete(dpp, params->op.bucket.info.bucket.name); + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLGetBucket::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLGetBucket - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareGetBucket"); + +out: + return ret; +} + +int SQLGetBucket::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + +out: + return rc; +} + +int SQLGetBucket::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + class SQLObjectOp *ObPtr = NULL; + + params->op.name = "GetBucket"; + + ObPtr = new SQLObjectOp(sdb, ctx()); + + /* For the case when the server restarts, need to reinsert objectmap*/ + objectmapInsert(dpp, params->op.bucket.info.bucket.name, ObPtr); + SQL_EXECUTE(dpp, params, stmt, list_bucket); +out: + return ret; +} + +int SQLListUserBuckets::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLListUserBuckets - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + if (params->op.query_str == "all") { + SQL_PREPARE(dpp, p_params, sdb, all_stmt, ret, "PrepareListUserBuckets"); + }else { + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareListUserBuckets"); + } + +out: + return ret; +} + +int SQLListUserBuckets::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + sqlite3_stmt** pstmt = NULL; // Prepared statement + + if (params->op.query_str == "all") { + pstmt = &all_stmt; + } else { + pstmt = &stmt; + } + + if (params->op.query_str != "all") { + SQL_BIND_INDEX(dpp, *pstmt, index, p_params.op.user.user_id, sdb); + SQL_BIND_TEXT(dpp, *pstmt, index, params->op.user.uinfo.user_id.id.c_str(), sdb); + } + + SQL_BIND_INDEX(dpp, *pstmt, index, p_params.op.bucket.min_marker, sdb); + SQL_BIND_TEXT(dpp, *pstmt, index, params->op.bucket.min_marker.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *pstmt, index, p_params.op.list_max_count, sdb); + SQL_BIND_INT(dpp, *pstmt, index, params->op.list_max_count, sdb); + +out: + return rc; +} + +int SQLListUserBuckets::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + if (params->op.query_str == "all") { + SQL_EXECUTE(dpp, params, all_stmt, list_bucket); + } else { + SQL_EXECUTE(dpp, params, stmt, list_bucket); + } +out: + return ret; +} + +int SQLPutObject::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLPutObject - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PreparePutObject"); + +out: + return ret; +} + +int SQLPutObject::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + int VersionNum = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_instance, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.instance.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_ns, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.ns.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.acls, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.acls, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.index_ver, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.index_ver, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.tag, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.tag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.flags, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.flags, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.versioned_epoch, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.versioned_epoch, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_category, sdb); + SQL_BIND_INT(dpp, stmt, index, (uint8_t)(params->op.obj.category), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.etag, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.etag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.owner, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.owner.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.owner_display_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.owner_display_name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.storage_class, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.appendable, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.appendable, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.content_type, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.content_type.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.index_hash_source, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.index_hash_source.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_size, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.state.size, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.accounted_size, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.state.accounted_size, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.mtime, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.mtime, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.epoch, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.state.epoch, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_tag, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.obj_tag, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.tail_tag, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.tail_tag, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.write_tag, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.write_tag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.fake_tag, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.state.fake_tag, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.shadow_obj, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.shadow_obj.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.has_data, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.state.has_data, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.is_versioned, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.is_versioned, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.version_num, sdb); + SQL_BIND_INT(dpp, stmt, index, VersionNum, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.pg_ver, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.state.pg_ver, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.zone_short_id, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.state.zone_short_id, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_version, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.state.objv_tracker.read_version.ver, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_version_tag, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.objv_tracker.read_version.tag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_attrs, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.attrset, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.head_size, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.head_size, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.max_head_size, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.max_head_size, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.obj_id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.tail_instance, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.tail_instance.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.head_placement_rule_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.head_placement_rule.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.head_placement_storage_class, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.head_placement_rule.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.tail_placement_rule_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.tail_placement.placement_rule.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.tail_placement_storage_class, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.tail_placement.placement_rule.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.manifest_part_objs, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.objs, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.manifest_part_rules, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.rules, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.omap, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.omap, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.is_multipart, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.obj.is_multipart, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.mp_parts, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.mp_parts, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.head_data, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.head_data, sdb); + +out: + return rc; +} + +int SQLPutObject::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLDeleteObject::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLDeleteObject - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareDeleteObject"); + +out: + return ret; +} + +int SQLDeleteObject::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_instance, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.instance.c_str(), sdb); +out: + return rc; +} + +int SQLDeleteObject::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLGetObject::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLGetObject - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareGetObject"); + +out: + return ret; +} + +int SQLGetObject::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_instance, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.instance.c_str(), sdb); + +out: + return rc; +} + +int SQLGetObject::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, list_object); +out: + return ret; +} + +int SQLUpdateObject::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + struct DBOpParams copy = *params; + string bucket_name; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLUpdateObject - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + if (params->op.query_str == "omap") { + SQL_PREPARE(dpp, p_params, sdb, omap_stmt, ret, "PrepareUpdateObject"); + } else if (params->op.query_str == "attrs") { + SQL_PREPARE(dpp, p_params, sdb, attrs_stmt, ret, "PrepareUpdateObject"); + } else if (params->op.query_str == "meta") { + SQL_PREPARE(dpp, p_params, sdb, meta_stmt, ret, "PrepareUpdateObject"); + } else if (params->op.query_str == "mp") { + SQL_PREPARE(dpp, p_params, sdb, mp_stmt, ret, "PrepareUpdateObject"); + } else { + ldpp_dout(dpp, 0)<<"In SQLUpdateObject invalid query_str:" << + params->op.query_str << dendl; + goto out; + } + +out: + return ret; +} + +int SQLUpdateObject::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + sqlite3_stmt** stmt = NULL; // Prepared statement + + /* All below fields for attrs */ + if (params->op.query_str == "omap") { + stmt = &omap_stmt; + } else if (params->op.query_str == "attrs") { + stmt = &attrs_stmt; + } else if (params->op.query_str == "meta") { + stmt = &meta_stmt; + } else if (params->op.query_str == "mp") { + stmt = &mp_stmt; + } else { + ldpp_dout(dpp, 0)<<"In SQLUpdateObject invalid query_str:" << + params->op.query_str << dendl; + goto out; + } + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_name, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_instance, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.state.obj.key.instance.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.mtime, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.state.mtime, sdb); + + if (params->op.query_str == "omap") { + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.omap, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.omap, sdb); + } + if (params->op.query_str == "attrs") { + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_attrs, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.state.attrset, sdb); + } + if (params->op.query_str == "mp") { + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.mp_parts, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.mp_parts, sdb); + } + if (params->op.query_str == "meta") { + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_ns, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.state.obj.key.ns.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.acls, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.acls, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.index_ver, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.index_ver, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.tag, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.tag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.flags, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.flags, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.versioned_epoch, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.versioned_epoch, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_category, sdb); + SQL_BIND_INT(dpp, *stmt, index, (uint8_t)(params->op.obj.category), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.etag, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.etag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.owner, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.owner.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.owner_display_name, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.owner_display_name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.storage_class, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.appendable, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.appendable, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.content_type, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.content_type.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.index_hash_source, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.state.obj.index_hash_source.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_size, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.state.size, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.accounted_size, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.state.accounted_size, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.epoch, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.state.epoch, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_tag, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.state.obj_tag, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.tail_tag, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.state.tail_tag, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.write_tag, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.state.write_tag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.fake_tag, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.state.fake_tag, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.shadow_obj, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.state.shadow_obj.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.has_data, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.state.has_data, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.is_versioned, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.is_versioned, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.version_num, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.version_num, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.pg_ver, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.state.pg_ver, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.zone_short_id, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.state.zone_short_id, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_version, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.state.objv_tracker.read_version.ver, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_version_tag, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.state.objv_tracker.read_version.tag.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_attrs, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.state.attrset, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.head_size, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.head_size, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.max_head_size, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.max_head_size, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.obj_id, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.obj_id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.tail_instance, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.tail_instance.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.head_placement_rule_name, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.head_placement_rule.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.head_placement_storage_class, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.head_placement_rule.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.tail_placement_rule_name, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.tail_placement.placement_rule.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.tail_placement_storage_class, sdb); + SQL_BIND_TEXT(dpp, *stmt, index, params->op.obj.tail_placement.placement_rule.storage_class.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.manifest_part_objs, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.objs, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.manifest_part_rules, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.rules, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.omap, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.omap, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.is_multipart, sdb); + SQL_BIND_INT(dpp, *stmt, index, params->op.obj.is_multipart, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.mp_parts, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.mp_parts, sdb); + + SQL_BIND_INDEX(dpp, *stmt, index, p_params.op.obj.head_data, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, *stmt, index, params->op.obj.head_data, sdb); + } + +out: + return rc; +} + +int SQLUpdateObject::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + sqlite3_stmt** stmt = NULL; // Prepared statement + + if (params->op.query_str == "omap") { + stmt = &omap_stmt; + } else if (params->op.query_str == "attrs") { + stmt = &attrs_stmt; + } else if (params->op.query_str == "meta") { + stmt = &meta_stmt; + } else if (params->op.query_str == "mp") { + stmt = &mp_stmt; + } else { + ldpp_dout(dpp, 0)<<"In SQLUpdateObject invalid query_str:" << + params->op.query_str << dendl; + goto out; + } + + SQL_EXECUTE(dpp, params, *stmt, NULL); +out: + return ret; +} + +int SQLListBucketObjects::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLListBucketObjects - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareListBucketObjects"); + +out: + return ret; +} + +int SQLListBucketObjects::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.min_marker, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.min_marker.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.prefix, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.prefix.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.list_max_count, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.list_max_count, sdb); + +out: + return rc; +} + +int SQLListBucketObjects::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, list_object); +out: + return ret; +} + +int SQLListVersionedObjects::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLListVersionedObjects - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareListVersionedObjects"); + +out: + return ret; +} + +int SQLListVersionedObjects::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.list_max_count, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.list_max_count, sdb); + +out: + return rc; +} + +int SQLListVersionedObjects::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, list_object); +out: + return ret; +} + +int SQLPutObjectData::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLPutObjectData - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PreparePutObjectData"); + +out: + return ret; +} + +int SQLPutObjectData::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_name, sdb); + + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_instance, sdb); + + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.instance.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_ns, sdb); + + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.ns.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.obj_id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj_data.part_num, sdb); + + SQL_BIND_INT(dpp, stmt, index, params->op.obj_data.part_num, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj_data.offset, sdb); + + SQL_BIND_INT(dpp, stmt, index, params->op.obj_data.offset, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj_data.data, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj_data.data, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj_data.size, sdb); + + SQL_BIND_INT(dpp, stmt, index, params->op.obj_data.size, sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj_data.multipart_part_str, sdb); + + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj_data.multipart_part_str.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.mtime, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.mtime, sdb); + +out: + return rc; +} + +int SQLPutObjectData::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLUpdateObjectData::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLUpdateObjectData - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareUpdateObjectData"); + +out: + return ret; +} + +int SQLUpdateObjectData::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_instance, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.instance.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.obj_id.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.mtime, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.mtime, sdb); + +out: + return rc; +} + +int SQLUpdateObjectData::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLGetObjectData::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLGetObjectData - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareGetObjectData"); + +out: + return ret; +} + +int SQLGetObjectData::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_instance, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.instance.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.obj_id.c_str(), sdb); + +out: + return rc; +} + +int SQLGetObjectData::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, get_objectdata); +out: + return ret; +} + +int SQLDeleteObjectData::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLDeleteObjectData - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareDeleteObjectData"); + +out: + return ret; +} + +int SQLDeleteObjectData::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + if (params->op.obj.state.obj.key.instance.empty()) { + params->op.obj.state.obj.key.instance = "null"; + } + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.bucket.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.bucket.info.bucket.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.name.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_instance, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.state.obj.key.instance.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.obj_id, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.obj.obj_id.c_str(), sdb); + +out: + return rc; +} + +int SQLDeleteObjectData::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLDeleteStaleObjectData::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLDeleteStaleObjectData - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareDeleteStaleObjectData"); + +out: + return ret; +} + +int SQLDeleteStaleObjectData::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.obj.mtime, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, params->op.obj.state.mtime, sdb); + +out: + return rc; +} + +int SQLDeleteStaleObjectData::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLInsertLCEntry::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLInsertLCEntry - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareInsertLCEntry"); + +out: + return ret; +} + +int SQLInsertLCEntry::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_entry.index, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_entry.index.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_entry.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_entry.entry.get_bucket().c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_entry.status, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.lc_entry.entry.get_status(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_entry.start_time, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.lc_entry.entry.get_start_time(), sdb); + +out: + return rc; +} + +int SQLInsertLCEntry::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLRemoveLCEntry::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLRemoveLCEntry - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareRemoveLCEntry"); + +out: + return ret; +} + +int SQLRemoveLCEntry::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_entry.index, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_entry.index.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_entry.bucket_name, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_entry.entry.get_bucket().c_str(), sdb); + +out: + return rc; +} + +int SQLRemoveLCEntry::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLGetLCEntry::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + sqlite3_stmt** pstmt = NULL; // Prepared statement + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLGetLCEntry - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + if (params->op.query_str == "get_next_entry") { + pstmt = &next_stmt; + } else { + pstmt = &stmt; + } + SQL_PREPARE(dpp, p_params, sdb, *pstmt, ret, "PrepareGetLCEntry"); + +out: + return ret; +} + +int SQLGetLCEntry::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + sqlite3_stmt** pstmt = NULL; // Prepared statement + + if (params->op.query_str == "get_next_entry") { + pstmt = &next_stmt; + } else { + pstmt = &stmt; + } + SQL_BIND_INDEX(dpp, *pstmt, index, p_params.op.lc_entry.index, sdb); + SQL_BIND_TEXT(dpp, *pstmt, index, params->op.lc_entry.index.c_str(), sdb); + + SQL_BIND_INDEX(dpp, *pstmt, index, p_params.op.lc_entry.bucket_name, sdb); + SQL_BIND_TEXT(dpp, *pstmt, index, params->op.lc_entry.entry.get_bucket().c_str(), sdb); + +out: + return rc; +} + +int SQLGetLCEntry::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + sqlite3_stmt** pstmt = NULL; // Prepared statement + + if (params->op.query_str == "get_next_entry") { + pstmt = &next_stmt; + } else { + pstmt = &stmt; + } + + SQL_EXECUTE(dpp, params, *pstmt, list_lc_entry); +out: + return ret; +} + +int SQLListLCEntries::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLListLCEntries - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareListLCEntries"); + +out: + return ret; +} + +int SQLListLCEntries::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_entry.index, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_entry.index.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_entry.min_marker, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_entry.min_marker.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.list_max_count, sdb); + SQL_BIND_INT(dpp, stmt, index, params->op.list_max_count, sdb); + +out: + return rc; +} + +int SQLListLCEntries::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, list_lc_entry); +out: + return ret; +} + +int SQLInsertLCHead::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLInsertLCHead - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareInsertLCHead"); + +out: + return ret; +} + +int SQLInsertLCHead::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_head.index, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_head.index.c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_head.marker, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_head.head.get_marker().c_str(), sdb); + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_head.start_date, sdb); + SQL_ENCODE_BLOB_PARAM(dpp, stmt, index, static_cast<int64_t>(params->op.lc_head.head.start_date), sdb); + +out: + return rc; +} + +int SQLInsertLCHead::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLRemoveLCHead::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLRemoveLCHead - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareRemoveLCHead"); + +out: + return ret; +} + +int SQLRemoveLCHead::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_head.index, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_head.index.c_str(), sdb); + +out: + return rc; +} + +int SQLRemoveLCHead::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + SQL_EXECUTE(dpp, params, stmt, NULL); +out: + return ret; +} + +int SQLGetLCHead::Prepare(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + struct DBOpPrepareParams p_params = PrepareParams; + + if (!*sdb) { + ldpp_dout(dpp, 0)<<"In SQLGetLCHead - no db" << dendl; + goto out; + } + + InitPrepareParams(dpp, p_params, params); + + SQL_PREPARE(dpp, p_params, sdb, stmt, ret, "PrepareGetLCHead"); + +out: + return ret; +} + +int SQLGetLCHead::Bind(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int index = -1; + int rc = 0; + struct DBOpPrepareParams p_params = PrepareParams; + + SQL_BIND_INDEX(dpp, stmt, index, p_params.op.lc_head.index, sdb); + SQL_BIND_TEXT(dpp, stmt, index, params->op.lc_head.index.c_str(), sdb); + +out: + return rc; +} + +int SQLGetLCHead::Execute(const DoutPrefixProvider *dpp, struct DBOpParams *params) +{ + int ret = -1; + + // clear the params before fetching the entry + params->op.lc_head.head = {}; + SQL_EXECUTE(dpp, params, stmt, list_lc_head); +out: + return ret; +} diff --git a/src/rgw/driver/dbstore/sqlite/sqliteDB.h b/src/rgw/driver/dbstore/sqlite/sqliteDB.h new file mode 100644 index 000000000..ec0ef2bb2 --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/sqliteDB.h @@ -0,0 +1,551 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab + +#pragma once + +#include <errno.h> +#include <stdlib.h> +#include <string> +#include <sqlite3.h> +#include "rgw/driver/dbstore/common/dbstore.h" + +using namespace rgw::store; + +class SQLiteDB : public DB, virtual public DBOp { + private: + sqlite3_mutex *mutex = NULL; + + protected: + CephContext *cct; + + public: + sqlite3_stmt *stmt = NULL; + DBOpPrepareParams PrepareParams; + + SQLiteDB(sqlite3 *dbi, std::string db_name, CephContext *_cct) : DB(db_name, _cct), cct(_cct) { + db = (void*)dbi; + } + SQLiteDB(std::string db_name, CephContext *_cct) : DB(db_name, _cct), cct(_cct) { + } + ~SQLiteDB() {} + + uint64_t get_blob_limit() override { return SQLITE_LIMIT_LENGTH; } + void *openDB(const DoutPrefixProvider *dpp) override; + int closeDB(const DoutPrefixProvider *dpp) override; + int InitializeDBOps(const DoutPrefixProvider *dpp) override; + + int InitPrepareParams(const DoutPrefixProvider *dpp, DBOpPrepareParams &p_params, + DBOpParams* params) override; + + int exec(const DoutPrefixProvider *dpp, const char *schema, + int (*callback)(void*,int,char**,char**)); + int Step(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt, + int (*cbk)(const DoutPrefixProvider *dpp, DBOpInfo &op, sqlite3_stmt *stmt)); + int Reset(const DoutPrefixProvider *dpp, sqlite3_stmt *stmt); + /* default value matches with sqliteDB style */ + + int createTables(const DoutPrefixProvider *dpp) override; + int createBucketTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int createUserTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int createObjectTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int createObjectDataTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int createObjectView(const DoutPrefixProvider *dpp, DBOpParams *params); + int createObjectTableTrigger(const DoutPrefixProvider *dpp, DBOpParams *params); + int createQuotaTable(const DoutPrefixProvider *dpp, DBOpParams *params); + void populate_object_params(const DoutPrefixProvider *dpp, + struct DBOpPrepareParams& p_params, + struct DBOpParams* params, bool data); + + int createLCTables(const DoutPrefixProvider *dpp) override; + + int DeleteBucketTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int DeleteUserTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int DeleteObjectTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int DeleteObjectDataTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int DeleteQuotaTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int DeleteLCEntryTable(const DoutPrefixProvider *dpp, DBOpParams *params); + int DeleteLCHeadTable(const DoutPrefixProvider *dpp, DBOpParams *params); + + int ListAllBuckets(const DoutPrefixProvider *dpp, DBOpParams *params) override; + int ListAllUsers(const DoutPrefixProvider *dpp, DBOpParams *params) override; + int ListAllObjects(const DoutPrefixProvider *dpp, DBOpParams *params) override; +}; + +class SQLObjectOp : public ObjectOp { + private: + sqlite3 **sdb = NULL; + CephContext *cct; + + public: + SQLObjectOp(sqlite3 **sdbi, CephContext *_cct) : sdb(sdbi), cct(_cct) {}; + ~SQLObjectOp() {} + + int InitializeObjectOps(std::string db_name, const DoutPrefixProvider *dpp); +}; + +class SQLInsertUser : public SQLiteDB, public InsertUserOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLInsertUser(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLInsertUser() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLRemoveUser : public SQLiteDB, public RemoveUserOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLRemoveUser(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLRemoveUser() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLGetUser : public SQLiteDB, public GetUserOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + sqlite3_stmt *email_stmt = NULL; // Prepared statement to query by useremail + sqlite3_stmt *ak_stmt = NULL; // Prepared statement to query by access_key_id + sqlite3_stmt *userid_stmt = NULL; // Prepared statement to query by user_id + + public: + SQLGetUser(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLGetUser() { + if (stmt) + sqlite3_finalize(stmt); + if (email_stmt) + sqlite3_finalize(email_stmt); + if (ak_stmt) + sqlite3_finalize(ak_stmt); + if (userid_stmt) + sqlite3_finalize(userid_stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLInsertBucket : public SQLiteDB, public InsertBucketOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLInsertBucket(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLInsertBucket() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLUpdateBucket : public SQLiteDB, public UpdateBucketOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *info_stmt = NULL; // Prepared statement + sqlite3_stmt *attrs_stmt = NULL; // Prepared statement + sqlite3_stmt *owner_stmt = NULL; // Prepared statement + + public: + SQLUpdateBucket(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLUpdateBucket() { + if (info_stmt) + sqlite3_finalize(info_stmt); + if (attrs_stmt) + sqlite3_finalize(attrs_stmt); + if (owner_stmt) + sqlite3_finalize(owner_stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLRemoveBucket : public SQLiteDB, public RemoveBucketOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLRemoveBucket(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLRemoveBucket() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLGetBucket : public SQLiteDB, public GetBucketOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLGetBucket(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLGetBucket() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLListUserBuckets : public SQLiteDB, public ListUserBucketsOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + sqlite3_stmt *all_stmt = NULL; // Prepared statement + + public: + SQLListUserBuckets(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLListUserBuckets() { + if (stmt) + sqlite3_finalize(stmt); + if (all_stmt) + sqlite3_finalize(all_stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLPutObject : public SQLiteDB, public PutObjectOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLPutObject(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLPutObject(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLPutObject() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLDeleteObject : public SQLiteDB, public DeleteObjectOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLDeleteObject(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLDeleteObject(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLDeleteObject() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLGetObject : public SQLiteDB, public GetObjectOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLGetObject(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLGetObject(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLGetObject() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLUpdateObject : public SQLiteDB, public UpdateObjectOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *omap_stmt = NULL; // Prepared statement + sqlite3_stmt *attrs_stmt = NULL; // Prepared statement + sqlite3_stmt *meta_stmt = NULL; // Prepared statement + sqlite3_stmt *mp_stmt = NULL; // Prepared statement + + public: + SQLUpdateObject(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLUpdateObject(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLUpdateObject() { + if (omap_stmt) + sqlite3_finalize(omap_stmt); + if (attrs_stmt) + sqlite3_finalize(attrs_stmt); + if (meta_stmt) + sqlite3_finalize(meta_stmt); + } + + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLListBucketObjects : public SQLiteDB, public ListBucketObjectsOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLListBucketObjects(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLListBucketObjects(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLListBucketObjects() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLListVersionedObjects : public SQLiteDB, public ListVersionedObjectsOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLListVersionedObjects(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLListVersionedObjects(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLListVersionedObjects() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLPutObjectData : public SQLiteDB, public PutObjectDataOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLPutObjectData(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLPutObjectData(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLPutObjectData() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLUpdateObjectData : public SQLiteDB, public UpdateObjectDataOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLUpdateObjectData(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLUpdateObjectData(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLUpdateObjectData() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLGetObjectData : public SQLiteDB, public GetObjectDataOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLGetObjectData(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLGetObjectData(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLGetObjectData() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLDeleteObjectData : public SQLiteDB, public DeleteObjectDataOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLDeleteObjectData(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLDeleteObjectData(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLDeleteObjectData() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLDeleteStaleObjectData : public SQLiteDB, public DeleteStaleObjectDataOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLDeleteStaleObjectData(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + SQLDeleteStaleObjectData(sqlite3 **sdbi, std::string db_name, CephContext *cct) : SQLiteDB(*sdbi, db_name, cct), sdb(sdbi) {} + + ~SQLDeleteStaleObjectData() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLInsertLCEntry : public SQLiteDB, public InsertLCEntryOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLInsertLCEntry(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLInsertLCEntry() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLRemoveLCEntry : public SQLiteDB, public RemoveLCEntryOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLRemoveLCEntry(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLRemoveLCEntry() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLGetLCEntry : public SQLiteDB, public GetLCEntryOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + sqlite3_stmt *next_stmt = NULL; // Prepared statement + + public: + SQLGetLCEntry(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLGetLCEntry() { + if (stmt) + sqlite3_finalize(stmt); + if (next_stmt) + sqlite3_finalize(next_stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLListLCEntries : public SQLiteDB, public ListLCEntriesOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLListLCEntries(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLListLCEntries() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLInsertLCHead : public SQLiteDB, public InsertLCHeadOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLInsertLCHead(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLInsertLCHead() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLRemoveLCHead : public SQLiteDB, public RemoveLCHeadOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLRemoveLCHead(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLRemoveLCHead() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; + +class SQLGetLCHead : public SQLiteDB, public GetLCHeadOp { + private: + sqlite3 **sdb = NULL; + sqlite3_stmt *stmt = NULL; // Prepared statement + + public: + SQLGetLCHead(void **db, std::string db_name, CephContext *cct) : SQLiteDB((sqlite3 *)(*db), db_name, cct), sdb((sqlite3 **)db) {} + ~SQLGetLCHead() { + if (stmt) + sqlite3_finalize(stmt); + } + int Prepare(const DoutPrefixProvider *dpp, DBOpParams *params); + int Execute(const DoutPrefixProvider *dpp, DBOpParams *params); + int Bind(const DoutPrefixProvider *dpp, DBOpParams *params); +}; diff --git a/src/rgw/driver/dbstore/sqlite/statement.cc b/src/rgw/driver/dbstore/sqlite/statement.cc new file mode 100644 index 000000000..dcf7dba9c --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/statement.cc @@ -0,0 +1,196 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include "common/dout.h" +#include "error.h" +#include "statement.h" + +#define dout_subsys ceph_subsys_rgw_dbstore + +namespace rgw::dbstore::sqlite { + +// owning pointer to arbitrary memory allocated and returned by sqlite3 +struct sqlite_deleter { + template <typename T> + void operator()(T* p) { ::sqlite3_free(p); } +}; +template <typename T> +using sqlite_ptr = std::unique_ptr<T, sqlite_deleter>; + + +stmt_ptr prepare_statement(const DoutPrefixProvider* dpp, + sqlite3* db, std::string_view sql) +{ + sqlite3_stmt* stmt = nullptr; + int result = ::sqlite3_prepare_v2(db, sql.data(), sql.size(), &stmt, nullptr); + auto ec = std::error_code{result, sqlite::error_category()}; + if (ec != sqlite::errc::ok) { + const char* errmsg = ::sqlite3_errmsg(db); + ldpp_dout(dpp, 1) << "preparation failed: " << errmsg + << " (" << ec << ")\nstatement: " << sql << dendl; + throw sqlite::error(errmsg, ec); + } + return stmt_ptr{stmt}; +} + +static int bind_index(const DoutPrefixProvider* dpp, + const stmt_binding& stmt, const char* name) +{ + const int index = ::sqlite3_bind_parameter_index(stmt.get(), name); + if (index <= 0) { + ldpp_dout(dpp, 1) << "binding failed on parameter name=" + << name << dendl; + sqlite3* db = ::sqlite3_db_handle(stmt.get()); + throw sqlite::error(db); + } + return index; +} + +void bind_text(const DoutPrefixProvider* dpp, const stmt_binding& stmt, + const char* name, std::string_view value) +{ + const int index = bind_index(dpp, stmt, name); + + int result = ::sqlite3_bind_text(stmt.get(), index, value.data(), + value.size(), SQLITE_STATIC); + auto ec = std::error_code{result, sqlite::error_category()}; + if (ec != sqlite::errc::ok) { + ldpp_dout(dpp, 1) << "binding failed on parameter name=" + << name << " value=" << value << dendl; + sqlite3* db = ::sqlite3_db_handle(stmt.get()); + throw sqlite::error(db, ec); + } +} + +void bind_int(const DoutPrefixProvider* dpp, const stmt_binding& stmt, + const char* name, int value) +{ + const int index = bind_index(dpp, stmt, name); + + int result = ::sqlite3_bind_int(stmt.get(), index, value); + auto ec = std::error_code{result, sqlite::error_category()}; + if (ec != sqlite::errc::ok) { + ldpp_dout(dpp, 1) << "binding failed on parameter name=" + << name << " value=" << value << dendl; + sqlite3* db = ::sqlite3_db_handle(stmt.get()); + throw sqlite::error(db, ec); + } +} + +void eval0(const DoutPrefixProvider* dpp, const stmt_execution& stmt) +{ + sqlite_ptr<char> sql; + if (dpp->get_cct()->_conf->subsys.should_gather<dout_subsys, 20>()) { + sql.reset(::sqlite3_expanded_sql(stmt.get())); + } + + const int result = ::sqlite3_step(stmt.get()); + auto ec = std::error_code{result, sqlite::error_category()}; + sqlite3* db = ::sqlite3_db_handle(stmt.get()); + + if (ec != sqlite::errc::done) { + const char* errmsg = ::sqlite3_errmsg(db); + ldpp_dout(dpp, 20) << "evaluation failed: " << errmsg + << " (" << ec << ")\nstatement: " << sql.get() << dendl; + throw sqlite::error(errmsg, ec); + } + ldpp_dout(dpp, 20) << "evaluation succeeded: " << sql.get() << dendl; +} + +void eval1(const DoutPrefixProvider* dpp, const stmt_execution& stmt) +{ + sqlite_ptr<char> sql; + if (dpp->get_cct()->_conf->subsys.should_gather<dout_subsys, 20>()) { + sql.reset(::sqlite3_expanded_sql(stmt.get())); + } + + const int result = ::sqlite3_step(stmt.get()); + auto ec = std::error_code{result, sqlite::error_category()}; + if (ec != sqlite::errc::row) { + sqlite3* db = ::sqlite3_db_handle(stmt.get()); + const char* errmsg = ::sqlite3_errmsg(db); + ldpp_dout(dpp, 1) << "evaluation failed: " << errmsg << " (" << ec + << ")\nstatement: " << sql.get() << dendl; + throw sqlite::error(errmsg, ec); + } + ldpp_dout(dpp, 20) << "evaluation succeeded: " << sql.get() << dendl; +} + +int column_int(const stmt_execution& stmt, int column) +{ + return ::sqlite3_column_int(stmt.get(), column); +} + +std::string column_text(const stmt_execution& stmt, int column) +{ + const unsigned char* text = ::sqlite3_column_text(stmt.get(), column); + // may be NULL + if (text) { + const std::size_t size = ::sqlite3_column_bytes(stmt.get(), column); + return {reinterpret_cast<const char*>(text), size}; + } else { + return {}; + } +} + +auto read_text_rows(const DoutPrefixProvider* dpp, + const stmt_execution& stmt, + std::span<std::string> entries) + -> std::span<std::string> +{ + sqlite_ptr<char> sql; + if (dpp->get_cct()->_conf->subsys.should_gather<dout_subsys, 20>()) { + sql.reset(::sqlite3_expanded_sql(stmt.get())); + } + + std::size_t count = 0; + while (count < entries.size()) { + const int result = ::sqlite3_step(stmt.get()); + auto ec = std::error_code{result, sqlite::error_category()}; + if (ec == sqlite::errc::done) { + break; + } + if (ec != sqlite::errc::row) { + sqlite3* db = ::sqlite3_db_handle(stmt.get()); + const char* errmsg = ::sqlite3_errmsg(db); + ldpp_dout(dpp, 1) << "evaluation failed: " << errmsg << " (" << ec + << ")\nstatement: " << sql.get() << dendl; + throw sqlite::error(errmsg, ec); + } + entries[count] = column_text(stmt, 0); + ++count; + } + ldpp_dout(dpp, 20) << "statement evaluation produced " << count + << " results: " << sql.get() << dendl; + + return entries.first(count); +} + +void execute(const DoutPrefixProvider* dpp, sqlite3* db, const char* query, + sqlite3_callback callback, void* arg) +{ + char* errmsg = nullptr; + const int result = ::sqlite3_exec(db, query, callback, arg, &errmsg); + auto ec = std::error_code{result, sqlite::error_category()}; + auto ptr = sqlite_ptr<char>{errmsg}; // free on destruction + if (ec != sqlite::errc::ok) { + ldpp_dout(dpp, 1) << "query execution failed: " << errmsg << " (" << ec + << ")\nquery: " << query << dendl; + throw sqlite::error(errmsg, ec); + } + ldpp_dout(dpp, 20) << "query execution succeeded: " << query << dendl; +} + +} // namespace rgw::dbstore::sqlite diff --git a/src/rgw/driver/dbstore/sqlite/statement.h b/src/rgw/driver/dbstore/sqlite/statement.h new file mode 100644 index 000000000..98b4acfea --- /dev/null +++ b/src/rgw/driver/dbstore/sqlite/statement.h @@ -0,0 +1,83 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab ft=cpp + +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2022 Red Hat, Inc. + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#pragma once + +#include <memory> +#include <span> +#include <string> + +#include <sqlite3.h> + +class DoutPrefixProvider; + +namespace rgw::dbstore::sqlite { + +// owning sqlite3_stmt pointer +struct stmt_deleter { + void operator()(sqlite3_stmt* p) const { ::sqlite3_finalize(p); } +}; +using stmt_ptr = std::unique_ptr<sqlite3_stmt, stmt_deleter>; + +// non-owning sqlite3_stmt pointer that clears binding state on destruction +struct stmt_binding_deleter { + void operator()(sqlite3_stmt* p) const { ::sqlite3_clear_bindings(p); } +}; +using stmt_binding = std::unique_ptr<sqlite3_stmt, stmt_binding_deleter>; + +// non-owning sqlite3_stmt pointer that clears execution state on destruction +struct stmt_execution_deleter { + void operator()(sqlite3_stmt* p) const { ::sqlite3_reset(p); } +}; +using stmt_execution = std::unique_ptr<sqlite3_stmt, stmt_execution_deleter>; + + +// prepare the sql statement or throw on error +stmt_ptr prepare_statement(const DoutPrefixProvider* dpp, + sqlite3* db, std::string_view sql); + +// bind an input string for the given parameter name +void bind_text(const DoutPrefixProvider* dpp, const stmt_binding& stmt, + const char* name, std::string_view value); + +// bind an input integer for the given parameter name +void bind_int(const DoutPrefixProvider* dpp, const stmt_binding& stmt, + const char* name, int value); + +// evaluate a prepared statement, expecting no result rows +void eval0(const DoutPrefixProvider* dpp, const stmt_execution& stmt); + +// evaluate a prepared statement, expecting a single result row +void eval1(const DoutPrefixProvider* dpp, const stmt_execution& stmt); + +// return the given column as an integer +int column_int(const stmt_execution& stmt, int column); + +// return the given column as text, or an empty string on NULL +std::string column_text(const stmt_execution& stmt, int column); + +// read the text column from each result row into the given entries, and return +// the sub-span of entries that contain results +auto read_text_rows(const DoutPrefixProvider* dpp, + const stmt_execution& stmt, + std::span<std::string> entries) + -> std::span<std::string>; + +// execute a raw query without preparing a statement. the optional callback +// can be used to read results +void execute(const DoutPrefixProvider* dpp, sqlite3* db, const char* query, + sqlite3_callback callback, void* arg); + +} // namespace rgw::dbstore::sqlite |