| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492 |
- //
- // Copyright (C) 2004-2016 Maciej Sobczak, Stephen Hutton
- // Distributed under the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- #ifndef SOCI_ORACLE_H_INCLUDED
- #define SOCI_ORACLE_H_INCLUDED
- #include <soci/soci-platform.h>
- #ifdef SOCI_ORACLE_SOURCE
- # define SOCI_ORACLE_DECL SOCI_DECL_EXPORT
- #else
- # define SOCI_ORACLE_DECL SOCI_DECL_IMPORT
- #endif
- #include <soci/soci-backend.h>
- #include <oci.h> // OCI
- #include <sstream>
- #include <vector>
- #ifdef _MSC_VER
- #pragma warning(disable:4512 4511)
- #endif
- namespace soci
- {
- class SOCI_ORACLE_DECL oracle_soci_error : public soci_error
- {
- public:
- oracle_soci_error(std::string const & msg, int errNum = 0);
- error_category get_error_category() const override { return cat_; }
- int err_num_;
- error_category cat_;
- };
- struct oracle_statement_backend;
- struct oracle_standard_into_type_backend : details::standard_into_type_backend
- {
- oracle_standard_into_type_backend(oracle_statement_backend &st)
- : statement_(st), defnp_(NULL), indOCIHolder_(0),
- data_(NULL), buf_(NULL) {}
- void define_by_pos(int &position,
- void *data, details::exchange_type type) override;
- void pre_exec(int num) override;
- void pre_fetch() override;
- void post_fetch(bool gotData, bool calledFromFetch,
- indicator *ind) override;
- void clean_up() override;
- oracle_statement_backend &statement_;
- OCIDefine *defnp_;
- sb2 indOCIHolder_;
- void *data_;
- void *ociData_;
- char *buf_; // generic buffer
- details::exchange_type type_;
- ub2 rCode_;
- };
- struct oracle_vector_into_type_backend : details::vector_into_type_backend
- {
- oracle_vector_into_type_backend(oracle_statement_backend &st)
- : statement_(st), defnp_(NULL),
- data_(NULL), buf_(NULL), user_ranges_(true) {}
- void define_by_pos(int &position,
- void *data, details::exchange_type type) override
- {
- user_ranges_ = false;
- define_by_pos_bulk(position, data, type, 0, &end_var_);
- }
- void define_by_pos_bulk(
- int & position, void * data, details::exchange_type type,
- std::size_t begin, std::size_t * end) override;
- void pre_exec(int num) override;
- void pre_fetch() override;
- void post_fetch(bool gotData, indicator *ind) override;
- void resize(std::size_t sz) override;
- std::size_t size() override;
- std::size_t full_size();
- void clean_up() override;
- // helper function for preparing indicators and sizes_ vectors
- // (as part of the define_by_pos)
- void prepare_indicators(std::size_t size);
- oracle_statement_backend &statement_;
- OCIDefine *defnp_;
- std::vector<sb2> indOCIHolderVec_;
- void *data_;
- char *buf_; // generic buffer
- details::exchange_type type_;
- std::size_t begin_;
- std::size_t * end_;
- std::size_t end_var_;
- bool user_ranges_;
- std::size_t colSize_; // size of the string column (used for strings)
- std::vector<ub2> sizes_; // sizes of data fetched (used for strings)
- std::vector<ub2> rCodes_;
- };
- struct oracle_standard_use_type_backend : details::standard_use_type_backend
- {
- oracle_standard_use_type_backend(oracle_statement_backend &st)
- : statement_(st), bindp_(NULL), indOCIHolder_(0),
- data_(NULL), buf_(NULL) {}
- void bind_by_pos(int &position,
- void *data, details::exchange_type type, bool readOnly) override;
- void bind_by_name(std::string const &name,
- void *data, details::exchange_type type, bool readOnly) override;
- // common part for bind_by_pos and bind_by_name
- void prepare_for_bind(void *&data, sb4 &size, ub2 &oracleType, bool readOnly);
- void pre_exec(int num) override;
- void pre_use(indicator const *ind) override;
- void post_use(bool gotData, indicator *ind) override;
- void clean_up() override;
- oracle_statement_backend &statement_;
- OCIBind *bindp_;
- sb2 indOCIHolder_;
- void *data_;
- void *ociData_;
- bool readOnly_;
- char *buf_; // generic buffer
- details::exchange_type type_;
- };
- struct oracle_vector_use_type_backend : details::vector_use_type_backend
- {
- oracle_vector_use_type_backend(oracle_statement_backend &st)
- : statement_(st), bindp_(NULL),
- data_(NULL), buf_(NULL), bind_position_(0) {}
- void bind_by_pos(int & position,
- void * data, details::exchange_type type) override
- {
- bind_by_pos_bulk(position, data, type, 0, &end_var_);
- }
- void bind_by_pos_bulk(int & position,
- void * data, details::exchange_type type,
- std::size_t begin, std::size_t * end) override;
- void bind_by_name(const std::string & name,
- void * data, details::exchange_type type) override
- {
- bind_by_name_bulk(name, data, type, 0, &end_var_);
- }
- void bind_by_name_bulk(std::string const &name,
- void *data, details::exchange_type type,
- std::size_t begin, std::size_t * end) override;
- // pre_use() helper
- void prepare_for_bind(void *&data, sb4 &size, ub2 &oracleType);
- // helper function for preparing indicators and sizes_ vectors
- // (as part of the bind_by_pos and bind_by_name)
- void prepare_indicators(std::size_t size);
- void pre_use(indicator const *ind) override;
- std::size_t size() override; // active size (might be lower than full vector size)
- std::size_t full_size(); // actual size of the user-provided vector
- void clean_up() override;
- oracle_statement_backend &statement_;
- OCIBind *bindp_;
- std::vector<sb2> indOCIHolderVec_;
- void *data_;
- char *buf_; // generic buffer
- details::exchange_type type_;
- std::size_t begin_;
- std::size_t * end_;
- std::size_t end_var_;
- // used for strings only
- std::vector<ub2> sizes_;
- std::size_t maxSize_;
- // name is used if non-empty, otherwise position
- std::string bind_name_;
- int bind_position_;
- };
- struct oracle_session_backend;
- struct oracle_statement_backend : details::statement_backend
- {
- oracle_statement_backend(oracle_session_backend &session);
- void alloc() override;
- void clean_up() override;
- void prepare(std::string const &query,
- details::statement_type eType) override;
- exec_fetch_result execute(int number) override;
- exec_fetch_result fetch(int number) override;
- long long get_affected_rows() override;
- int get_number_of_rows() override;
- std::string get_parameter_name(int index) const override;
- std::string rewrite_for_procedure_call(std::string const &query) override;
- int prepare_for_describe() override;
- void describe_column(int colNum,
- db_type &dbtype,
- std::string &columnName) override;
- // helper for defining into vector<string>
- std::size_t column_size(int position);
- oracle_standard_into_type_backend * make_into_type_backend() override;
- oracle_standard_use_type_backend * make_use_type_backend() override;
- oracle_vector_into_type_backend * make_vector_into_type_backend() override;
- oracle_vector_use_type_backend * make_vector_use_type_backend() override;
- oracle_session_backend &session_;
- OCIStmt *stmtp_;
- bool boundByName_;
- bool boundByPos_;
- bool noData_;
- };
- struct oracle_rowid_backend : details::rowid_backend
- {
- oracle_rowid_backend(oracle_session_backend &session);
- ~oracle_rowid_backend() override;
- OCIRowid *rowidp_;
- };
- struct oracle_blob_backend : details::blob_backend
- {
- typedef OCILobLocator * locator_t;
- oracle_blob_backend(oracle_session_backend &session);
- ~oracle_blob_backend() override;
- std::size_t get_len() override;
- std::size_t read_from_start(void * buf, std::size_t toRead, std::size_t offset = 0) override;
- std::size_t write_from_start(const void * buf, std::size_t toWrite, std::size_t offset = 0) override;
- std::size_t append(const void *buf, std::size_t toWrite) override;
- void trim(std::size_t newLen) override;
- locator_t get_lob_locator() const;
- void set_lob_locator(locator_t locator, bool initialized = true);
- void reset();
- void ensure_initialized();
- private:
- std::size_t do_deprecated_read(std::size_t offset, void *buf, std::size_t toRead) override
- {
- // Offsets are 1-based in Oracle
- return read_from_start(buf, toRead, offset - 1);
- }
- std::size_t do_deprecated_write(std::size_t offset, const void *buf, std::size_t toWrite) override
- {
- // Offsets are 1-based in Oracle
- return write_from_start(buf, toWrite, offset - 1);
- }
- oracle_session_backend &session_;
- locator_t lobp_;
- // If this is true, then the locator lobp_ points to something useful
- // (instead of being the equivalent to a pointer with random value)
- bool initialized_;
- };
- struct oracle_session_backend : details::session_backend
- {
- oracle_session_backend(std::string const & serviceName,
- std::string const & userName,
- std::string const & password,
- int mode,
- bool decimals_as_strings = false,
- int charset = 0,
- int ncharset = 0);
- ~oracle_session_backend() override;
- bool is_connected() override;
- void begin() override;
- void commit() override;
- void rollback() override;
- std::string get_table_names_query() const override
- {
- return "select table_name"
- " from user_tables";
- }
- std::string get_column_descriptions_query() const override
- {
- return "select column_name,"
- " data_type,"
- " char_length as character_maximum_length,"
- " data_precision as numeric_precision,"
- " data_scale as numeric_scale,"
- " decode(nullable, 'Y', 'YES', 'N', 'NO') as is_nullable"
- " from user_tab_columns"
- " where table_name = :t";
- }
- std::string create_column_type(db_type dt,
- int precision, int scale) override
- {
- // Oracle-specific SQL syntax:
- std::string res;
- switch (dt)
- {
- case db_string:
- {
- std::ostringstream oss;
- if (precision == 0)
- {
- oss << "clob";
- }
- else
- {
- oss << "varchar(" << precision << ")";
- }
- res += oss.str();
- }
- break;
- case db_date:
- res += "timestamp";
- break;
- case db_double:
- {
- std::ostringstream oss;
- if (precision == 0)
- {
- oss << "number";
- }
- else
- {
- oss << "number(" << precision << ", " << scale << ")";
- }
- res += oss.str();
- }
- break;
- case db_int16:
- res += "smallint";
- break;
- case db_int32:
- res += "integer";
- break;
- case db_int64:
- res += "number";
- break;
- case db_uint64:
- res += "number";
- break;
- case db_blob:
- res += "blob";
- break;
- case db_xml:
- res += "xmltype";
- break;
- default:
- throw soci_error("this db_type is not supported in create_column");
- }
- return res;
- }
- std::string add_column(const std::string & tableName,
- const std::string & columnName, db_type dt,
- int precision, int scale) override
- {
- return "alter table " + tableName + " add " +
- columnName + " " + create_column_type(dt, precision, scale);
- }
- std::string alter_column(const std::string & tableName,
- const std::string & columnName, db_type dt,
- int precision, int scale) override
- {
- return "alter table " + tableName + " modify " +
- columnName + " " + create_column_type(dt, precision, scale);
- }
- std::string empty_blob() override
- {
- return "empty_blob()";
- }
- std::string nvl() override
- {
- return "nvl";
- }
- bool get_next_sequence_value(session &s,
- std::string const &sequence, long long &value) override;
- std::string get_dummy_from_table() const override { return "dual"; }
- std::string get_backend_name() const override { return "oracle"; }
- void clean_up();
- oracle_statement_backend * make_statement_backend() override;
- oracle_rowid_backend * make_rowid_backend() override;
- oracle_blob_backend * make_blob_backend() override;
- bool get_option_decimals_as_strings() { return decimals_as_strings_; }
- // Return either SQLT_FLT or SQLT_BDOUBLE as the type to use when binding
- // values of C type "double" (the latter is preferable but might not be
- // always available).
- ub2 get_double_sql_type() const;
- OCIEnv *envhp_;
- OCIServer *srvhp_;
- OCIError *errhp_;
- OCISvcCtx *svchp_;
- OCISession *usrhp_;
- bool decimals_as_strings_;
- };
- struct oracle_backend_factory : backend_factory
- {
- oracle_backend_factory() {}
- oracle_session_backend * make_session(
- connection_parameters const & parameters) const override;
- };
- extern SOCI_ORACLE_DECL oracle_backend_factory const oracle;
- extern "C"
- {
- // for dynamic backend loading
- SOCI_ORACLE_DECL backend_factory const * factory_oracle();
- SOCI_ORACLE_DECL void register_factory_oracle();
- } // extern "C"
- } // namespace soci
- #endif
|