#pragma once #include #include #include #include #include #include #ifndef _WIN32 #include #endif #include "base/define.h" #include "base/error.h" #include "base/buffer.h" #include "util/json.h" #include "util/pool.hpp" namespace ylib::mysql { class pool; class result; class conn; class prepare_statement; // 与 MySQL Connector/C++ sql::DataType 数值对齐 enum class field_type : int { UNKNOWN = 0, BIT, TINYINT, SMALLINT, MEDIUMINT, INTEGER, BIGINT, REAL, DOUBLE, DECIMAL, NUMERIC, CHAR, BINARY, VARCHAR, VARBINARY, LONGVARCHAR, LONGVARBINARY, TIMESTAMP, DATE, TIME, YEAR, GEOMETRY, ENUM, SET, SQLNULL, JSON }; struct field { uint32 index = 0; // 列下标,从 1 开始 std::string name; field_type type = field_type::UNKNOWN; bool is_unsigned = false; }; // 单列取值:从 ResultSet 读出后独立保存 class data { public: data() = default; bool is_null() const { return m_hold == hold::null; } field_type type() const { return m_type; } int32 to_int32() const; uint32 to_uint32() const; int64 to_int64() const; uint64 to_uint64() const; bool to_boolean() const; double to_double() const; std::string to_string() const; ylib::buffer to_blob() const; friend class result; friend class row; private: enum class hold { null, i64, u64, f64, boolean, str, blob }; hold m_hold = hold::null; field_type m_type = field_type::UNKNOWN; int64 m_i64 = 0; uint64 m_u64 = 0; double m_f64 = 0; bool m_bool = false; std::string m_str; ylib::buffer m_blob; }; // 整行数据:支持按索引 / 字段名取值,并可转为 json 对象 class row { public: row() = default; size_t size() const { return m_values.size(); } bool empty() const { return m_values.empty(); } bool has(const std::string& name) const; // 列下标从 1 开始 const data& get(uint32 index) const; const data& get(const std::string& name) const; const data& operator[](uint32 index) const { return get(index); } const data& operator[](const std::string& name) const { return get(name); } const field& field_info(uint32 index) const; const std::vector& fields() const { return m_fields; } ylib::json to_json() const; friend class result; private: std::vector m_fields; std::vector m_values; std::unordered_map m_name_index; // value: 0-based }; struct mysql_conn_info { mysql_conn_info() { port = 0; } std::string ipaddress; std::string username; std::string password; std::string database; std::string charset; uint32 port; }; class result :public ylib::error_base { public: result(void* handle); ~result(); // 列名 std::string field_name(uint32 index); // 列数量 uint32 field_count(); // 行数量 size_t row_count(); // 下一行 bool next(); // 按列下标(从1开始) / 列名取值 ylib::mysql::data get(uint32 index); ylib::mysql::data get(const std::string& name); // 获取当前整行 ylib::mysql::row get_row(); // 当前行转 json 对象 ylib::json row_to_json(); ylib::json table(); private: uint32 field_index(const std::string& name) const; ylib::mysql::data read_data(uint32 index) const; void* m_handle = nullptr; std::vector m_fields; std::unordered_map m_field_index; }; class prepare_statement :public ylib::error_base { public: prepare_statement(); ~prepare_statement(); void set_bigint(uint32 index, const std::string& value); void set_boolean(uint32 index, bool value); void set_datetime(uint32 index, const std::string& value); void set_double(uint32 index, double value); void set_int32(uint32 index, int32 value); void set_uint32(uint32 index, uint32 value); void set_int64(uint32 index, int64 value); void set_uint64(uint32 index, uint64 value); void set_null(uint32 index); void set_string(uint32 index, const std::string& value); void set_string(uint32 index,const char* data,int size); void set_blob(uint32 index, const char* data, int size); void clear(); uint64 update(); ylib::mysql::result* query(); friend class ylib::mysql::conn; private: ylib::mysql::result* m_result = nullptr; void* m_handle = nullptr; // 持有 blob 流,保证 execute 前有效(仅一次拷贝进 stringstream) std::queue> m_blobs; }; class conn :public ylib::example, public ylib::error_base { public: conn(); ~conn(); virtual EXAMPLE_START_RESULT start(const ylib::mysql::mysql_conn_info& info) override; virtual void close() override; virtual void recover() override; virtual void task_out() override; void clear(); ylib::mysql::prepare_statement* setsql(const std::string& sql); uint64 insert_id(); void begin(bool autocommit = false); void commit(); void rollback(); void setDatabase(const std::string& name); friend class ylib::mysql::pool; private: void* m_handle = nullptr; ylib::mysql::mysql_conn_info m_info; class prepare_statement* m_ppst = nullptr; // 事务状态 0=未开启 1=已开启 int m_sw = 0; }; // 连接池:增量配置,未填字段用默认值 // ylib::pool_options opt; // opt.max_size = 50; // 只改需要的项 // pool.start(info, opt); class pool : public ylib::pool { public: pool() = default; ~pool() = default; }; }