diff --git a/docs/api/backend.md b/docs/api/backend.md index bf99ad242..372ceca9b 100644 --- a/docs/api/backend.md +++ b/docs/api/backend.md @@ -24,6 +24,24 @@ enum data_type dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long }; +// data types, as seen by the user +enum db_type +{ + db_string, + db_int8, + db_uint8, + db_int16, + db_uint16, + db_int32, + db_uint32, + db_int64, + db_uint64, + db_double, + db_date, + db_blob, + db_xml +}; + // the enum type for indicator variables enum indicator { i_ok, i_null, i_truncated }; @@ -32,15 +50,26 @@ enum exchange_type { x_char, x_stdstring, - x_short, - x_integer, - x_long_long, - x_unsigned_long_long, + x_int8, + x_uint8, + x_int16, + x_short = x_int16, + x_uint16, + x_int32, + x_integer = x_int32, + x_uint32, + x_int64, + x_long_long = x_int64, + x_uint64, + x_unsigned_long_long = x_uint64, x_double, x_stdtm, x_statement, x_rowid, - x_blob + x_blob, + + x_xmltype, + x_longstring }; struct cstring_descriptor @@ -60,8 +89,9 @@ public: }; ``` -The `data_type` enumeration type defines all types that form the core type support for SOCI. +The `data_type` and `db_type` enumeration type defines all types that form the core type support for SOCI. The enum itself can be used by clients when dealing with dynamic rowset description. +`data_type` is deprecated in favor of `db_type`, so users are encouraged to use the latter. The `indicator` enumeration type defines all recognized *states* of data. The `i_truncated` state is provided for the case where the string is retrieved from the database @@ -191,6 +221,7 @@ public: virtual int prepare_for_describe() = 0; virtual void describe_column(int colNum, data_type& dtype, + db_type& dbtype, std::string& column_name) = 0; virtual standard_into_type_backend* make_into_type_backend() = 0; diff --git a/docs/api/client.md b/docs/api/client.md index b149c04bc..386497ec5 100644 --- a/docs/api/client.md +++ b/docs/api/client.md @@ -15,6 +15,9 @@ The following types are commonly used in the rest of the interface: // data types, as seen by the user enum data_type { dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long }; +// data types, as seen by the user +enum db_type { db_string, db_date, db_double, db_int8, db_uint8, db_int16, db_uint16, db_int32, db_uint32, db_int64, db_uint64 }; + // the enum type for indicator variables enum indicator { i_ok, i_null, i_truncated }; @@ -22,7 +25,8 @@ enum indicator { i_ok, i_null, i_truncated }; class soci_error : public std::runtime_error { /* ... */ }; ``` -The `data_type` type defines the basic SOCI data types. User provided data types need to be associated with one of these basic types. +The `data_type` and `db_type` types define the basic SOCI data types. User provided data types need to be associated with one of these basic types. +`data_type` is deprecated in favor of `db_type`, so users are encouraged to use the latter. The `indicator` type defines the possible states of data. @@ -443,14 +447,16 @@ class column_properties { public: std::string get_name() const; - data_type get_data_type() const; + data_type_type get_data_type() const; + db_type get_db_type() const; }; ``` This class contains the following members: * `get_name` function that returns the name of the column. -* `get_data_type` that returns the type of the column. +* `get_data_type` that returns the type of the column (deprecate in favor of `get_db_type`). +* `get_db_type` that returns the type of the column. See [Dynamic resultset binding](../types.md#dynamic-binding) for examples. @@ -642,6 +648,14 @@ The functions above create and destroy the statement object. If the statement ca int soci_into_string (statement_handle st); int soci_into_int (statement_handle st); int soci_into_long_long(statement_handle st); +int soci_into_int8 (statement_handle st); +int soci_into_uint8 (statement_handle st); +int soci_into_int16 (statement_handle st); +int soci_into_uint16 (statement_handle st); +int soci_into_int32 (statement_handle st); +int soci_into_uint32 (statement_handle st); +int soci_into_int64 (statement_handle st); +int soci_into_uint64 (statement_handle st); int soci_into_double (statement_handle st); int soci_into_date (statement_handle st); int soci_into_blob (statement_handle st); @@ -649,6 +663,14 @@ int soci_into_blob (statement_handle st); int soci_into_string_v (statement_handle st); int soci_into_int_v (statement_handle st); int soci_into_long_long_v(statement_handle st); +int soci_into_int8_v (statement_handle st); +int soci_into_uint8_v (statement_handle st); +int soci_into_int16_v (statement_handle st); +int soci_into_uint16_v (statement_handle st); +int soci_into_int32_v (statement_handle st); +int soci_into_uint32_v (statement_handle st); +int soci_into_int64_v (statement_handle st); +int soci_into_uint64_v (statement_handle st); int soci_into_double_v (statement_handle st); int soci_into_date_v (statement_handle st); ``` @@ -669,6 +691,14 @@ This function returns `1` if the into element at the given position has non-null char const * soci_get_into_string (statement_handle st, int position); int soci_get_into_int (statement_handle st, int position); long long soci_get_into_long_long(statement_handle st, int position); +int8_t soci_get_into_int8 (statement_handle st, int position); +uint8_t soci_get_into_uint8 (statement_handle st, int position); +int16_t soci_get_into_int16 (statement_handle st, int position); +uint16_t soci_get_into_uint16 (statement_handle st, int position); +int32_t soci_get_into_int32 (statement_handle st, int position); +uint32_t soci_get_into_uint32 (statement_handle st, int position); +int64_t soci_get_into_int64 (statement_handle st, int position); +uint64_t soci_get_into_uint64 (statement_handle st, int position); double soci_get_into_double (statement_handle st, int position); char const * soci_get_into_date (statement_handle st, int position); blob_handle soci_get_into_blob (statement_handle st, int position); @@ -676,6 +706,14 @@ blob_handle soci_get_into_blob (statement_handle st, int position); char const * soci_get_into_string_v (statement_handle st, int position, int index); int soci_get_into_int_v (statement_handle st, int position, int index); long long soci_get_into_long_long_v(statement_handle st, int position, int index); +int8_t soci_get_into_int8_v (statement_handle st, int position, int index); +uint8_t soci_get_into_uint8_v (statement_handle st, int position, int index); +int16_t soci_get_into_int16_v (statement_handle st, int position, int index); +uint16_t soci_get_into_uint16_v (statement_handle st, int position, int index); +int32_t soci_get_into_int32_v (statement_handle st, int position, int index); +uint32_t soci_get_into_uint32_v (statement_handle st, int position, int index); +int64_t soci_get_into_int64_v (statement_handle st, int position, int index); +uint64_t soci_get_into_uint64_v (statement_handle st, int position, int index); double soci_get_into_double_v (statement_handle st, int position, int index); char const * soci_get_into_date_v (statement_handle st, int position, int index); ``` @@ -688,6 +726,14 @@ The functions above allow to retrieve the current value of the given into elemen void soci_use_string (statement_handle st, char const * name); void soci_use_int (statement_handle st, char const * name); void soci_use_long_long(statement_handle st, char const * name); +void soci_use_int8 (statement_handle st, char const * name); +void soci_use_uint8 (statement_handle st, char const * name); +void soci_use_int16 (statement_handle st, char const * name); +void soci_use_uint16 (statement_handle st, char const * name); +void soci_use_int32 (statement_handle st, char const * name); +void soci_use_uint32 (statement_handle st, char const * name); +void soci_use_int64 (statement_handle st, char const * name); +void soci_use_uint64 (statement_handle st, char const * name); void soci_use_double (statement_handle st, char const * name); void soci_use_date (statement_handle st, char const * name); void soci_use_blob (statement_handle st, char const * name); @@ -695,6 +741,14 @@ void soci_use_blob (statement_handle st, char const * name); void soci_use_string_v (statement_handle st, char const * name); void soci_use_int_v (statement_handle st, char const * name); void soci_use_long_long_v(statement_handle st, char const * name); +void soci_use_int8_v (statement_handle st, char const * name); +void soci_use_uint8_v (statement_handle st, char const * name); +void soci_use_int16_v (statement_handle st, char const * name); +void soci_use_uint16_v (statement_handle st, char const * name); +void soci_use_int32_v (statement_handle st, char const * name); +void soci_use_uint32_v (statement_handle st, char const * name); +void soci_use_int64_v (statement_handle st, char const * name); +void soci_use_uint64_v (statement_handle st, char const * name); void soci_use_double_v (statement_handle st, char const * name); void soci_use_date_v (statement_handle st, char const * name); ``` @@ -718,6 +772,14 @@ These functions get and set the size of vector use elements (see comments for ve void soci_set_use_string (statement_handle st, char const * name, char const * val); void soci_set_use_int (statement_handle st, char const * name, int val); void soci_set_use_long_long(statement_handle st, char const * name, long long val); +void soci_set_use_int8 (statement_handle st, char const * name, int8_t val); +void soci_set_use_uint8 (statement_handle st, char const * name, uint8_t val); +void soci_set_use_int16 (statement_handle st, char const * name, int16_t val); +void soci_set_use_uint16 (statement_handle st, char const * name, uint16_t val); +void soci_set_use_int32 (statement_handle st, char const * name, int32_t val); +void soci_set_use_uint32 (statement_handle st, char const * name, uint32_t val); +void soci_set_use_int64 (statement_handle st, char const * name, int64_t val); +void soci_set_use_uint64 (statement_handle st, char const * name, uint64_t val); void soci_set_use_double (statement_handle st, char const * name, double val); void soci_set_use_date (statement_handle st, char const * name, char const * val); void soci_set_use_blob (statement_handle st, char const * name, blob_handle blob); @@ -726,6 +788,14 @@ void soci_set_use_state_v (statement_handle st, char const * name, int index, void soci_set_use_string_v (statement_handle st, char const * name, int index, char const * val); void soci_set_use_int_v (statement_handle st, char const * name, int index, int val); void soci_set_use_long_long_v(statement_handle st, char const * name, int index, long long val); +void soci_set_use_int8_v (statement_handle st, char const * name, int index, int8_t val); +void soci_set_use_uint8_v (statement_handle st, char const * name, int index, uint8_t val); +void soci_set_use_int16_v (statement_handle st, char const * name, int index, int16_t val); +void soci_set_use_uint16_v (statement_handle st, char const * name, int index, uint16_t val); +void soci_set_use_int32_v (statement_handle st, char const * name, int index, int32_t val); +void soci_set_use_uint32_v (statement_handle st, char const * name, int index, uint32_t val); +void soci_set_use_int64_v (statement_handle st, char const * name, int index, int64_t val); +void soci_set_use_uint64_v (statement_handle st, char const * name, int index, uint64_t val); void soci_set_use_double_v (statement_handle st, char const * name, int index, double val); void soci_set_use_date_v (statement_handle st, char const * name, int index, char const * val); ``` @@ -739,6 +809,14 @@ int soci_get_use_state (statement_handle st, char const * name); char const * soci_get_use_string (statement_handle st, char const * name); int soci_get_use_int (statement_handle st, char const * name); long long soci_get_use_long_long(statement_handle st, char const * name); +int8_t soci_get_use_int8 (statement_handle st, char const * name); +uint8_t soci_get_use_uint8 (statement_handle st, char const * name); +int16_t soci_get_use_int16 (statement_handle st, char const * name); +uint16_t soci_get_use_uint16 (statement_handle st, char const * name); +int32_t soci_get_use_int32 (statement_handle st, char const * name); +uint32_t soci_get_use_uint32 (statement_handle st, char const * name); +int64_t soci_get_use_int64 (statement_handle st, char const * name); +uint64_t soci_get_use_uint64 (statement_handle st, char const * name); double soci_get_use_double (statement_handle st, char const * name); char const * soci_get_use_date (statement_handle st, char const * name); blob_handle soci_get_use_blob (statement_handle st, char const * name); diff --git a/docs/backends/firebird.md b/docs/backends/firebird.md index 24e26111e..c4a61d79e 100644 --- a/docs/backends/firebird.md +++ b/docs/backends/firebird.md @@ -73,14 +73,25 @@ type is not known at compile time. When calling `row::get()`, the type you should pass as T depends upon the underlying database type. For the Firebird backend, this type mapping is: -|Firebird Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|numeric, decimal (where scale > 0)|dt_double|double| -|numeric, decimal [^1] (where scale = 0)|dt_integer, dt_double|int, double| -|double precision, float|dt_double|double| -|smallint, integer|dt_integer|int| -|char, varchar|dt_string|std::string| -|date, time, timestamp|dt_date|std::tm| +| Firebird Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| --------------------------------------- | --------------------------------------- | --------------------------------- | +| numeric, decimal (where scale > 0) | dt_double | double | +| numeric, decimal [^1] (where scale = 0) | dt_integer, dt_double | int, double | +| double precision, float | dt_double | double | +| smallint, integer | dt_integer | int | +| char, varchar | dt_string | std::string | +| date, time, timestamp | dt_date | std::tm | + +| Firebird Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| --------------------------------------- | --------------------------------------- | --------------------------------- | +| numeric, decimal (where scale > 0) | db_double | double | +| numeric, decimal [^1] (where scale = 0) | db_int16/db_int32/db_int64, db_double | int16_t/int32_t/int64_t, double | +| double precision, float | db_double | double | +| smallint | db_int16 | int16_t | +| integer | db_int32 | int32_t | +| bigint | db_int64 | int64_t | +| char, varchar | db_string | std::string | +| date, time, timestamp | db_date | std::tm | [^1] There is also 64bit integer type for larger values which is currently not supported. diff --git a/docs/backends/mysql.md b/docs/backends/mysql.md index 7589718dc..bbac99763 100644 --- a/docs/backends/mysql.md +++ b/docs/backends/mysql.md @@ -72,15 +72,31 @@ The MySQL backend supports the use of the SOCI `row` class, which facilitates re When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the MySQL backend, this type mapping is: -|MySQL Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|FLOAT, DOUBLE, DECIMAL and synonyms|dt_double|double| -|TINYINT, TINYINT UNSIGNED, SMALLINT, SMALLINT UNSIGNED, INT|dt_integer|int| -|INT UNSIGNED|dt_long_long|long long or unsigned| -|BIGINT|dt_long_long|long long| -|BIGINT UNSIGNED|dt_unsigned_long_long|unsigned long long| -|CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM|dt_string|std::string| -|TIMESTAMP (works only with MySQL >= 5.0), DATE, TIME, DATETIME|dt_date|std::tm| +| MySQL Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| ----------------------------------------------------------------------------------------------------------------- | ---------------------------- | ----------------------------- | +| FLOAT, DOUBLE, DECIMAL and synonyms | dt_double | double | +| TINYINT, TINYINT UNSIGNED, SMALLINT, SMALLINT UNSIGNED, INT | dt_integer | int | +| INT UNSIGNED | dt_long_long | long long or unsigned | +| BIGINT | dt_long_long | long long | +| BIGINT UNSIGNED | dt_unsigned_long_long | unsigned long long | +| CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM | dt_string | std::string | +| TIMESTAMP (works only with MySQL >= 5.0), DATE, TIME, DATETIME | dt_date | std::tm | + +| MySQL Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| ----------------------------------------------------------------------------------------------------------------- | ---------------------------- | ----------------------------- | +| FLOAT, DOUBLE, DECIMAL and synonyms | db_double | double | +| TINYINT | db_int8 | int8_t | +| TINYINT UNSIGNED | db_uint8 | uint8_t | +| SMALLINT | db_int16 | int16_t | +| SMALLINT UNSIGNED | db_uint16 | uint16_t | +| MEDIUMINT | db_int32 | int32_t | +| MEDIUMINT UNSIGNED | db_uint32 | uint32_t | +| INT | db_int32 | int32_t | +| INT UNSIGNED | db_uint32 | uint32_t | +| BIGINT | db_int64 | int64_t | +| BIGINT UNSIGNED | db_uint64 | uint64_t | +| CHAR, VARCHAR, BINARY, VARBINARY, TINYBLOB, MEDIUMBLOB, BLOB,LONGBLOB, TINYTEXT, MEDIUMTEXT, TEXT, LONGTEXT, ENUM | db_string | std::string | +| TIMESTAMP (works only with MySQL >= 5.0), DATE, TIME, DATETIME | db_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `Row` class.) diff --git a/docs/backends/odbc.md b/docs/backends/odbc.md index 84bcd38f6..9365c0281 100644 --- a/docs/backends/odbc.md +++ b/docs/backends/odbc.md @@ -60,14 +60,25 @@ The ODBC backend supports the use of the SOCI `row` class, which facilitates ret When calling `row::get()`, the type you should pass as T depends upon the underlying database type. For the ODBC backend, this type mapping is: -|ODBC Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|SQL_DOUBLE, SQL_DECIMAL, SQL_REAL, SQL_FLOAT, SQL_NUMERIC|dt_double|double| -|SQL_TINYINT, SQL_SMALLINT, SQL_INTEGER, SQL_BIGINT|dt_integer|int| -|SQL_CHAR, SQL_VARCHAR|dt_string|std::string| -|SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP|dt_date|std::tm| +| ODBC Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| --------------------------------------------------------- | ---------------------------- | ----------------------------- | +| SQL_DOUBLE, SQL_DECIMAL, SQL_REAL, SQL_FLOAT, SQL_NUMERIC | dt_double | double | +| SQL_TINYINT, SQL_SMALLINT, SQL_INTEGER, SQL_BIGINT | dt_integer | int | +| SQL_CHAR, SQL_VARCHAR | dt_string | std::string | +| SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP | dt_date | std::tm | + +| ODBC Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| --------------------------------------------------------- | -------------------------- | ----------------------------- | +| SQL_DOUBLE, SQL_DECIMAL, SQL_REAL, SQL_FLOAT, SQL_NUMERIC | db_double | double | +| SQL_TINYINT | db_int8 | int8_t | +| SQL_SMALLINT | db_int16 | int16_t | +| SQL_INTEGER | db_int32 | int32_t | +| SQL_BIGINT | db_int64 | int64_t | +| SQL_CHAR, SQL_VARCHAR | db_string | std::string | +| SQL_TYPE_DATE, SQL_TYPE_TIME, SQL_TYPE_TIMESTAMP | db_date | std::tm | Not all ODBC drivers support all datatypes. +Columns having the attribute `unsigned` get mapped to their corresponding `db_uint[n]` and `uint[n]_t` types. (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/oracle.md b/docs/backends/oracle.md index 4e5eae434..13317a6b9 100644 --- a/docs/backends/oracle.md +++ b/docs/backends/oracle.md @@ -71,13 +71,21 @@ The Oracle backend supports the use of the SOCI `row` class, which facilitates r When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the Oracle backend, this type mapping is: -|Oracle Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|number (where scale > 0)|dt_double|double| -|number(where scale = 0 and precision ≤ `std::numeric_limits::digits10`)|dt_integer|int| -|number|dt_long_long|long long| -|char, varchar, varchar2|dt_string|std::string| -|date|dt_date|std::tm| +| Oracle Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| --------------------------------------------------------------------------------- | ---------------------------- | ----------------------------- | +| number (where scale > 0) | dt_double | double | +| number (where scale = 0 and precision ≤ `std::numeric_limits::digits10`) | dt_integer | int | +| number (where scale = 0) | dt_long_long | long long | +| char, varchar, varchar2 | dt_string | std::string | +| date | dt_date | std::tm | + +| Oracle Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| --------------------------------------------------------------------------------- | ---------------------------- | ----------------------------- | +| number (where scale > 0) | db_double | double | +| number (where scale = 0 and precision ≤ `std::numeric_limits::digits10`) | db_int32 | int32_t | +| number (where scale = 0) | db_int64 | int64_t | +| char, varchar, varchar2 | db_string | std::string | +| date | db_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/postgresql.md b/docs/backends/postgresql.md index 5f97f7f92..f7268ac32 100644 --- a/docs/backends/postgresql.md +++ b/docs/backends/postgresql.md @@ -88,14 +88,25 @@ The PostgreSQL backend supports the use of the SOCI `row` class, which facilitat When calling `row::get()`, the type you should pass as `T` depends upon the underlying database type. For the PostgreSQL backend, this type mapping is: -|PostgreSQL Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|numeric, real, double|dt_double|double| -|boolean, smallint, integer|dt_integer|int| -|int8|dt_long_long|long long| -|oid|dt_integer|unsigned long| -|char, varchar, text, cstring, bpchar|dt_string|std::string| -|abstime, reltime, date, time, timestamp, timestamptz, timetz|dt_date|std::tm| +| PostgreSQL Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| ------------------------------------------------------------ | ---------------------------- | ----------------------------- | +| numeric, real, double | dt_double | double | +| boolean, smallint, integer | dt_integer | int | +| int8 | dt_long_long | long long | +| oid | dt_integer | unsigned long | +| char, varchar, text, cstring, bpchar | dt_string | std::string | +| abstime, reltime, date, time, timestamp, timestamptz, timetz | dt_date | std::tm | + +| PostgreSQL Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| ------------------------------------------------------------ | ---------------------------- | ----------------------------- | +| numeric, real, double | db_double | double | +| boolean | db_int8 | int8_t | +| smallint | db_int16 | int16_t | +| integer | db_int32 | int32_t | +| int8 | db_int64 | int64_t | +| oid | db_int32 | int32_t | +| char, varchar, text, cstring, bpchar | db_string | std::string | +| abstime, reltime, date, time, timestamp, timestamptz, timetz | db_date | std::tm | (See the [dynamic resultset binding](../types.md#dynamic-binding) documentation for general information on using the `row` class.) diff --git a/docs/backends/sqlite3.md b/docs/backends/sqlite3.md index 4d449d057..a77a7f2a5 100644 --- a/docs/backends/sqlite3.md +++ b/docs/backends/sqlite3.md @@ -75,14 +75,25 @@ When calling `row::get()`, the type you should pass as T depends upon the und For the SQLite3 backend, this type mapping is complicated by the fact the SQLite3 does not enforce [types][INTEGER_PRIMARY_KEY] and makes no attempt to validate the type names used in table creation or alteration statements. SQLite3 will return the type as a string, SOCI will recognize the following strings and match them the corresponding SOCI types: -|SQLite3 Data Type|SOCI Data Type|`row::get` specializations| -|--- |--- |--- | -|*float*, *double*|dt_double|double| -|*int8*, *bigint*|dt_long_long|long long| -|*unsigned big int*|dt_unsigned_long_long|unsigned long long| -|*int*, *boolean*|dt_integer|int| -|*text, *char*|dt_string|std::string| -|*date*, *time*|dt_date|std::tm| +| SQLite3 Data Type | SOCI Data Type (`data_type`) | `row::get` specializations | +| ------------------------------------------------------------------------------------------------------------ | ---------------------------- | ----------------------------- | +| *float*, *decimal*, *double*, *double precision*, *number*, *numeric*, *real* | dt_double | double | +| *int*, *integer*, *int2*, *mediumint*, *boolean* | dt_integer | int | +| *int8*, *bigint* | dt_long_long | long long | +| *unsigned big int* | dt_unsigned_long_long | unsigned long long | +| *text*, *char*, *character*, *clob*, *native character*, *nchar*, *nvarchar*, *varchar*, *varying character* | dt_string | std::string | +| *date*, *time*, *datetime* | dt_date | std::tm | + +| SQLite3 Data Type | SOCI Data Type (`db_type`) | `row::get` specializations | +| ------------------------------------------------------------------------------------------------------------ | ---------------------------- | ----------------------------- | +| *float*, *decimal*, *double*, *double precision*, *number*, *numeric*, *real* | db_double | double | +| *tinyint* | db_int8 | int8_t | +| *smallint* | db_int16 | int16_t | +| *int*, *integer*, *int2*, *mediumint*, *boolean* | db_int32 | int32_t | +| *int8*, *bigint* | db_int64 | int64_t | +| *unsigned big int* | db_uint64 | uint64_t | +| *text*, *char*, *character*, *clob*, *native character*, *nchar*, *nvarchar*, *varchar*, *varying character* | db_string | std::string | +| *date*, *time*, *datetime* | db_date | std::tm | [INTEGER_PRIMARY_KEY] : There is one case where SQLite3 enforces type. If a column is declared as "integer primary key", then SQLite3 uses that as an alias to the internal ROWID column that exists for every table. Only integers are allowed in this column. diff --git a/docs/interfaces.md b/docs/interfaces.md index 36480734d..d63206e81 100644 --- a/docs/interfaces.md +++ b/docs/interfaces.md @@ -56,8 +56,8 @@ session_handle sql = soci_create_session("postgresql://dbname=mydb"); statement_handle st = soci_create_statement(sql); -soci_use_int(st, "id"); -soci_set_use_int(st, "id", 123); +soci_use_int32(st, "id"); +soci_set_use_int32(st, "id", 123); int namePosition = soci_into_string(st); diff --git a/docs/types.md b/docs/types.md index 201fea440..e71962611 100644 --- a/docs/types.md +++ b/docs/types.md @@ -7,7 +7,7 @@ The static binding for types is most useful when the types used in the database The following types are currently supported for use with `into` and `use` expressions: * `char` (for character values) -* `short`, `int`, `unsigned long`, `long long`, `double` (for numeric values) +* `int8_t`, `uint8_t`, `int16_t`, `uint16_t`, `int32_t`, `uint32_t`, `int64_t`, `uint64_t`, `double` (for numeric values) * `std::string` (for string values) * `std::tm` (for datetime values) * `soci::statement` (for nested statements and PL/SQL cursors) @@ -16,15 +16,22 @@ The following types are currently supported for use with `into` and `use` expres See the test code that accompanies the library to see how each of these types is used. +Note that the fixed-size types `int32_t`, `int64_t` etc. are only typedefs for the fundamental types `int`, `long` etc. +This means that the two can be used interchangeably when interacting with SOCI and you can choose which one of them you want to use in your code. + ### Static binding for bulk operations Bulk inserts, updates, and selects are supported through the following `std::vector` based into and use types: * `std::vector` -* `std::vector` -* `std::vector` -* `std::vector` -* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` +* `std::vector` * `std::vector` * `std::vector` * `std::vector` @@ -57,24 +64,39 @@ for(std::size_t i = 0; i != r.size(); ++i) doc << '<' << props.get_name() << '>'; - switch(props.get_data_type()) + switch(props.get_db_type()) { - case dt_string: + case db_string: doc << r.get(i); break; - case dt_double: + case db_double: doc << r.get(i); break; - case dt_integer: - doc << r.get(i); + case db_int8: + doc << r.get(i); + break; + case db_uint8: + doc << r.get(i); + break; + case db_int16: + doc << r.get(i); + break; + case db_uint16: + doc << r.get(i); + break; + case db_int32: + doc << r.get(i); + break; + case db_uint32: + doc << r.get(i); break; - case dt_long_long: - doc << r.get(i); + case db_int64: + doc << r.get(i); break; - case dt_unsigned_long_long: - doc << r.get(i); + case db_uint64: + doc << r.get(i); break; - case dt_date: + case db_date: std::tm when = r.get(i); doc << asctime(&when); break; @@ -85,18 +107,33 @@ for(std::size_t i = 0; i != r.size(); ++i) doc << ""; ``` -The type `T` parameter that should be passed to `row::get()` depends on the SOCI data type that is returned from `column_properties::get_data_type()`. +The type `T` parameter that should be passed to `row::get()` depends on the SOCI data type that is returned from `data_type column_properties::get_data_type()` or `db_type column_properties::get_db_type()`. +Users are encouraged to use the latter as it supports a wider range of numerical C++ types. `row::get()` throws an exception of type `std::bad_cast` if an incorrect type `T` is requested. -| SOCI Data Type | `row::get` specialization | -|----------------|------------------------------| -| `dt_double` | `double` | -| `dt_integer` | `int` | -| `dt_long_long` | `long long` | -| `dt_unsigned_long_long` | `unsigned long long`| -| `dt_string` | `std::string` | -| `dt_date` | `std::tm` | +| SOCI Data Type (`data_type`) | `row::get` specialization | +|------------------------------|------------------------------| +| `dt_double` | `double` | +| `dt_integer` | `int` | +| `dt_long_long` | `long long` | +| `dt_unsigned_long_long` | `unsigned long long` | +| `dt_string` | `std::string` | +| `dt_date` | `std::tm` | + +| SOCI Data Type (`db_type`) | `row::get` specialization | +|------------------------------|------------------------------| +| `db_double` | `double` | +| `db_int8` | `int8_t` | +| `db_uint8` | `uint8_t` | +| `db_int16` | `int16_t` | +| `db_uint16` | `uint16_t` | +| `db_int32` | `int32_t` | +| `db_uint32` | `uint32_t` | +| `db_int64` | `int64_t` | +| `db_uint64` | `uint64_t` | +| `db_string` | `std::string` | +| `db_date` | `std::tm` | The mapping of underlying database column types to SOCI datatypes is database specific. See the [backend documentation](backends/index.md) for details. @@ -133,9 +170,14 @@ SOCI can be easily extended with support for user-defined datatypes. The extension mechanism relies on appropriate specialization of the `type_conversion` structure that converts to and from one of the following SOCI base types: * `double` -* `int` -* `long long` -* `unsigned long long` +* `int8_t` +* `uint8_t` +* `int16_t` +* `uint16_t` +* `int32_t` +* `uint32_t` +* `int64_t` +* `uint64_t` * `std::string` * `char` * `std::tm` diff --git a/docs/utilities.md b/docs/utilities.md index 110f0e19b..4a331dbc0 100644 --- a/docs/utilities.md +++ b/docs/utilities.md @@ -9,7 +9,7 @@ SOCI supports some basic methods to construct portable DDL queries. That is, ins It is possible to create a new table in a single statement: ```cpp -sql.create_table("t1").column("i", soci::dt_integer).column("j", soci::dt_integer); +sql.create_table("t1").column("i", soci::db_int32).column("j", soci::db_int32); ``` Above, table "t1" will be created with two columns ("i", "j") of type integer. @@ -19,9 +19,9 @@ It is also possible to build similar statements piece by piece, which is useful ```cpp { soci::ddl_type ddl = sql.create_table("t2"); - ddl.column("i", soci::dt_integer); - ddl.column("j", soci::dt_integer); - ddl.column("k", soci::dt_integer)("not null"); + ddl.column("i", soci::db_int32); + ddl.column("j", soci::db_int32); + ddl.column("k", soci::db_int32)("not null"); ddl.primary_key("t2_pk", "j"); } ``` @@ -31,9 +31,9 @@ The actual statement is executed at the end of above block, when the ddl object Columns can be added to and dropped from already existing tables as well: ```cpp -sql.add_column("t1", "k", soci::dt_integer); +sql.add_column("t1", "k", soci::db_int32); // or with constraint: -//sql.add_column("t1", "k", soci::dt_integer)("not null"); +//sql.add_column("t1", "k", soci::db_int32)("not null"); sql.drop_column("t1", "i"); ``` @@ -41,8 +41,8 @@ sql.drop_column("t1", "i"); If needed, precision and scale can be defined with additional integer arguments to functions that create columns: ```cpp -sql.add_column("t1", "s", soci::dt_string, precision); -sql.add_column("t1", "d", soci::dt_double, precision, scale); +sql.add_column("t1", "s", soci::db_string, precision); +sql.add_column("t1", "d", soci::db_double, precision, scale); ``` Tables with foreign keys to each other can be also created: @@ -50,8 +50,8 @@ Tables with foreign keys to each other can be also created: ```cpp { soci::ddl_type ddl = sql.create_table("t3"); - ddl.column("x", soci::dt_integer); - ddl.column("y", soci::dt_integer); + ddl.column("x", soci::db_int32); + ddl.column("y", soci::db_int32); ddl.foreign_key("t3_fk", "x", "t2", "j"); } ``` diff --git a/include/private/firebird/common.h b/include/private/firebird/common.h index 94468bfd1..0e6b89d4b 100644 --- a/include/private/firebird/common.h +++ b/include/private/firebird/common.h @@ -10,6 +10,7 @@ #include "soci/firebird/soci-firebird.h" #include "soci-compiler.h" +#include #include #include #include @@ -135,20 +136,20 @@ void to_isc(void * val, XSQLVAR * var, short x_scale = 0) { case SQL_SHORT: { - short tmp = static_cast(round_for_isc(value*multiplier)/divisor); - std::memcpy(var->sqldata, &tmp, sizeof(short)); + int16_t tmp = static_cast(round_for_isc(value*multiplier)/divisor); + std::memcpy(var->sqldata, &tmp, sizeof(int16_t)); } break; case SQL_LONG: { - int tmp = static_cast(round_for_isc(value*multiplier)/divisor); - std::memcpy(var->sqldata, &tmp, sizeof(int)); + int32_t tmp = static_cast(round_for_isc(value*multiplier)/divisor); + std::memcpy(var->sqldata, &tmp, sizeof(int32_t)); } break; case SQL_INT64: { - long long tmp = static_cast(round_for_isc(value*multiplier)/divisor); - std::memcpy(var->sqldata, &tmp, sizeof(long long)); + int64_t tmp = static_cast(round_for_isc(value*multiplier)/divisor); + std::memcpy(var->sqldata, &tmp, sizeof(int64_t)); } break; case SQL_FLOAT: @@ -240,11 +241,11 @@ T1 from_isc(XSQLVAR * var) switch (var->sqltype & ~1) { case SQL_SHORT: - return static_cast(*reinterpret_cast(var->sqldata)/tens); + return static_cast(*reinterpret_cast(var->sqldata)/tens); case SQL_LONG: - return static_cast(*reinterpret_cast(var->sqldata)/tens); + return static_cast(*reinterpret_cast(var->sqldata)/tens); case SQL_INT64: - return static_cast(*reinterpret_cast(var->sqldata)/tens); + return static_cast(*reinterpret_cast(var->sqldata)/tens); case SQL_FLOAT: return static_cast(*reinterpret_cast(var->sqldata)); case SQL_DOUBLE: diff --git a/include/private/soci-exchange-cast.h b/include/private/soci-exchange-cast.h index 9f5b6cfdd..596386dc4 100644 --- a/include/private/soci-exchange-cast.h +++ b/include/private/soci-exchange-cast.h @@ -11,6 +11,7 @@ #include "soci/soci-backend.h" #include "soci/type-wrappers.h" +#include #include namespace soci @@ -35,27 +36,51 @@ struct exchange_type_traits }; template <> -struct exchange_type_traits +struct exchange_type_traits { - typedef short value_type; + typedef int8_t value_type; }; template <> -struct exchange_type_traits +struct exchange_type_traits { - typedef int value_type; + typedef uint8_t value_type; }; template <> -struct exchange_type_traits +struct exchange_type_traits { - typedef long long value_type; + typedef int16_t value_type; }; template <> -struct exchange_type_traits +struct exchange_type_traits { - typedef unsigned long long value_type; + typedef uint16_t value_type; +}; + +template <> +struct exchange_type_traits +{ + typedef int32_t value_type; +}; + +template <> +struct exchange_type_traits +{ + typedef uint32_t value_type; +}; + +template <> +struct exchange_type_traits +{ + typedef int64_t value_type; +}; + +template <> +struct exchange_type_traits +{ + typedef uint64_t value_type; }; template <> diff --git a/include/private/soci-vector-helpers.h b/include/private/soci-vector-helpers.h index eae5fbabd..d4eff1443 100644 --- a/include/private/soci-vector-helpers.h +++ b/include/private/soci-vector-helpers.h @@ -33,14 +33,22 @@ inline std::size_t get_vector_size(exchange_type e, void *data) return exchange_vector_type_cast(data).size(); case x_stdstring: return exchange_vector_type_cast(data).size(); - case x_short: - return exchange_vector_type_cast(data).size(); - case x_integer: - return exchange_vector_type_cast(data).size(); - case x_long_long: - return exchange_vector_type_cast(data).size(); - case x_unsigned_long_long: - return exchange_vector_type_cast(data).size(); + case x_int8: + return exchange_vector_type_cast(data).size(); + case x_uint8: + return exchange_vector_type_cast(data).size(); + case x_int16: + return exchange_vector_type_cast(data).size(); + case x_uint16: + return exchange_vector_type_cast(data).size(); + case x_int32: + return exchange_vector_type_cast(data).size(); + case x_uint32: + return exchange_vector_type_cast(data).size(); + case x_int64: + return exchange_vector_type_cast(data).size(); + case x_uint64: + return exchange_vector_type_cast(data).size(); case x_double: return exchange_vector_type_cast(data).size(); case x_stdtm: @@ -68,17 +76,29 @@ inline void resize_vector(exchange_type e, void *data, std::size_t newSize) case x_stdstring: exchange_vector_type_cast(data).resize(newSize); return; - case x_short: - exchange_vector_type_cast(data).resize(newSize); + case x_int8: + exchange_vector_type_cast(data).resize(newSize); return; - case x_integer: - exchange_vector_type_cast(data).resize(newSize); + case x_uint8: + exchange_vector_type_cast(data).resize(newSize); return; - case x_long_long: - exchange_vector_type_cast(data).resize(newSize); + case x_int16: + exchange_vector_type_cast(data).resize(newSize); return; - case x_unsigned_long_long: - exchange_vector_type_cast(data).resize(newSize); + case x_uint16: + exchange_vector_type_cast(data).resize(newSize); + return; + case x_int32: + exchange_vector_type_cast(data).resize(newSize); + return; + case x_uint32: + exchange_vector_type_cast(data).resize(newSize); + return; + case x_int64: + exchange_vector_type_cast(data).resize(newSize); + return; + case x_uint64: + exchange_vector_type_cast(data).resize(newSize); return; case x_double: exchange_vector_type_cast(data).resize(newSize); @@ -112,10 +132,14 @@ inline std::string& vector_string_value(exchange_type e, void *data, std::size_t case x_longstring: return exchange_vector_type_cast(data).at(ind).value; case x_char: - case x_short: - case x_integer: - case x_long_long: - case x_unsigned_long_long: + case x_int8: + case x_uint8: + case x_int16: + case x_uint16: + case x_int32: + case x_uint32: + case x_int64: + case x_uint64: case x_double: case x_stdtm: case x_statement: diff --git a/include/soci/column-info.h b/include/soci/column-info.h index 2105628e7..21a04f013 100644 --- a/include/soci/column-info.h +++ b/include/soci/column-info.h @@ -12,13 +12,17 @@ #include "soci/type-conversion.h" #include "soci/values.h" +#include + namespace soci { struct SOCI_DECL column_info { std::string name; + // DEPRECATED. USE dataType INSTEAD. data_type type; + db_type dataType; std::size_t length; // meaningful for text columns only std::size_t precision; std::size_t scale; @@ -33,22 +37,36 @@ struct type_conversion static std::size_t get_numeric_value(const values & v, const std::string & field_name) { - data_type dt = v.get_properties(field_name).get_data_type(); + db_type dt = v.get_properties(field_name).get_db_type(); switch (dt) { - case dt_double: + case db_double: return static_cast( v.get(field_name, 0.0)); - case dt_integer: + case db_int8: + return static_cast( + v.get(field_name, 0)); + case db_uint8: + return static_cast( + v.get(field_name, 0)); + case db_int16: + return static_cast( + v.get(field_name, 0)); + case db_uint16: + return static_cast( + v.get(field_name, 0)); + case db_int32: + return static_cast( + v.get(field_name, 0)); + case db_uint32: return static_cast( - v.get(field_name, 0)); - case dt_long_long: + v.get(field_name, 0)); + case db_int64: return static_cast( - v.get(field_name, 0ll)); - case dt_unsigned_long_long: + v.get(field_name, 0ll)); + case db_uint64: return static_cast( - v.get(field_name, 0ull)); - break; + v.get(field_name, 0ull)); default: return 0u; } @@ -69,10 +87,12 @@ struct type_conversion type_name.find("CHAR") != std::string::npos) { ci.type = dt_string; + ci.dataType = db_string; } else if (type_name == "integer" || type_name == "INTEGER") { ci.type = dt_integer; + ci.dataType = db_int32; } else if (type_name.find("number") != std::string::npos || type_name.find("NUMBER") != std::string::npos || @@ -82,10 +102,12 @@ struct type_conversion if (ci.scale != 0) { ci.type = dt_double; + ci.dataType = db_double; } else { ci.type = dt_integer; + ci.dataType = db_int32; } } else if (type_name.find("time") != std::string::npos || @@ -94,6 +116,7 @@ struct type_conversion type_name.find("DATE") != std::string::npos) { ci.type = dt_date; + ci.dataType = db_date; } else if (type_name.find("blob") != std::string::npos || type_name.find("BLOB") != std::string::npos || @@ -101,16 +124,19 @@ struct type_conversion type_name.find("OID") != std::string::npos) { ci.type = dt_blob; + ci.dataType = db_blob; } else if (type_name.find("xml") != std::string::npos || type_name.find("XML") != std::string::npos) { ci.type = dt_xml; + ci.dataType = db_xml; } else { // this seems to be a safe default ci.type = dt_string; + ci.dataType = db_string; } const std::string & nullable_s = v.get("IS_NULLABLE"); diff --git a/include/soci/db2/soci-db2.h b/include/soci/db2/soci-db2.h index fcd326d59..5ede930b0 100644 --- a/include/soci/db2/soci-db2.h +++ b/include/soci/db2/soci-db2.h @@ -197,7 +197,7 @@ struct SOCI_DB2_DECL db2_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const& query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type& dtype, std::string& columnName) override; + void describe_column(int colNum, data_type& dtype, db_type& dbtype, std::string& columnName) override; size_t column_size(int col); db2_standard_into_type_backend* make_into_type_backend() override; diff --git a/include/soci/empty/soci-empty.h b/include/soci/empty/soci-empty.h index eb58e8524..c7c62ec3f 100644 --- a/include/soci/empty/soci-empty.h +++ b/include/soci/empty/soci-empty.h @@ -114,7 +114,7 @@ struct SOCI_EMPTY_DECL empty_statement_backend : details::statement_backend std::string rewrite_for_procedure_call(std::string const& query) override; int prepare_for_describe() override; - void describe_column(int colNum, data_type& dtype, std::string& columnName) override; + void describe_column(int colNum, data_type& dtype, db_type& dbtype, std::string& columnName) override; empty_standard_into_type_backend* make_into_type_backend() override; empty_standard_use_type_backend* make_use_type_backend() override; diff --git a/include/soci/exchange-traits.h b/include/soci/exchange-traits.h index 77f558698..068571daf 100644 --- a/include/soci/exchange-traits.h +++ b/include/soci/exchange-traits.h @@ -8,10 +8,12 @@ #ifndef SOCI_EXCHANGE_TRAITS_H_INCLUDED #define SOCI_EXCHANGE_TRAITS_H_INCLUDED +#include "soci/soci-types.h" #include "soci/type-conversion-traits.h" #include "soci/soci-backend.h" #include "soci/type-wrappers.h" // std +#include #include #include #include @@ -43,66 +45,92 @@ struct exchange_traits }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_short }; + enum { x_type = x_int8 }; }; template <> -struct exchange_traits : exchange_traits +struct exchange_traits { + typedef basic_type_tag type_family; + enum { x_type = x_uint8 }; }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_integer }; + enum { x_type = x_int16 }; }; template <> -struct exchange_traits : exchange_traits +struct exchange_traits { + typedef basic_type_tag type_family; + enum { x_type = x_uint16 }; }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_char }; + enum { x_type = x_int32 }; }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_long_long }; + enum { x_type = x_uint32 }; }; template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = x_unsigned_long_long }; + enum { x_type = x_int64 }; }; -// long must be mapped either to x_integer or x_long_long: -template struct long_traits_helper; -template<> struct long_traits_helper<4> { enum { x_type = x_integer }; }; -template<> struct long_traits_helper<8> { enum { x_type = x_long_long }; }; - template <> -struct exchange_traits +struct exchange_traits { typedef basic_type_tag type_family; - enum { x_type = long_traits_helper::x_type }; + enum { x_type = x_uint64 }; +}; + +#if defined(SOCI_INT64_IS_LONG) +template <> +struct exchange_traits : exchange_traits +{ +}; + +template <> +struct exchange_traits : exchange_traits +{ +}; +#elif defined(SOCI_LONG_IS_64_BIT) +template <> +struct exchange_traits : exchange_traits +{ +}; + +template <> +struct exchange_traits : exchange_traits +{ +}; +#else +template <> +struct exchange_traits : exchange_traits +{ }; template <> -struct exchange_traits : exchange_traits +struct exchange_traits : exchange_traits { }; +#endif template <> struct exchange_traits @@ -111,6 +139,13 @@ struct exchange_traits enum { x_type = x_double }; }; +template <> +struct exchange_traits +{ + typedef basic_type_tag type_family; + enum { x_type = x_char }; +}; + template <> struct exchange_traits { diff --git a/include/soci/firebird/soci-firebird.h b/include/soci/firebird/soci-firebird.h index 61bc76716..fef98de02 100644 --- a/include/soci/firebird/soci-firebird.h +++ b/include/soci/firebird/soci-firebird.h @@ -202,6 +202,7 @@ struct firebird_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; firebird_standard_into_type_backend * make_into_type_backend() override; diff --git a/include/soci/fixed-size-ints.h b/include/soci/fixed-size-ints.h new file mode 100644 index 000000000..fcdcef44d --- /dev/null +++ b/include/soci/fixed-size-ints.h @@ -0,0 +1,155 @@ +#ifndef SOCI_FIXED_SIZE_INTS_H_INCLUDED +#define SOCI_FIXED_SIZE_INTS_H_INCLUDED + +#include "soci/soci-types.h" +#include "soci/type-conversion-traits.h" + +#include + +namespace soci +{ + +// Completion of dt_[u]int* bindings for all architectures. +// This allows us to extract values on types where the type definition is +// specific to the underlying architecture. E.g. Unix defines a int64_t as +// long. This would make it impossible to extract a dt_int64 value as both +// long and long long. With the following type_conversion specializations, +// this becomes possible. + +#if defined(SOCI_INT64_IS_LONG) +template <> +struct type_conversion +{ + typedef int64_t base_type; + + static void from_base(base_type const & in, indicator ind, long long & out) + { + if (ind == i_null) + { + throw soci_error("Null value not allowed for this type."); + } + + out = static_cast(in); + } + + static void to_base(long long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; + +template <> +struct type_conversion +{ + typedef uint64_t base_type; + + static void from_base(base_type const & in, indicator ind, unsigned long long & out) + { + if (ind == i_null) + { + throw soci_error("Null value not allowed for this type."); + } + + out = static_cast(in); + } + + static void to_base(unsigned long long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; +#elif defined(SOCI_LONG_IS_64_BIT) +template <> +struct type_conversion +{ + typedef int64_t base_type; + + static void from_base(base_type const & in, indicator ind, long & out) + { + if (ind == i_null) + { + throw soci_error("Null value not allowed for this type."); + } + + out = static_cast(in); + } + + static void to_base(long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; + +template <> +struct type_conversion +{ + typedef uint64_t base_type; + + static void from_base(base_type const & in, indicator ind, unsigned long & out) + { + if (ind == i_null) + { + throw soci_error("Null value not allowed for this type."); + } + + out = static_cast(in); + } + + static void to_base(unsigned long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; +#else +template <> +struct type_conversion +{ + typedef int32_t base_type; + + static void from_base(base_type const & in, indicator ind, long & out) + { + if (ind == i_null) + { + throw soci_error("Null value not allowed for this type."); + } + + out = static_cast(in); + } + + static void to_base(long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; + +template <> +struct type_conversion +{ + typedef uint32_t base_type; + + static void from_base(base_type const & in, indicator ind, unsigned long & out) + { + if (ind == i_null) + { + throw soci_error("Null value not allowed for this type."); + } + + out = static_cast(in); + } + + static void to_base(unsigned long const & in, base_type & out, indicator & ind) + { + out = static_cast(in); + ind = i_ok; + } +}; +#endif + +} // namespace soci + +#endif // SOCI_FIXED_SIZE_INTS_H_INCLUDED diff --git a/include/soci/mysql/soci-mysql.h b/include/soci/mysql/soci-mysql.h index 456b0239e..daa2f44bc 100644 --- a/include/soci/mysql/soci-mysql.h +++ b/include/soci/mysql/soci-mysql.h @@ -182,6 +182,7 @@ struct mysql_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; mysql_standard_into_type_backend * make_into_type_backend() override; diff --git a/include/soci/odbc/soci-odbc.h b/include/soci/odbc/soci-odbc.h index 4c32ef211..833d33711 100644 --- a/include/soci/odbc/soci-odbc.h +++ b/include/soci/odbc/soci-odbc.h @@ -78,6 +78,8 @@ class odbc_standard_type_backend_base inline SQLLEN get_sqllen_from_value(const SQLLEN val) const; inline void set_sqllen_from_value(SQLLEN &target, const SQLLEN val) const; + inline bool supports_negative_tinyint() const; + inline bool can_convert_to_unsigned_sql_type() const; odbc_statement_backend &statement_; private: @@ -252,6 +254,7 @@ struct odbc_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; // helper for defining into vector @@ -545,6 +548,25 @@ inline void odbc_standard_type_backend_base::set_sqllen_from_value(SQLLEN &targe } } +inline bool odbc_standard_type_backend_base::supports_negative_tinyint() const +{ + // MSSQL ODBC driver only supports a range of [0..255] for tinyint. + return statement_.session_.get_database_product() + != odbc_session_backend::prod_mssql; +} + +inline bool odbc_standard_type_backend_base::can_convert_to_unsigned_sql_type() const +{ + // MSSQL ODBC driver seemingly can't handle the conversion of unsigned C + // types to their respective unsigned SQL type because they are out of + // range for their supported signed types. This results in the error + // "Numeric value out of range (SQL state 22003)". + // The only place it works is with tinyint values as their range is + // [0..255], i.e. they have enough space for unsigned values anyway. + return statement_.session_.get_database_product() + != odbc_session_backend::prod_mssql; +} + inline SQLLEN odbc_vector_into_type_backend::get_sqllen_from_vector_at(std::size_t idx) const { if (requires_noncompliant_32bit_sqllen()) diff --git a/include/soci/once-temp-type.h b/include/soci/once-temp-type.h index a6be0942a..b860d35e8 100644 --- a/include/soci/once-temp-type.h +++ b/include/soci/once-temp-type.h @@ -133,8 +133,11 @@ class SOCI_DECL ddl_type int precision, int scale); void drop_column(const std::string & tableName, const std::string & columnName); + // DEPRECATED. USE column(std::string, db_type, int, int) INSTEAD. ddl_type & column(const std::string & columnName, data_type dt, int precision = 0, int scale = 0); + ddl_type & column(const std::string & columnName, db_type dt, + int precision = 0, int scale = 0); ddl_type & unique(const std::string & name, const std::string & columnNames); ddl_type & primary_key(const std::string & name, diff --git a/include/soci/oracle/soci-oracle.h b/include/soci/oracle/soci-oracle.h index 3dc52630d..6224caf5c 100644 --- a/include/soci/oracle/soci-oracle.h +++ b/include/soci/oracle/soci-oracle.h @@ -230,6 +230,7 @@ struct oracle_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; // helper for defining into vector @@ -330,6 +331,78 @@ struct oracle_session_backend : details::session_backend } std::string create_column_type(data_type dt, + int precision, int scale) override + { + // Oracle-specific SQL syntax: + + std::string res; + switch (dt) + { + case dt_string: + { + std::ostringstream oss; + + if (precision == 0) + { + oss << "clob"; + } + else + { + oss << "varchar(" << precision << ")"; + } + + res += oss.str(); + } + break; + + case dt_date: + res += "timestamp"; + break; + + case dt_double: + { + std::ostringstream oss; + if (precision == 0) + { + oss << "number"; + } + else + { + oss << "number(" << precision << ", " << scale << ")"; + } + + res += oss.str(); + } + break; + + case dt_integer: + res += "integer"; + break; + + case dt_long_long: + res += "number"; + break; + + case dt_unsigned_long_long: + res += "number"; + break; + + case dt_blob: + res += "blob"; + break; + + case dt_xml: + res += "xmltype"; + break; + + default: + throw soci_error("this data_type is not supported in create_column"); + } + + return res; + } + + std::string create_column_type(db_type dt, int precision, int scale) override { // Oracle-specific SQL syntax: @@ -337,7 +410,7 @@ struct oracle_session_backend : details::session_backend std::string res; switch (dt) { - case dt_string: + case db_string: { std::ostringstream oss; @@ -354,11 +427,11 @@ struct oracle_session_backend : details::session_backend } break; - case dt_date: + case db_date: res += "timestamp"; break; - case dt_double: + case db_double: { std::ostringstream oss; if (precision == 0) @@ -374,23 +447,27 @@ struct oracle_session_backend : details::session_backend } break; - case dt_integer: + case db_int16: + res += "smallint"; + break; + + case db_int32: res += "integer"; break; - case dt_long_long: + case db_int64: res += "number"; break; - case dt_unsigned_long_long: + case db_uint64: res += "number"; break; - case dt_blob: + case db_blob: res += "blob"; break; - case dt_xml: + case db_xml: res += "xmltype"; break; @@ -403,6 +480,13 @@ struct oracle_session_backend : details::session_backend std::string add_column(const std::string & tableName, const std::string & columnName, data_type dt, int precision, int scale) override + { + return "alter table " + tableName + " add " + + columnName + " " + create_column_type(dt, precision, scale); + } + 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); @@ -410,6 +494,13 @@ struct oracle_session_backend : details::session_backend std::string alter_column(const std::string & tableName, const std::string & columnName, data_type dt, int precision, int scale) override + { + return "alter table " + tableName + " modify " + + 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); diff --git a/include/soci/postgresql/soci-postgresql.h b/include/soci/postgresql/soci-postgresql.h index f518d2e9d..594d41034 100644 --- a/include/soci/postgresql/soci-postgresql.h +++ b/include/soci/postgresql/soci-postgresql.h @@ -271,6 +271,7 @@ struct postgresql_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type & dtype, + db_type & dbtype, std::string & columnName) override; postgresql_standard_into_type_backend * make_into_type_backend() override; diff --git a/include/soci/row.h b/include/soci/row.h index 8cd816dc4..3279dae25 100644 --- a/include/soci/row.h +++ b/include/soci/row.h @@ -27,14 +27,20 @@ class SOCI_DECL column_properties public: std::string get_name() const { return name_; } + // DEPRECATED. USE get_db_type() INSTEAD. data_type get_data_type() const { return dataType_; } + db_type get_db_type() const { return dbType_; } void set_name(std::string const& name) { name_ = name; } + // DEPRECATED. USE set_db_type(db_type) INSTEAD. void set_data_type(data_type dataType) { dataType_ = dataType; } + void set_db_type(db_type dataType) { dbType_ = dataType; } private: std::string name_; + // DEPRECATED. USE exchangeDataType_ INSTEAD. data_type dataType_; + db_type dbType_; }; class SOCI_DECL row diff --git a/include/soci/soci-backend.h b/include/soci/soci-backend.h index 237f6587a..72f058835 100644 --- a/include/soci/soci-backend.h +++ b/include/soci/soci-backend.h @@ -19,11 +19,36 @@ namespace soci { +// DEPRECATED. USE db_type INSTEAD. // data types, as seen by the user enum data_type { - dt_string, dt_date, dt_double, dt_integer, dt_long_long, dt_unsigned_long_long, - dt_blob, dt_xml + dt_string, + dt_integer, + dt_long_long, + dt_unsigned_long_long, + dt_double, + dt_date, + dt_blob, + dt_xml +}; + +// data types, as seen by the user +enum db_type +{ + db_string, + db_int8, + db_uint8, + db_int16, + db_uint16, + db_int32, + db_uint32, + db_int64, + db_uint64, + db_double, + db_date, + db_blob, + db_xml }; // the enum type for indicator variables @@ -40,10 +65,18 @@ enum exchange_type { x_char, x_stdstring, - x_short, - x_integer, - x_long_long, - x_unsigned_long_long, + x_int8, + x_uint8, + x_int16, + x_short = x_int16, + x_uint16, + x_int32, + x_integer = x_int32, + x_uint32, + x_int64, + x_long_long = x_int64, + x_uint64, + x_unsigned_long_long = x_uint64, x_double, x_stdtm, x_statement, @@ -198,6 +231,7 @@ class statement_backend virtual int prepare_for_describe() = 0; virtual void describe_column(int colNum, data_type& dtype, + db_type& dbtype, std::string& column_name) = 0; virtual standard_into_type_backend* make_into_type_backend() = 0; @@ -313,7 +347,54 @@ class session_backend { return "truncate table " + tableName; } + // DEPRECATED. USE create_column_type(db_type, int, int) INSTEAD. virtual std::string create_column_type(data_type dt, + int precision, int scale) + { + // PostgreSQL was selected as a baseline for the syntax: + + std::string res; + switch (dt) + { + case dt_string: + res += create_column_type(db_string, precision, scale); + break; + + case dt_date: + res += create_column_type(db_date, precision, scale); + break; + + case dt_double: + res += create_column_type(db_double, precision, scale); + break; + + case dt_integer: + res += create_column_type(db_int32, precision, scale); + break; + + case dt_long_long: + res += create_column_type(db_int64, precision, scale); + break; + + case dt_unsigned_long_long: + res += create_column_type(db_uint64, precision, scale); + break; + + case dt_blob: + res += create_column_type(db_blob, precision, scale); + break; + + case dt_xml: + res += create_column_type(db_xml, precision, scale); + break; + + default: + throw soci_error("this data_type is not supported in create_column"); + } + + return res; + } + virtual std::string create_column_type(db_type dt, int precision, int scale) { // PostgreSQL was selected as a baseline for the syntax: @@ -321,7 +402,7 @@ class session_backend std::string res; switch (dt) { - case dt_string: + case db_string: { std::ostringstream oss; @@ -338,11 +419,11 @@ class session_backend } break; - case dt_date: + case db_date: res += "timestamp"; break; - case dt_double: + case db_double: { std::ostringstream oss; if (precision == 0) @@ -358,32 +439,36 @@ class session_backend } break; - case dt_integer: - res += "integer"; + case db_int16: + case db_uint16: + res += "smallint"; break; - case dt_long_long: - res += "bigint"; + case db_int32: + case db_uint32: + res += "integer"; break; - case dt_unsigned_long_long: + case db_int64: + case db_uint64: res += "bigint"; break; - case dt_blob: + case db_blob: res += "oid"; break; - case dt_xml: + case db_xml: res += "xml"; break; default: - throw soci_error("this data_type is not supported in create_column"); + throw soci_error("this db_type is not supported in create_column"); } return res; } + // DEPRECATED. USE add_column(std::string, std::string, db_type, int, int) INSTEAD. virtual std::string add_column(const std::string & tableName, const std::string & columnName, data_type dt, int precision, int scale) @@ -391,13 +476,31 @@ class session_backend return "alter table " + tableName + " add column " + columnName + " " + create_column_type(dt, precision, scale); } + virtual std::string add_column(const std::string & tableName, + const std::string & columnName, + db_type dt, + int precision, int scale) + { + return "alter table " + tableName + " add column " + columnName + + " " + create_column_type(dt, precision, scale); + } + // DEPRECATED. USE alter_column(std::string, std::string, db_type, int, int) INSTEAD. virtual std::string alter_column(const std::string & tableName, - const std::string & columnName, data_type dt, - int precision, int scale) + const std::string & columnName, data_type dt, + int precision, int scale) + { + return "alter table " + tableName + " alter column " + + columnName + " type " + + create_column_type(dt, precision, scale); + } + virtual std::string alter_column(const std::string & tableName, + const std::string & columnName, + db_type dt, + int precision, int scale) { return "alter table " + tableName + " alter column " + - columnName + " type " + - create_column_type(dt, precision, scale); + columnName + " type " + + create_column_type(dt, precision, scale); } virtual std::string drop_column(const std::string & tableName, const std::string & columnName) diff --git a/include/soci/soci-platform.h b/include/soci/soci-platform.h index 3f94cb57b..bb2b8eeff 100644 --- a/include/soci/soci-platform.h +++ b/include/soci/soci-platform.h @@ -175,4 +175,23 @@ private: \ #define SOCI_DUMMY_RETURN(x) return x #endif +#define SOCI_OS_LINUX 0x0001 +#define SOCI_OS_FREE_BSD 0x0002 +#define SOCI_OS_APPLE 0x0003 +#define SOCI_OS_WINDOWS 0x0004 + +#if defined(linux) || defined(__linux) || defined(__linux__) + #define SOCI_OS SOCI_OS_LINUX +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) + #define SOCI_OS SOCI_OS_FREE_BSD +#elif defined(__APPLE__) + #define SOCI_OS SOCI_OS_APPLE +#elif defined(_WIN32) || defined(_WIN64) + #define SOCI_OS SOCI_OS_WINDOWS +#endif + +#if !defined(SOCI_OS) + #error "Unknown platform" +#endif + #endif // SOCI_PLATFORM_H_INCLUDED diff --git a/include/soci/soci-simple.h b/include/soci/soci-simple.h index 5771c44eb..01a32f760 100644 --- a/include/soci/soci-simple.h +++ b/include/soci/soci-simple.h @@ -10,6 +10,8 @@ #include "soci/soci-platform.h" +#include + #ifdef __cplusplus extern "C" { @@ -59,6 +61,14 @@ SOCI_DECL void soci_destroy_statement(statement_handle st); SOCI_DECL int soci_into_string (statement_handle st); SOCI_DECL int soci_into_int (statement_handle st); SOCI_DECL int soci_into_long_long(statement_handle st); +SOCI_DECL int soci_into_int8 (statement_handle st); +SOCI_DECL int soci_into_uint8 (statement_handle st); +SOCI_DECL int soci_into_int16 (statement_handle st); +SOCI_DECL int soci_into_uint16 (statement_handle st); +SOCI_DECL int soci_into_int32 (statement_handle st); +SOCI_DECL int soci_into_uint32 (statement_handle st); +SOCI_DECL int soci_into_int64 (statement_handle st); +SOCI_DECL int soci_into_uint64 (statement_handle st); SOCI_DECL int soci_into_double (statement_handle st); SOCI_DECL int soci_into_date (statement_handle st); SOCI_DECL int soci_into_blob (statement_handle st); @@ -67,6 +77,14 @@ SOCI_DECL int soci_into_blob (statement_handle st); SOCI_DECL int soci_into_string_v (statement_handle st); SOCI_DECL int soci_into_int_v (statement_handle st); SOCI_DECL int soci_into_long_long_v(statement_handle st); +SOCI_DECL int soci_into_int8_v (statement_handle st); +SOCI_DECL int soci_into_uint8_v (statement_handle st); +SOCI_DECL int soci_into_int16_v (statement_handle st); +SOCI_DECL int soci_into_uint16_v (statement_handle st); +SOCI_DECL int soci_into_int32_v (statement_handle st); +SOCI_DECL int soci_into_uint32_v (statement_handle st); +SOCI_DECL int soci_into_int64_v (statement_handle st); +SOCI_DECL int soci_into_uint64_v (statement_handle st); SOCI_DECL int soci_into_double_v (statement_handle st); SOCI_DECL int soci_into_date_v (statement_handle st); @@ -75,6 +93,14 @@ SOCI_DECL int soci_get_into_state (statement_handle st, int position SOCI_DECL char const * soci_get_into_string (statement_handle st, int position); SOCI_DECL int soci_get_into_int (statement_handle st, int position); SOCI_DECL long long soci_get_into_long_long(statement_handle st, int position); +SOCI_DECL int8_t soci_get_into_int8 (statement_handle st, int position); +SOCI_DECL uint8_t soci_get_into_uint8 (statement_handle st, int position); +SOCI_DECL int16_t soci_get_into_int16 (statement_handle st, int position); +SOCI_DECL uint16_t soci_get_into_uint16 (statement_handle st, int position); +SOCI_DECL int32_t soci_get_into_int32 (statement_handle st, int position); +SOCI_DECL uint32_t soci_get_into_uint32 (statement_handle st, int position); +SOCI_DECL int64_t soci_get_into_int64 (statement_handle st, int position); +SOCI_DECL uint64_t soci_get_into_uint64 (statement_handle st, int position); SOCI_DECL double soci_get_into_double (statement_handle st, int position); SOCI_DECL char const * soci_get_into_date (statement_handle st, int position); SOCI_DECL blob_handle soci_get_into_blob (statement_handle st, int position); @@ -88,6 +114,14 @@ SOCI_DECL int soci_get_into_state_v (statement_handle st, int positi SOCI_DECL char const * soci_get_into_string_v (statement_handle st, int position, int index); SOCI_DECL int soci_get_into_int_v (statement_handle st, int position, int index); SOCI_DECL long long soci_get_into_long_long_v(statement_handle st, int position, int index); +SOCI_DECL int8_t soci_get_into_int8_v (statement_handle st, int position, int index); +SOCI_DECL uint8_t soci_get_into_uint8_v (statement_handle st, int position, int index); +SOCI_DECL int16_t soci_get_into_int16_v (statement_handle st, int position, int index); +SOCI_DECL uint16_t soci_get_into_uint16_v (statement_handle st, int position, int index); +SOCI_DECL int32_t soci_get_into_int32_v (statement_handle st, int position, int index); +SOCI_DECL uint32_t soci_get_into_uint32_v (statement_handle st, int position, int index); +SOCI_DECL int64_t soci_get_into_int64_v (statement_handle st, int position, int index); +SOCI_DECL uint64_t soci_get_into_uint64_v (statement_handle st, int position, int index); SOCI_DECL double soci_get_into_double_v (statement_handle st, int position, int index); SOCI_DECL char const * soci_get_into_date_v (statement_handle st, int position, int index); @@ -96,6 +130,14 @@ SOCI_DECL char const * soci_get_into_date_v (statement_handle st, int positi SOCI_DECL void soci_use_string (statement_handle st, char const * name); SOCI_DECL void soci_use_int (statement_handle st, char const * name); SOCI_DECL void soci_use_long_long(statement_handle st, char const * name); +SOCI_DECL void soci_use_int8 (statement_handle st, char const * name); +SOCI_DECL void soci_use_uint8 (statement_handle st, char const * name); +SOCI_DECL void soci_use_int16 (statement_handle st, char const * name); +SOCI_DECL void soci_use_uint16 (statement_handle st, char const * name); +SOCI_DECL void soci_use_int32 (statement_handle st, char const * name); +SOCI_DECL void soci_use_uint32 (statement_handle st, char const * name); +SOCI_DECL void soci_use_int64 (statement_handle st, char const * name); +SOCI_DECL void soci_use_uint64 (statement_handle st, char const * name); SOCI_DECL void soci_use_double (statement_handle st, char const * name); SOCI_DECL void soci_use_date (statement_handle st, char const * name); SOCI_DECL void soci_use_blob (statement_handle st, char const * name); @@ -104,15 +146,30 @@ SOCI_DECL void soci_use_blob (statement_handle st, char const * name); SOCI_DECL void soci_use_string_v (statement_handle st, char const * name); SOCI_DECL void soci_use_int_v (statement_handle st, char const * name); SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name); +SOCI_DECL void soci_use_int8_v (statement_handle st, char const * name); +SOCI_DECL void soci_use_uint8_v (statement_handle st, char const * name); +SOCI_DECL void soci_use_int16_v (statement_handle st, char const * name); +SOCI_DECL void soci_use_uint16_v (statement_handle st, char const * name); +SOCI_DECL void soci_use_int32_v (statement_handle st, char const * name); +SOCI_DECL void soci_use_uint32_v (statement_handle st, char const * name); +SOCI_DECL void soci_use_int64_v (statement_handle st, char const * name); +SOCI_DECL void soci_use_uint64_v (statement_handle st, char const * name); SOCI_DECL void soci_use_double_v (statement_handle st, char const * name); SOCI_DECL void soci_use_date_v (statement_handle st, char const * name); - // named write of use elements SOCI_DECL void soci_set_use_state (statement_handle st, char const * name, int state); SOCI_DECL void soci_set_use_string (statement_handle st, char const * name, char const * val); SOCI_DECL void soci_set_use_int (statement_handle st, char const * name, int val); SOCI_DECL void soci_set_use_long_long(statement_handle st, char const * name, long long val); +SOCI_DECL void soci_set_use_int8 (statement_handle st, char const * name, int8_t val); +SOCI_DECL void soci_set_use_uint8 (statement_handle st, char const * name, uint8_t val); +SOCI_DECL void soci_set_use_int18 (statement_handle st, char const * name, int16_t val); +SOCI_DECL void soci_set_use_uint18 (statement_handle st, char const * name, uint16_t val); +SOCI_DECL void soci_set_use_int32 (statement_handle st, char const * name, int32_t val); +SOCI_DECL void soci_set_use_uint32 (statement_handle st, char const * name, uint32_t val); +SOCI_DECL void soci_set_use_int64 (statement_handle st, char const * name, int64_t val); +SOCI_DECL void soci_set_use_uint64 (statement_handle st, char const * name, uint64_t val); SOCI_DECL void soci_set_use_double (statement_handle st, char const * name, double val); SOCI_DECL void soci_set_use_date (statement_handle st, char const * name, char const * val); SOCI_DECL void soci_set_use_blob (statement_handle st, char const * name, blob_handle blob); @@ -130,6 +187,22 @@ SOCI_DECL void soci_set_use_int_v(statement_handle st, char const * name, int index, int val); SOCI_DECL void soci_set_use_long_long_v(statement_handle st, char const * name, int index, long long val); +SOCI_DECL void soci_set_use_int8_v(statement_handle st, + char const * name, int index, int8_t val); +SOCI_DECL void soci_set_use_uint8_v(statement_handle st, + char const * name, int index, uint8_t val); +SOCI_DECL void soci_set_use_int16_v(statement_handle st, + char const * name, int index, int16_t val); +SOCI_DECL void soci_set_use_uint16_v(statement_handle st, + char const * name, int index, uint16_t val); +SOCI_DECL void soci_set_use_int32_v(statement_handle st, + char const * name, int index, int32_t val); +SOCI_DECL void soci_set_use_uint32_v(statement_handle st, + char const * name, int index, uint32_t val); +SOCI_DECL void soci_set_use_int64_v(statement_handle st, + char const * name, int index, int64_t val); +SOCI_DECL void soci_set_use_uint64_v(statement_handle st, + char const * name, int index, uint64_t val); SOCI_DECL void soci_set_use_double_v(statement_handle st, char const * name, int index, double val); SOCI_DECL void soci_set_use_date_v(statement_handle st, @@ -141,6 +214,14 @@ SOCI_DECL int soci_get_use_state (statement_handle st, char const * SOCI_DECL char const * soci_get_use_string (statement_handle st, char const * name); SOCI_DECL int soci_get_use_int (statement_handle st, char const * name); SOCI_DECL long long soci_get_use_long_long(statement_handle st, char const * name); +SOCI_DECL int8_t soci_get_use_int8 (statement_handle st, char const * name); +SOCI_DECL uint8_t soci_get_use_uint8 (statement_handle st, char const * name); +SOCI_DECL int16_t soci_get_use_int16 (statement_handle st, char const * name); +SOCI_DECL uint16_t soci_get_use_uint16 (statement_handle st, char const * name); +SOCI_DECL int32_t soci_get_use_int32 (statement_handle st, char const * name); +SOCI_DECL uint32_t soci_get_use_uint32 (statement_handle st, char const * name); +SOCI_DECL int64_t soci_get_use_int64 (statement_handle st, char const * name); +SOCI_DECL uint64_t soci_get_use_uint64 (statement_handle st, char const * name); SOCI_DECL double soci_get_use_double (statement_handle st, char const * name); SOCI_DECL char const * soci_get_use_date (statement_handle st, char const * name); SOCI_DECL blob_handle soci_get_use_blob (statement_handle st, char const * name); diff --git a/include/soci/soci-types.h b/include/soci/soci-types.h new file mode 100644 index 000000000..be94bc3c8 --- /dev/null +++ b/include/soci/soci-types.h @@ -0,0 +1,15 @@ +#ifndef SOCI_TYPES_H_INCLUDED +#define SOCI_TYPES_H_INCLUDED + +#include "soci/soci-platform.h" + +#if defined(__GNUC__) || defined(__clang__) + #if defined(__LP64__) + #define SOCI_LONG_IS_64_BIT 1 + #if SOCI_OS == SOCI_OS_LINUX || SOCI_OS == SOCI_OS_FREE_BSD + #define SOCI_INT64_IS_LONG 1 + #endif + #endif +#endif + +#endif // SOCI_TYPES_H_INCLUDED diff --git a/include/soci/soci.h b/include/soci/soci.h index 628cd6e7e..39fe0f939 100644 --- a/include/soci/soci.h +++ b/include/soci/soci.h @@ -17,6 +17,7 @@ #include "soci/connection-pool.h" #include "soci/error.h" #include "soci/exchange-traits.h" +#include "soci/fixed-size-ints.h" #include "soci/into.h" #include "soci/into-type.h" #include "soci/once-temp-type.h" @@ -38,7 +39,6 @@ #include "soci/type-holder.h" #include "soci/type-ptr.h" #include "soci/type-wrappers.h" -#include "soci/unsigned-types.h" #include "soci/use.h" #include "soci/use-type.h" #include "soci/values.h" diff --git a/include/soci/sqlite3/soci-sqlite3.h b/include/soci/sqlite3/soci-sqlite3.h index 2520dfd4b..28ae3b634 100644 --- a/include/soci/sqlite3/soci-sqlite3.h +++ b/include/soci/sqlite3/soci-sqlite3.h @@ -17,6 +17,7 @@ #endif #include +#include #include #include @@ -169,13 +170,21 @@ struct sqlite3_column_buffer struct sqlite3_column { bool isNull_; + // DEPRECATED. USE dataType_ INSTEAD. data_type type_; + db_type dataType_; union { sqlite3_column_buffer buffer_; - int int32_; + int8_t int8_; + uint8_t uint8_; + int16_t int16_; + uint16_t uint16_; + int32_t int32_; + uint32_t uint32_; sqlite_api::sqlite3_int64 int64_; + sqlite_api::sqlite3_uint64 uint64_; double double_; }; }; @@ -186,7 +195,9 @@ typedef std::vector sqlite3_recordset; struct sqlite3_column_info { + // DEPRECATED. USE dataType_ INSTEAD. data_type type_; + db_type dataType_; std::string name_; }; typedef std::vector sqlite3_column_info_list; @@ -214,6 +225,7 @@ struct sqlite3_statement_backend : details::statement_backend int prepare_for_describe() override; void describe_column(int colNum, data_type &dtype, + db_type &dbtype, std::string &columnName) override; sqlite3_standard_into_type_backend * make_into_type_backend() override; @@ -308,7 +320,7 @@ struct sqlite3_session_backend : details::session_backend " from sqlite_master where type = 'table'"; } std::string create_column_type(data_type dt, - int , int ) override + int , int ) override { switch (dt) { @@ -327,8 +339,34 @@ struct sqlite3_session_backend : details::session_backend default: throw soci_error("this data_type is not supported in create_column"); } - } + std::string create_column_type(db_type dt, + int , int ) override + { + switch (dt) + { + case db_xml: + case db_string: + return "text"; + case db_double: + return "real"; + case db_date: + case db_int8: + case db_uint8: + case db_int16: + case db_uint16: + case db_int32: + case db_uint32: + case db_int64: + case db_uint64: + return "integer"; + case db_blob: + return "blob"; + default: + throw soci_error("this data_type is not supported in create_column"); + } + } + sqlite_api::sqlite3 *conn_; // This flag is set to true if the internal sqlite_sequence table exists in diff --git a/include/soci/statement.h b/include/soci/statement.h index b356762e0..a1397d106 100644 --- a/include/soci/statement.h +++ b/include/soci/statement.h @@ -144,7 +144,7 @@ class SOCI_DECL statement_impl exchange_for_row(into(*t, *ind)); } - template + template void bind_into(); bool alreadyDescribed_; diff --git a/include/soci/unsigned-types.h b/include/soci/unsigned-types.h deleted file mode 100644 index 0d496a462..000000000 --- a/include/soci/unsigned-types.h +++ /dev/null @@ -1,114 +0,0 @@ -// -// Copyright (C) 2010 Maciej Sobczak -// 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_UNSIGNED_TYPES_H_INCLUDED -#define SOCI_UNSIGNED_TYPES_H_INCLUDED - -#include "soci/type-conversion-traits.h" -#include - -namespace soci -{ - -// simple fall-back for unsigned types - -template <> -struct type_conversion -{ - typedef long long base_type; - - static void from_base(base_type const & in, indicator ind, - unsigned char & out) - { - if (ind == i_null) - { - throw soci_error("Null value not allowed for this type."); - } - - const base_type max = (std::numeric_limits::max)(); - const base_type min = (std::numeric_limits::min)(); - if (in < min || in > max) - { - throw soci_error("Value outside of allowed range."); - } - - out = static_cast(in); - } - - static void to_base(unsigned char const & in, - base_type & out, indicator & ind) - { - out = static_cast(in); - ind = i_ok; - } -}; - -template <> -struct type_conversion -{ - typedef long long base_type; - - static void from_base(base_type const & in, indicator ind, - unsigned short & out) - { - if (ind == i_null) - { - throw soci_error("Null value not allowed for this type."); - } - - const long long max = (std::numeric_limits::max)(); - const long long min = (std::numeric_limits::min)(); - if (in < min || in > max) - { - throw soci_error("Value outside of allowed range."); - } - - out = static_cast(in); - } - - static void to_base(unsigned short const & in, - base_type & out, indicator & ind) - { - out = static_cast(in); - ind = i_ok; - } -}; - -template <> -struct type_conversion -{ - typedef long long base_type; - - static void from_base(base_type const & in, indicator ind, - unsigned int & out) - { - if (ind == i_null) - { - throw soci_error("Null value not allowed for this type."); - } - - const long long max = (std::numeric_limits::max)(); - const long long min = (std::numeric_limits::min)(); - if (in < min || in > max) - { - throw soci_error("Value outside of allowed range."); - } - - out = static_cast(in); - } - - static void to_base(unsigned int const & in, - base_type & out, indicator & ind) - { - out = static_cast(in); - ind = i_ok; - } -}; - -} // namespace soci - -#endif // SOCI_UNSIGNED_TYPES_H_INCLUDED diff --git a/src/backends/db2/standard-into-type.cpp b/src/backends/db2/standard-into-type.cpp index 97e6db6ea..f476d1a55 100644 --- a/src/backends/db2/standard-into-type.cpp +++ b/src/backends/db2/standard-into-type.cpp @@ -11,6 +11,7 @@ #include "soci-exchange-cast.h" #include "soci-mktime.h" #include "common.h" +#include #include using namespace soci; @@ -45,21 +46,37 @@ void db2_standard_into_type_backend::define_by_pos( buf = new char[size]; data = buf; break; - case x_short: + case x_int8: + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + break; + case x_uint8: + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + break; + case x_int16: cType = SQL_C_SSHORT; - size = sizeof(short); + size = sizeof(int16_t); break; - case x_integer: + case x_uint16: + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + break; + case x_int32: cType = SQL_C_SLONG; size = sizeof(SQLINTEGER); break; - case x_long_long: + case x_uint32: + cType = SQL_C_ULONG; + size = sizeof(SQLUINTEGER); + break; + case x_int64: cType = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); break; - case x_unsigned_long_long: + case x_uint64: cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(uint64_t); break; case x_double: cType = SQL_C_DOUBLE; @@ -73,7 +90,7 @@ void db2_standard_into_type_backend::define_by_pos( break; case x_rowid: cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(int64_t); break; default: throw soci_error("Into element used with non-supported type."); diff --git a/src/backends/db2/standard-use-type.cpp b/src/backends/db2/standard-use-type.cpp index 87dbd4698..c6f08c8a0 100644 --- a/src/backends/db2/standard-use-type.cpp +++ b/src/backends/db2/standard-use-type.cpp @@ -10,6 +10,7 @@ #include "soci/db2/soci-db2.h" #include "soci-exchange-cast.h" #include +#include #include #include #include @@ -24,25 +25,45 @@ void *db2_standard_use_type_backend::prepare_for_bind( switch (type) { // simple cases - case x_short: + case x_int8: + sqlType = SQL_SMALLINT; + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + break; + case x_uint8: + sqlType = SQL_SMALLINT; + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + break; + case x_int16: sqlType = SQL_SMALLINT; cType = SQL_C_SSHORT; - size = sizeof(short); + size = sizeof(int16_t); break; - case x_integer: + case x_uint16: + sqlType = SQL_SMALLINT; + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + break; + case x_int32: sqlType = SQL_INTEGER; cType = SQL_C_SLONG; - size = sizeof(int); + size = sizeof(int32_t); + break; + case x_uint32: + sqlType = SQL_INTEGER; + cType = SQL_C_ULONG; + size = sizeof(uint32_t); break; - case x_long_long: + case x_int64: sqlType = SQL_BIGINT; cType = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); break; - case x_unsigned_long_long: + case x_uint64: sqlType = SQL_BIGINT; cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(uint64_t); break; case x_double: sqlType = SQL_DOUBLE; diff --git a/src/backends/db2/statement.cpp b/src/backends/db2/statement.cpp index 73b7432bb..1c154fb46 100644 --- a/src/backends/db2/statement.cpp +++ b/src/backends/db2/statement.cpp @@ -225,7 +225,7 @@ int db2_statement_backend::prepare_for_describe() } void db2_statement_backend::describe_column(int colNum, - data_type & type, std::string & columnName ) + data_type & type, db_type & dbtype, std::string & columnName ) { SQLCHAR colNameBuffer[2048]; SQLSMALLINT colNameBufferOverflow; @@ -253,6 +253,7 @@ SQLCHAR colNameBuffer[2048]; case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: type = dt_date; + dbtype = db_date; break; case SQL_DOUBLE: case SQL_DECIMAL: @@ -260,20 +261,30 @@ SQLCHAR colNameBuffer[2048]; case SQL_FLOAT: case SQL_NUMERIC: type = dt_double; + dbtype = db_double; break; case SQL_TINYINT: + type = dt_integer; + dbtype = db_int8; + break; case SQL_SMALLINT: + type = dt_integer; + dbtype = db_int16; + break; case SQL_INTEGER: type = dt_integer; + dbtype = db_int32; break; case SQL_BIGINT: type = dt_long_long; + dbtype = db_int64; break; case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: default: type = dt_string; + dbtype = db_string; break; } } diff --git a/src/backends/db2/vector-into-type.cpp b/src/backends/db2/vector-into-type.cpp index 19362ec4a..664065d95 100644 --- a/src/backends/db2/vector-into-type.cpp +++ b/src/backends/db2/vector-into-type.cpp @@ -10,6 +10,7 @@ #include "soci/db2/soci-db2.h" #include "soci-mktime.h" #include +#include #include #include #include @@ -39,17 +40,47 @@ void db2_vector_into_type_backend::define_by_pos( switch (type) { // simple cases - case x_short: + case x_int8: + { + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint8: + { + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_int16: { cType = SQL_C_SSHORT; - size = sizeof(short); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint16: + { + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } break; - case x_integer: + case x_int32: { cType = SQL_C_SLONG; size = sizeof(SQLINTEGER); @@ -59,24 +90,34 @@ void db2_vector_into_type_backend::define_by_pos( data = &v[0]; } break; - case x_long_long: + case x_uint32: + { + cType = SQL_C_ULONG; + size = sizeof(SQLUINTEGER); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_int64: { cType = SQL_C_SBIGINT; - size = sizeof(long long); - std::vector *vp - = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int64_t); + std::vector *vp + = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } break; - case x_unsigned_long_long: + case x_uint64: { cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); - std::vector *vp - = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(uint64_t); + std::vector *vp + = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } @@ -286,29 +327,53 @@ void db2_vector_into_type_backend::resize(std::size_t sz) v->resize(sz); } break; - case x_short: + case x_int8: + { + std::vector *v = static_cast *>(data); + v->resize(sz); + } + break; + case x_uint8: + { + std::vector *v = static_cast *>(data); + v->resize(sz); + } + break; + case x_int16: { - std::vector *v = static_cast *>(data); + std::vector *v = static_cast *>(data); v->resize(sz); } break; - case x_integer: + case x_uint16: + { + std::vector *v = static_cast *>(data); + v->resize(sz); + } + break; + case x_int32: { std::vector *v = static_cast *>(data); v->resize(sz); } break; - case x_long_long: + case x_uint32: { - std::vector *v - = static_cast *>(data); + std::vector *v = static_cast *>(data); v->resize(sz); } break; - case x_unsigned_long_long: + case x_int64: { - std::vector *v - = static_cast *>(data); + std::vector *v + = static_cast *>(data); + v->resize(sz); + } + break; + case x_uint64: + { + std::vector *v + = static_cast *>(data); v->resize(sz); } break; @@ -354,29 +419,53 @@ std::size_t db2_vector_into_type_backend::size() sz = v->size(); } break; - case x_short: + case x_int8: + { + std::vector *v = static_cast *>(data); + sz = v->size(); + } + break; + case x_uint8: { - std::vector *v = static_cast *>(data); + std::vector *v = static_cast *>(data); sz = v->size(); } break; - case x_integer: + case x_int16: + { + std::vector *v = static_cast *>(data); + sz = v->size(); + } + break; + case x_uint16: + { + std::vector *v = static_cast *>(data); + sz = v->size(); + } + break; + case x_int32: { std::vector *v = static_cast *>(data); sz = v->size(); } break; - case x_long_long: + case x_uint32: + { + std::vector *v = static_cast *>(data); + sz = v->size(); + } + break; + case x_int64: { - std::vector *v - = static_cast *>(data); + std::vector *v + = static_cast *>(data); sz = v->size(); } break; - case x_unsigned_long_long: + case x_uint64: { - std::vector *v - = static_cast *>(data); + std::vector *v + = static_cast *>(data); sz = v->size(); } break; diff --git a/src/backends/db2/vector-use-type.cpp b/src/backends/db2/vector-use-type.cpp index a5f30f9b1..972002ea2 100644 --- a/src/backends/db2/vector-use-type.cpp +++ b/src/backends/db2/vector-use-type.cpp @@ -10,6 +10,7 @@ #include "soci/soci-platform.h" #include "soci/db2/soci-db2.h" #include +#include #include #include #include @@ -42,48 +43,92 @@ void *db2_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, void* sqlData = NULL; switch (type) { // simple cases - case x_short: + case x_int8: + { + sqlType = SQL_SMALLINT; + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + sqlData = &v[0]; + } + break; + case x_uint8: + { + sqlType = SQL_SMALLINT; + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + sqlData = &v[0]; + } + break; + case x_int16: { sqlType = SQL_SMALLINT; cType = SQL_C_SSHORT; - size = sizeof(short); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + sqlData = &v[0]; + } + break; + case x_uint16: + { + sqlType = SQL_SMALLINT; + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); sqlData = &v[0]; } break; - case x_integer: + case x_int32: { sqlType = SQL_INTEGER; cType = SQL_C_SLONG; - size = sizeof(int); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int32_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(v.size()); + sqlData = &v[0]; + } + break; + case x_uint32: + { + sqlType = SQL_INTEGER; + cType = SQL_C_ULONG; + size = sizeof(uint32_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); sqlData = &v[0]; } break; - case x_long_long: + case x_int64: { sqlType = SQL_BIGINT; cType = SQL_C_SBIGINT; - size = sizeof(long long); - std::vector *vp - = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(int64_t); + std::vector *vp + = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); sqlData = &v[0]; } break; - case x_unsigned_long_long: + case x_uint64: { sqlType = SQL_BIGINT; cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); - std::vector *vp - = static_cast *>(data); - std::vector &v(*vp); + size = sizeof(uint64_t); + std::vector *vp + = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(v.size()); sqlData = &v[0]; } @@ -332,29 +377,53 @@ std::size_t db2_vector_use_type_backend::size() sz = vp->size(); } break; - case x_short: + case x_int8: + { + std::vector *vp = static_cast *>(data); + sz = vp->size(); + } + break; + case x_uint8: + { + std::vector *vp = static_cast *>(data); + sz = vp->size(); + } + break; + case x_int16: + { + std::vector *vp = static_cast *>(data); + sz = vp->size(); + } + break; + case x_uint16: + { + std::vector *vp = static_cast *>(data); + sz = vp->size(); + } + break; + case x_int32: { - std::vector *vp = static_cast *>(data); + std::vector *vp = static_cast *>(data); sz = vp->size(); } break; - case x_integer: + case x_uint32: { - std::vector *vp = static_cast *>(data); + std::vector *vp = static_cast *>(data); sz = vp->size(); } break; - case x_long_long: + case x_int64: { - std::vector *vp - = static_cast *>(data); + std::vector *vp + = static_cast *>(data); sz = vp->size(); } break; - case x_unsigned_long_long: + case x_uint64: { - std::vector *vp - = static_cast *>(data); + std::vector *vp + = static_cast *>(data); sz = vp->size(); } break; diff --git a/src/backends/empty/statement.cpp b/src/backends/empty/statement.cpp index 87f9fda9f..045bee5cd 100644 --- a/src/backends/empty/statement.cpp +++ b/src/backends/empty/statement.cpp @@ -82,7 +82,8 @@ int empty_statement_backend::prepare_for_describe() } void empty_statement_backend::describe_column(int /* colNum */, - data_type & /* type */, std::string & /* columnName */) + data_type & /* type */, db_type & /* dbtype */, + std::string & /* columnName */) { // ... } diff --git a/src/backends/firebird/common.cpp b/src/backends/firebird/common.cpp index 3e8580ebe..9b2b07852 100644 --- a/src/backends/firebird/common.cpp +++ b/src/backends/firebird/common.cpp @@ -123,15 +123,15 @@ void setTextParam(char const * s, std::size_t size, char * buf_, } else if (sqltype == SQL_SHORT) { - parse_decimal(buf_, var, s); + parse_decimal(buf_, var, s); } else if (sqltype == SQL_LONG) { - parse_decimal(buf_, var, s); + parse_decimal(buf_, var, s); } else if (sqltype == SQL_INT64) { - parse_decimal(buf_, var, s); + parse_decimal(buf_, var, s); } else if (sqltype == SQL_TIMESTAMP || sqltype == SQL_TYPE_DATE) @@ -204,15 +204,15 @@ std::string getTextParam(XSQLVAR const *var) } else if ((var->sqltype & ~1) == SQL_SHORT) { - return format_decimal(var->sqldata, var->sqlscale); + return format_decimal(var->sqldata, var->sqlscale); } else if ((var->sqltype & ~1) == SQL_LONG) { - return format_decimal(var->sqldata, var->sqlscale); + return format_decimal(var->sqldata, var->sqlscale); } else if ((var->sqltype & ~1) == SQL_INT64) { - return format_decimal(var->sqldata, var->sqlscale); + return format_decimal(var->sqldata, var->sqlscale); } else throw soci_error("Unexpected string type"); diff --git a/src/backends/firebird/standard-into-type.cpp b/src/backends/firebird/standard-into-type.cpp index 278b23fe1..796220eee 100644 --- a/src/backends/firebird/standard-into-type.cpp +++ b/src/backends/firebird/standard-into-type.cpp @@ -76,18 +76,29 @@ void firebird_standard_into_type_backend::exchangeData() case x_char: exchange_type_cast(data_) = getTextParam(var)[0]; break; - case x_short: - exchange_type_cast(data_) = from_isc(var); + case x_int8: + exchange_type_cast(data_) = from_isc(var); break; - case x_integer: - exchange_type_cast(data_) = from_isc(var); + case x_uint8: + exchange_type_cast(data_) = from_isc(var); break; - case x_long_long: - exchange_type_cast(data_) = from_isc(var); + case x_int16: + exchange_type_cast(data_) = from_isc(var); break; - case x_unsigned_long_long: - exchange_type_cast(data_) = - from_isc(var); + case x_uint16: + exchange_type_cast(data_) = from_isc(var); + break; + case x_int32: + exchange_type_cast(data_) = from_isc(var); + break; + case x_uint32: + exchange_type_cast(data_) = from_isc(var); + break; + case x_int64: + exchange_type_cast(data_) = from_isc(var); + break; + case x_uint64: + exchange_type_cast(data_) = from_isc(var); break; case x_double: exchange_type_cast(data_) = from_isc(var); diff --git a/src/backends/firebird/standard-use-type.cpp b/src/backends/firebird/standard-use-type.cpp index a1fa005e2..254c42d7e 100644 --- a/src/backends/firebird/standard-use-type.cpp +++ b/src/backends/firebird/standard-use-type.cpp @@ -107,17 +107,29 @@ void firebird_standard_use_type_backend::exchangeData() case x_char: setTextParam(&exchange_type_cast(data_), 1, buf_, var); break; - case x_short: - to_isc(data_, var); + case x_int8: + to_isc(data_, var); break; - case x_integer: - to_isc(data_, var); + case x_uint8: + to_isc(data_, var); break; - case x_long_long: - to_isc(data_, var); + case x_int16: + to_isc(data_, var); break; - case x_unsigned_long_long: - to_isc(data_, var); + case x_uint16: + to_isc(data_, var); + break; + case x_int32: + to_isc(data_, var); + break; + case x_uint32: + to_isc(data_, var); + break; + case x_int64: + to_isc(data_, var); + break; + case x_uint64: + to_isc(data_, var); break; case x_double: to_isc(data_, var); diff --git a/src/backends/firebird/statement.cpp b/src/backends/firebird/statement.cpp index f7ee8c947..0249543c5 100644 --- a/src/backends/firebird/statement.cpp +++ b/src/backends/firebird/statement.cpp @@ -658,7 +658,9 @@ int firebird_statement_backend::prepare_for_describe() } void firebird_statement_backend::describe_column(int colNum, - data_type & type, std::string & columnName) + data_type & type, + db_type & dbtype, + std::string & columnName) { XSQLVAR * var = sqldap_->sqlvar+(colNum-1); @@ -669,41 +671,77 @@ void firebird_statement_backend::describe_column(int colNum, case SQL_TEXT: case SQL_VARYING: type = dt_string; + dbtype = db_string; break; case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TIMESTAMP: type = dt_date; + dbtype = db_date; break; case SQL_FLOAT: case SQL_DOUBLE: type = dt_double; + dbtype = db_double; break; case SQL_SHORT: + if (var->sqlscale < 0) + { + if (session_.get_option_decimals_as_strings()) + { + type = dt_string; + dbtype = db_string; + } + else + { + type = dt_double; + dbtype = db_double; + } + } + else + { + type = dt_integer; + dbtype = db_int16; + } + break; case SQL_LONG: if (var->sqlscale < 0) { if (session_.get_option_decimals_as_strings()) + { type = dt_string; + dbtype = db_string; + } else + { type = dt_double; + dbtype = db_double; + } } else { type = dt_integer; + dbtype = db_int32; } break; case SQL_INT64: if (var->sqlscale < 0) { if (session_.get_option_decimals_as_strings()) + { type = dt_string; + dbtype = db_string; + } else + { type = dt_double; + dbtype = db_double; + } } else { type = dt_long_long; + dbtype = db_int64; } break; /* case SQL_BLOB: diff --git a/src/backends/firebird/vector-into-type.cpp b/src/backends/firebird/vector-into-type.cpp index cbc721de4..50ec382a8 100644 --- a/src/backends/firebird/vector-into-type.cpp +++ b/src/backends/firebird/vector-into-type.cpp @@ -63,27 +63,51 @@ void firebird_vector_into_type_backend::exchangeData(std::size_t row) case x_char: setIntoVector(data_, row, getTextParam(var)[0]); break; - case x_short: + case x_int8: { - short tmp = from_isc(var); + int8_t tmp = from_isc(var); setIntoVector(data_, row, tmp); } break; - case x_integer: + case x_uint8: { - int tmp = from_isc(var); + uint8_t tmp = from_isc(var); setIntoVector(data_, row, tmp); } break; - case x_long_long: + case x_int16: { - long long tmp = from_isc(var); + int16_t tmp = from_isc(var); setIntoVector(data_, row, tmp); } break; - case x_unsigned_long_long: + case x_uint16: { - unsigned long long tmp = from_isc(var); + uint16_t tmp = from_isc(var); + setIntoVector(data_, row, tmp); + } + break; + case x_int32: + { + int32_t tmp = from_isc(var); + setIntoVector(data_, row, tmp); + } + break; + case x_uint32: + { + uint32_t tmp = from_isc(var); + setIntoVector(data_, row, tmp); + } + break; + case x_int64: + { + int64_t tmp = from_isc(var); + setIntoVector(data_, row, tmp); + } + break; + case x_uint64: + { + uint64_t tmp = from_isc(var); setIntoVector(data_, row, tmp); } break; diff --git a/src/backends/firebird/vector-use-type.cpp b/src/backends/firebird/vector-use-type.cpp index 13404ac24..0635a54dc 100644 --- a/src/backends/firebird/vector-use-type.cpp +++ b/src/backends/firebird/vector-use-type.cpp @@ -119,24 +119,44 @@ void firebird_vector_use_type_backend::exchangeData(std::size_t row) case x_char: setTextParam(getUseVectorValue(data_, row), 1, buf_, var); break; - case x_short: - to_isc( - static_cast(getUseVectorValue(data_, row)), + case x_int8: + to_isc( + static_cast(getUseVectorValue(data_, row)), var); break; - case x_integer: - to_isc( - static_cast(getUseVectorValue(data_, row)), + case x_uint8: + to_isc( + static_cast(getUseVectorValue(data_, row)), var); break; - case x_long_long: - to_isc( - static_cast(getUseVectorValue(data_, row)), + case x_int16: + to_isc( + static_cast(getUseVectorValue(data_, row)), var); break; - case x_unsigned_long_long: - to_isc( - static_cast(getUseVectorValue(data_, row)), + case x_uint16: + to_isc( + static_cast(getUseVectorValue(data_, row)), + var); + break; + case x_int32: + to_isc( + static_cast(getUseVectorValue(data_, row)), + var); + break; + case x_uint32: + to_isc( + static_cast(getUseVectorValue(data_, row)), + var); + break; + case x_int64: + to_isc( + static_cast(getUseVectorValue(data_, row)), + var); + break; + case x_uint64: + to_isc( + static_cast(getUseVectorValue(data_, row)), var); break; case x_double: diff --git a/src/backends/mysql/standard-into-type.cpp b/src/backends/mysql/standard-into-type.cpp index 06dfc47cc..edb68684f 100644 --- a/src/backends/mysql/standard-into-type.cpp +++ b/src/backends/mysql/standard-into-type.cpp @@ -6,6 +6,7 @@ // http://www.boost.org/LICENSE_1_0.txt) // +#include "soci-cstrtoi.h" #define SOCI_MYSQL_SOURCE #include "soci/mysql/soci-mysql.h" #include "soci/soci-platform.h" @@ -14,6 +15,7 @@ #include "soci-mktime.h" // std #include +#include #include #include #include @@ -89,17 +91,47 @@ void mysql_standard_into_type_backend::post_fetch( dest.assign(buf, lengths[pos]); } break; - case x_short: - parse_num(buf, exchange_type_cast(data_)); + case x_int8: + { + int32_t tmp = 0; + parse_num(buf, tmp); + if (tmp < (std::numeric_limits::min)() || + tmp > (std::numeric_limits::max)()) + { + throw soci_error("Cannot convert data."); + } + exchange_type_cast(data_) = static_cast(tmp); + } + break; + case x_uint8: + { + uint32_t tmp = 0; + parse_num(buf, tmp); + if (tmp < (std::numeric_limits::min)() || + tmp > (std::numeric_limits::max)()) + { + throw soci_error("Cannot convert data."); + } + exchange_type_cast(data_) = static_cast(tmp); + } + break; + case x_int16: + parse_num(buf, exchange_type_cast(data_)); + break; + case x_uint16: + parse_num(buf, exchange_type_cast(data_)); + break; + case x_int32: + parse_num(buf, exchange_type_cast(data_)); break; - case x_integer: - parse_num(buf, exchange_type_cast(data_)); + case x_uint32: + parse_num(buf, exchange_type_cast(data_)); break; - case x_long_long: - parse_num(buf, exchange_type_cast(data_)); + case x_int64: + parse_num(buf, exchange_type_cast(data_)); break; - case x_unsigned_long_long: - parse_num(buf, exchange_type_cast(data_)); + case x_uint64: + parse_num(buf, exchange_type_cast(data_)); break; case x_double: parse_num(buf, exchange_type_cast(data_)); diff --git a/src/backends/mysql/standard-use-type.cpp b/src/backends/mysql/standard-use-type.cpp index 362958e2f..17fe5d381 100644 --- a/src/backends/mysql/standard-use-type.cpp +++ b/src/backends/mysql/standard-use-type.cpp @@ -14,6 +14,7 @@ #include "soci-exchange-cast.h" // std #include +#include #include #include #include @@ -64,38 +65,70 @@ void mysql_standard_use_type_backend::pre_use(indicator const *ind) s.c_str(), s.size()); } break; - case x_short: + case x_int8: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; - case x_integer: + case x_uint8: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); } break; - case x_long_long: + case x_int16: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d", exchange_type_cast(data_)); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; - case x_unsigned_long_long: + case x_uint16: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); + } + break; + case x_int32: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); + } + break; + case x_uint32: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); + } + break; + case x_int64: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d", + static_cast(exchange_type_cast(data_))); + } + break; + case x_uint64: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "u", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); } break; diff --git a/src/backends/mysql/statement.cpp b/src/backends/mysql/statement.cpp index cfa91a16e..cd901602d 100644 --- a/src/backends/mysql/statement.cpp +++ b/src/backends/mysql/statement.cpp @@ -402,24 +402,47 @@ int mysql_statement_backend::prepare_for_describe() } void mysql_statement_backend::describe_column(int colNum, - data_type & type, std::string & columnName) + data_type & type, db_type & dbtype, std::string & columnName) { int pos = colNum - 1; MYSQL_FIELD *field = mysql_fetch_field_direct(result_, pos); switch (field->type) { case FIELD_TYPE_CHAR: //MYSQL_TYPE_TINY: + type = dt_integer; + dbtype = field->flags & UNSIGNED_FLAG ? db_uint8 : db_int8; + break; case FIELD_TYPE_SHORT: //MYSQL_TYPE_SHORT: + type = dt_integer; + dbtype = field->flags & UNSIGNED_FLAG ? db_uint16 : db_int16; + break; case FIELD_TYPE_INT24: //MYSQL_TYPE_INT24: type = dt_integer; + dbtype = field->flags & UNSIGNED_FLAG ? db_uint32 : db_int32; break; case FIELD_TYPE_LONG: //MYSQL_TYPE_LONG: - type = field->flags & UNSIGNED_FLAG ? dt_long_long - : dt_integer; + if (field->flags & UNSIGNED_FLAG) + { + type = dt_long_long; + dbtype = db_uint32; + } + else + { + type = dt_integer; + dbtype = db_int32; + } break; case FIELD_TYPE_LONGLONG: //MYSQL_TYPE_LONGLONG: - type = field->flags & UNSIGNED_FLAG ? dt_unsigned_long_long : - dt_long_long; + if (field->flags & UNSIGNED_FLAG) + { + type = dt_unsigned_long_long; + dbtype = db_uint64; + } + else + { + type = dt_long_long; + dbtype = db_int64; + } break; case FIELD_TYPE_FLOAT: //MYSQL_TYPE_FLOAT: case FIELD_TYPE_DOUBLE: //MYSQL_TYPE_DOUBLE: @@ -430,6 +453,7 @@ void mysql_statement_backend::describe_column(int colNum, // the client is using. case 246: //MYSQL_TYPE_NEWDECIMAL: type = dt_double; + dbtype = db_double; break; case FIELD_TYPE_TIMESTAMP: //MYSQL_TYPE_TIMESTAMP: case FIELD_TYPE_DATE: //MYSQL_TYPE_DATE: @@ -438,6 +462,7 @@ void mysql_statement_backend::describe_column(int colNum, case FIELD_TYPE_YEAR: //MYSQL_TYPE_YEAR: case FIELD_TYPE_NEWDATE: //MYSQL_TYPE_NEWDATE: type = dt_date; + dbtype = db_date; break; // case MYSQL_TYPE_VARCHAR: case 245: //MYSQL_TYPE_JSON: @@ -448,6 +473,7 @@ void mysql_statement_backend::describe_column(int colNum, case FIELD_TYPE_MEDIUM_BLOB: case FIELD_TYPE_LONG_BLOB: type = dt_string; + dbtype = db_string; break; default: //std::cerr << "field->type: " << field->type << std::endl; diff --git a/src/backends/mysql/vector-into-type.cpp b/src/backends/mysql/vector-into-type.cpp index 9cc6da633..908888fed 100644 --- a/src/backends/mysql/vector-into-type.cpp +++ b/src/backends/mysql/vector-into-type.cpp @@ -12,6 +12,7 @@ #include "common.h" #include "soci/soci-platform.h" #include +#include #include using namespace soci; @@ -108,30 +109,60 @@ void mysql_vector_into_type_backend::post_fetch(bool gotData, indicator *ind) (*dest)[i].assign(buf, lengths[pos]); } break; - case x_short: + case x_int8: { - short val; + int32_t tmp = 0; + parse_num(buf, tmp); + int8_t val = static_cast(tmp); + set_invector_(data_, i, val); + } + break; + case x_uint8: + { + uint32_t tmp = 0; + parse_num(buf, tmp); + uint8_t val = static_cast(tmp); + set_invector_(data_, i, val); + } + break; + case x_int16: + { + int16_t val; + parse_num(buf, val); + set_invector_(data_, i, val); + } + break; + case x_uint16: + { + uint16_t val; + parse_num(buf, val); + set_invector_(data_, i, val); + } + break; + case x_int32: + { + int32_t val; parse_num(buf, val); set_invector_(data_, i, val); } break; - case x_integer: + case x_uint32: { - int val; + uint32_t val; parse_num(buf, val); set_invector_(data_, i, val); } break; - case x_long_long: + case x_int64: { - long long val; + int64_t val; parse_num(buf, val); set_invector_(data_, i, val); } break; - case x_unsigned_long_long: + case x_uint64: { - unsigned long long val; + uint64_t val; parse_num(buf, val); set_invector_(data_, i, val); } @@ -182,12 +213,14 @@ void mysql_vector_into_type_backend::resize(std::size_t sz) { // simple cases case x_char: resizevector_ (data_, sz); break; - case x_short: resizevector_ (data_, sz); break; - case x_integer: resizevector_ (data_, sz); break; - case x_long_long: resizevector_ (data_, sz); break; - case x_unsigned_long_long: - resizevector_(data_, sz); - break; + case x_int8: resizevector_ (data_, sz); break; + case x_uint8: resizevector_ (data_, sz); break; + case x_int16: resizevector_ (data_, sz); break; + case x_uint16: resizevector_ (data_, sz); break; + case x_int32: resizevector_ (data_, sz); break; + case x_uint32: resizevector_ (data_, sz); break; + case x_int64: resizevector_ (data_, sz); break; + case x_uint64: resizevector_ (data_, sz); break; case x_double: resizevector_ (data_, sz); break; case x_stdstring: resizevector_ (data_, sz); break; case x_stdtm: resizevector_ (data_, sz); break; @@ -204,12 +237,14 @@ std::size_t mysql_vector_into_type_backend::size() { // simple cases case x_char: sz = get_vector_size (data_); break; - case x_short: sz = get_vector_size (data_); break; - case x_integer: sz = get_vector_size (data_); break; - case x_long_long: sz = get_vector_size (data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); - break; + case x_int8: sz = get_vector_size (data_); break; + case x_uint8: sz = get_vector_size (data_); break; + case x_int16: sz = get_vector_size (data_); break; + case x_uint16: sz = get_vector_size (data_); break; + case x_int32: sz = get_vector_size (data_); break; + case x_uint32: sz = get_vector_size (data_); break; + case x_int64: sz = get_vector_size (data_); break; + case x_uint64: sz = get_vector_size (data_); break; case x_double: sz = get_vector_size (data_); break; case x_stdstring: sz = get_vector_size (data_); break; case x_stdtm: sz = get_vector_size (data_); break; diff --git a/src/backends/mysql/vector-use-type.cpp b/src/backends/mysql/vector-use-type.cpp index 67a5e1906..456f2a9b2 100644 --- a/src/backends/mysql/vector-use-type.cpp +++ b/src/backends/mysql/vector-use-type.cpp @@ -14,6 +14,7 @@ // std #include #include +#include #include #include #include @@ -81,52 +82,102 @@ void mysql_vector_use_type_backend::pre_use(indicator const *ind) v[i].c_str(), v[i].size()); } break; - case x_short: + case x_int8: { - std::vector *pv - = static_cast *>(data_); - std::vector &v = *pv; + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", static_cast(v[i])); + snprintf(buf, bufSize, "%d", v[i]); + } + break; + case x_uint8: + { + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%u", v[i]); + } + break; + case x_int16: + { + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%d", v[i]); + } + break; + case x_uint16: + { + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%u", v[i]); } break; - case x_integer: + case x_int32: { - std::vector *pv - = static_cast *>(data_); - std::vector &v = *pv; + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; snprintf(buf, bufSize, "%d", v[i]); } break; - case x_long_long: + case x_uint32: + { + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%u", v[i]); + } + break; + case x_int64: { - std::vector *pv - = static_cast *>(data_); - std::vector &v = *pv; + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%" LL_FMT_FLAGS "d", v[i]); + snprintf(buf, bufSize, "%" LL_FMT_FLAGS "d", + static_cast(v[i])); } break; - case x_unsigned_long_long: + case x_uint64: { - std::vector *pv - = static_cast *>(data_); - std::vector &v = *pv; + std::vector *pv + = static_cast *>(data_); + std::vector &v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%" LL_FMT_FLAGS "u", v[i]); + snprintf(buf, bufSize, "%" LL_FMT_FLAGS "u", + static_cast(v[i])); } break; case x_double: @@ -190,12 +241,14 @@ std::size_t mysql_vector_use_type_backend::size() { // simple cases case x_char: sz = get_vector_size (data_); break; - case x_short: sz = get_vector_size (data_); break; - case x_integer: sz = get_vector_size (data_); break; - case x_long_long: sz = get_vector_size (data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); - break; + case x_int8: sz = get_vector_size (data_); break; + case x_uint8: sz = get_vector_size (data_); break; + case x_int16: sz = get_vector_size (data_); break; + case x_uint16: sz = get_vector_size (data_); break; + case x_int32: sz = get_vector_size (data_); break; + case x_uint32: sz = get_vector_size (data_); break; + case x_int64: sz = get_vector_size (data_); break; + case x_uint64: sz = get_vector_size (data_); break; case x_double: sz = get_vector_size (data_); break; case x_stdstring: sz = get_vector_size (data_); break; case x_stdtm: sz = get_vector_size (data_); break; diff --git a/src/backends/odbc/standard-into-type.cpp b/src/backends/odbc/standard-into-type.cpp index 26a4b41be..37c028a3f 100644 --- a/src/backends/odbc/standard-into-type.cpp +++ b/src/backends/odbc/standard-into-type.cpp @@ -12,6 +12,7 @@ #include "soci-cstrtoi.h" #include "soci-exchange-cast.h" #include "soci-mktime.h" +#include #include using namespace soci; @@ -49,15 +50,31 @@ void odbc_standard_into_type_backend::define_by_pos( buf_ = new char[size]; data = buf_; break; - case x_short: + case x_int8: + odbcType_ = SQL_C_STINYINT; + size = sizeof(int8_t); + break; + case x_uint8: + odbcType_ = SQL_C_UTINYINT; + size = sizeof(uint8_t); + break; + case x_int16: odbcType_ = SQL_C_SSHORT; - size = sizeof(short); + size = sizeof(int16_t); + break; + case x_uint16: + odbcType_ = SQL_C_USHORT; + size = sizeof(uint16_t); break; - case x_integer: + case x_int32: odbcType_ = SQL_C_SLONG; - size = sizeof(int); + size = sizeof(int32_t); + break; + case x_uint32: + odbcType_ = SQL_C_ULONG; + size = sizeof(uint32_t); break; - case x_long_long: + case x_int64: if (use_string_for_bigint()) { odbcType_ = SQL_C_CHAR; @@ -68,10 +85,10 @@ void odbc_standard_into_type_backend::define_by_pos( else // Normal case, use ODBC support. { odbcType_ = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); } break; - case x_unsigned_long_long: + case x_uint64: if (use_string_for_bigint()) { odbcType_ = SQL_C_CHAR; @@ -82,7 +99,7 @@ void odbc_standard_into_type_backend::define_by_pos( else // Normal case, use ODBC support. { odbcType_ = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(uint64_t); } break; case x_double: @@ -191,17 +208,17 @@ void odbc_standard_into_type_backend::post_fetch( ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second); } - else if (type_ == x_long_long && use_string_for_bigint()) + else if (type_ == x_int64 && use_string_for_bigint()) { - long long& ll = exchange_type_cast(data_); + int64_t ll = exchange_type_cast(data_); if (!cstring_to_integer(ll, buf_)) { throw soci_error("Failed to parse the returned 64-bit integer value"); } } - else if (type_ == x_unsigned_long_long && use_string_for_bigint()) + else if (type_ == x_uint64 && use_string_for_bigint()) { - unsigned long long& ll = exchange_type_cast(data_); + uint64_t ll = exchange_type_cast(data_); if (!cstring_to_unsigned(ll, buf_)) { throw soci_error("Failed to parse the returned 64-bit integer value"); diff --git a/src/backends/odbc/standard-use-type.cpp b/src/backends/odbc/standard-use-type.cpp index 60ec149e7..12c573cd7 100644 --- a/src/backends/odbc/standard-use-type.cpp +++ b/src/backends/odbc/standard-use-type.cpp @@ -9,6 +9,7 @@ #include "soci-compiler.h" #include "soci-exchange-cast.h" #include +#include #include #include #include @@ -23,17 +24,37 @@ void* odbc_standard_use_type_backend::prepare_for_bind( switch (type_) { // simple cases - case x_short: + case x_int8: + sqlType = supports_negative_tinyint() ? SQL_TINYINT : SQL_SMALLINT; + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + break; + case x_uint8: + sqlType = can_convert_to_unsigned_sql_type() ? SQL_TINYINT : SQL_SMALLINT; + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + break; + case x_int16: sqlType = SQL_SMALLINT; cType = SQL_C_SSHORT; - size = sizeof(short); + size = sizeof(int16_t); + break; + case x_uint16: + sqlType = can_convert_to_unsigned_sql_type() ? SQL_SMALLINT : SQL_INTEGER; + cType = SQL_C_USHORT; + size = sizeof(uint16_t); break; - case x_integer: + case x_int32: sqlType = SQL_INTEGER; cType = SQL_C_SLONG; - size = sizeof(int); + size = sizeof(int32_t); break; - case x_long_long: + case x_uint32: + sqlType = can_convert_to_unsigned_sql_type() ? SQL_INTEGER : SQL_BIGINT; + cType = SQL_C_ULONG; + size = sizeof(uint32_t); + break; + case x_int64: if (use_string_for_bigint()) { sqlType = SQL_NUMERIC; @@ -41,32 +62,32 @@ void* odbc_standard_use_type_backend::prepare_for_bind( size = max_bigint_length; buf_ = new char[size]; snprintf(buf_, size, "%" LL_FMT_FLAGS "d", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); indHolder_ = SQL_NTS; } else // Normal case, use ODBC support. { sqlType = SQL_BIGINT; cType = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); } break; - case x_unsigned_long_long: - if (use_string_for_bigint()) + case x_uint64: + if (use_string_for_bigint() || !can_convert_to_unsigned_sql_type()) { sqlType = SQL_NUMERIC; cType = SQL_C_CHAR; size = max_bigint_length; buf_ = new char[size]; snprintf(buf_, size, "%" LL_FMT_FLAGS "u", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); indHolder_ = SQL_NTS; } - else // Normal case, use ODBC support. + else { sqlType = SQL_BIGINT; cType = SQL_C_UBIGINT; - size = sizeof(unsigned long long); + size = sizeof(uint64_t); } break; case x_double: diff --git a/src/backends/odbc/statement.cpp b/src/backends/odbc/statement.cpp index 54711a5ed..816953f1a 100644 --- a/src/backends/odbc/statement.cpp +++ b/src/backends/odbc/statement.cpp @@ -328,6 +328,7 @@ int odbc_statement_backend::prepare_for_describe() } void odbc_statement_backend::describe_column(int colNum, data_type & type, + db_type & dbtype, std::string & columnName) { SQLCHAR colNameBuffer[2048]; @@ -352,12 +353,24 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, char const *name = reinterpret_cast(colNameBuffer); columnName.assign(name, std::strlen(name)); + SQLLEN is_unsigned = 0; + SQLRETURN rc_colattr = SQLColAttribute(hstmt_, static_cast(colNum), + SQL_DESC_UNSIGNED, 0, 0, 0, &is_unsigned); + + if (is_odbc_error(rc_colattr)) + { + std::ostringstream ss; + ss << "getting \"unsigned\" column attribute of the column at position " << colNum; + throw odbc_soci_error(SQL_HANDLE_STMT, hstmt_, ss.str()); + } + switch (dataType) { case SQL_TYPE_DATE: case SQL_TYPE_TIME: case SQL_TYPE_TIMESTAMP: type = dt_date; + dbtype = db_date; break; case SQL_DOUBLE: case SQL_DECIMAL: @@ -365,20 +378,30 @@ void odbc_statement_backend::describe_column(int colNum, data_type & type, case SQL_FLOAT: case SQL_NUMERIC: type = dt_double; + dbtype = db_double; break; case SQL_TINYINT: + type = dt_integer; + dbtype = is_unsigned == SQL_TRUE ? db_uint8 : db_int8; + break; case SQL_SMALLINT: + type = dt_integer; + dbtype = is_unsigned == SQL_TRUE ? db_uint16 : db_int16; + break; case SQL_INTEGER: type = dt_integer; + dbtype = is_unsigned == SQL_TRUE ? db_uint32 : db_int32; break; case SQL_BIGINT: type = dt_long_long; + dbtype = is_unsigned == SQL_TRUE ? db_uint64 : db_int64; break; case SQL_CHAR: case SQL_VARCHAR: case SQL_LONGVARCHAR: default: type = dt_string; + dbtype = db_string; break; } } diff --git a/src/backends/odbc/vector-into-type.cpp b/src/backends/odbc/vector-into-type.cpp index 84863542a..3e864d9be 100644 --- a/src/backends/odbc/vector-into-type.cpp +++ b/src/backends/odbc/vector-into-type.cpp @@ -15,6 +15,7 @@ #include "soci-vector-helpers.h" #include #include +#include #include #include #include @@ -43,14 +44,26 @@ void odbc_vector_into_type_backend::define_by_pos( switch (type) { // simple cases - case x_short: + case x_int8: + odbcType_ = SQL_C_STINYINT; + break; + case x_uint8: + odbcType_ = SQL_C_UTINYINT; + break; + case x_int16: odbcType_ = SQL_C_SSHORT; break; - case x_integer: + case x_uint16: + odbcType_ = SQL_C_USHORT; + break; + case x_int32: odbcType_ = SQL_C_SLONG; - static_assert(sizeof(SQLINTEGER) == sizeof(int), "unsupported SQLINTEGER size"); + static_assert(sizeof(SQLINTEGER) == sizeof(int32_t), "unsupported SQLINTEGER size"); break; - case x_long_long: + case x_uint32: + odbcType_ = SQL_C_ULONG; + break; + case x_int64: if (use_string_for_bigint()) { odbcType_ = SQL_C_CHAR; @@ -62,7 +75,7 @@ void odbc_vector_into_type_backend::define_by_pos( odbcType_ = SQL_C_SBIGINT; } break; - case x_unsigned_long_long: + case x_uint64: if (use_string_for_bigint()) { odbcType_ = SQL_C_CHAR; @@ -136,26 +149,42 @@ void odbc_vector_into_type_backend::rebind_row(std::size_t rowInd) switch (type_) { // simple cases - case x_short: - elementPtr = &exchange_vector_type_cast(data_)[rowInd]; - size = sizeof(short); + case x_int8: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(int8_t); + break; + case x_uint8: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(uint8_t); + break; + case x_int16: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(int16_t); + break; + case x_uint16: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(uint16_t); + break; + case x_int32: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(SQLINTEGER); break; - case x_integer: - elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + case x_uint32: + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; size = sizeof(SQLINTEGER); break; - case x_long_long: + case x_int64: if (!use_string_for_bigint()) { - elementPtr = &exchange_vector_type_cast(data_)[rowInd]; - size = sizeof(long long); + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(int64_t); } break; - case x_unsigned_long_long: + case x_uint64: if (!use_string_for_bigint()) { - elementPtr = &exchange_vector_type_cast(data_)[rowInd]; - size = sizeof(unsigned long long); + elementPtr = &exchange_vector_type_cast(data_)[rowInd]; + size = sizeof(uint64_t); } break; case x_double: @@ -280,11 +309,11 @@ void odbc_vector_into_type_backend::do_post_fetch_rows( pos += colSize_; } } - else if (type_ == x_long_long && use_string_for_bigint()) + else if (type_ == x_int64 && use_string_for_bigint()) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; for (std::size_t i = beginRow; i != endRow; ++i) { @@ -295,11 +324,11 @@ void odbc_vector_into_type_backend::do_post_fetch_rows( pos += colSize_; } } - else if (type_ == x_unsigned_long_long && use_string_for_bigint()) + else if (type_ == x_uint64 && use_string_for_bigint()) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; for (std::size_t i = beginRow; i != endRow; ++i) { diff --git a/src/backends/odbc/vector-use-type.cpp b/src/backends/odbc/vector-use-type.cpp index 90ab74e54..b6dfa6250 100644 --- a/src/backends/odbc/vector-use-type.cpp +++ b/src/backends/odbc/vector-use-type.cpp @@ -11,6 +11,7 @@ #include "soci-compiler.h" #include "soci-vector-helpers.h" #include +#include #include #include #include @@ -42,34 +43,78 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, void* data = NULL; switch (type_) { // simple cases - case x_short: + case x_int8: + { + sqlType = supports_negative_tinyint() ? SQL_TINYINT : SQL_SMALLINT; + cType = SQL_C_STINYINT; + size = sizeof(int8_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint8: + { + sqlType = can_convert_to_unsigned_sql_type() ? SQL_TINYINT : SQL_SMALLINT; + cType = SQL_C_UTINYINT; + size = sizeof(uint8_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_int16: { sqlType = SQL_SMALLINT; cType = SQL_C_SSHORT; - size = sizeof(short); - std::vector *vp = static_cast *>(data_); - std::vector &v(*vp); + size = sizeof(int16_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } break; - case x_integer: + case x_uint16: + { + sqlType = can_convert_to_unsigned_sql_type() ? SQL_SMALLINT : SQL_INTEGER; + cType = SQL_C_USHORT; + size = sizeof(uint16_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_int32: { sqlType = SQL_INTEGER; cType = SQL_C_SLONG; size = sizeof(SQLINTEGER); - static_assert(sizeof(SQLINTEGER) == sizeof(int), "unsupported SQLINTEGER size"); - std::vector *vp = static_cast *>(data_); - std::vector &v(*vp); + static_assert(sizeof(SQLINTEGER) == sizeof(int32_t), "unsupported SQLINTEGER size"); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(v.size()); + data = &v[0]; + } + break; + case x_uint32: + { + sqlType = can_convert_to_unsigned_sql_type() ? SQL_INTEGER : SQL_BIGINT; + cType = SQL_C_ULONG; + size = sizeof(SQLINTEGER); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); prepare_indicators(v.size()); data = &v[0]; } break; - case x_long_long: + case x_int64: { - std::vector *vp = - static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp = + static_cast *>(data_); + std::vector &v(*vp); std::size_t const vsize = v.size(); prepare_indicators(vsize); @@ -85,20 +130,20 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, { sqlType = SQL_BIGINT; cType = SQL_C_SBIGINT; - size = sizeof(long long); + size = sizeof(int64_t); data = &v[0]; } } break; - case x_unsigned_long_long: + case x_uint64: { - std::vector *vp = - static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp = + static_cast *>(data_); + std::vector &v(*vp); std::size_t const vsize = v.size(); prepare_indicators(vsize); - if (use_string_for_bigint()) + if (use_string_for_bigint() || !can_convert_to_unsigned_sql_type()) { sqlType = SQL_NUMERIC; cType = SQL_C_CHAR; @@ -106,11 +151,11 @@ void* odbc_vector_use_type_backend::prepare_for_bind(SQLUINTEGER &size, buf_ = new char[size * vsize]; data = buf_; } - else // Normal case, use ODBC support. + else // Normal case, use ODBC support { sqlType = SQL_BIGINT; - cType = SQL_C_SBIGINT; - size = sizeof(unsigned long long); + cType = SQL_C_UBIGINT; + size = sizeof(uint64_t); data = &v[0]; } } @@ -282,8 +327,12 @@ void odbc_vector_use_type_backend::pre_use(indicator const *ind) SQLLEN non_null_indicator = 0; switch (type_) { - case x_short: - case x_integer: + case x_int8: + case x_uint8: + case x_int16: + case x_uint16: + case x_int32: + case x_uint32: case x_double: // Length of the parameter value is ignored for these types. break; @@ -327,18 +376,19 @@ void odbc_vector_use_type_backend::pre_use(indicator const *ind) } break; - case x_long_long: + case x_int64: if (use_string_for_bigint()) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; std::size_t const vsize = v.size(); for (std::size_t i = 0; i != vsize; ++i) { - snprintf(pos, max_bigint_length, "%" LL_FMT_FLAGS "d", v[i]); + snprintf(pos, max_bigint_length, "%" LL_FMT_FLAGS "d", + static_cast(v[i])); pos += max_bigint_length; } @@ -346,18 +396,19 @@ void odbc_vector_use_type_backend::pre_use(indicator const *ind) } break; - case x_unsigned_long_long: - if (use_string_for_bigint()) + case x_uint64: + if (use_string_for_bigint() || !can_convert_to_unsigned_sql_type()) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; std::size_t const vsize = v.size(); for (std::size_t i = 0; i != vsize; ++i) { - snprintf(pos, max_bigint_length, "%" LL_FMT_FLAGS "u", v[i]); + snprintf(pos, max_bigint_length, "%" LL_FMT_FLAGS "u", + static_cast(v[i])); pos += max_bigint_length; } diff --git a/src/backends/oracle/standard-into-type.cpp b/src/backends/oracle/standard-into-type.cpp index 8fa9750a2..01292313b 100644 --- a/src/backends/oracle/standard-into-type.cpp +++ b/src/backends/oracle/standard-into-type.cpp @@ -16,6 +16,7 @@ #include "soci-exchange-cast.h" #include "soci-mktime.h" #include +#include #include #include #include @@ -70,13 +71,29 @@ void oracle_standard_into_type_backend::define_by_pos( oracleType = SQLT_AFC; size = sizeof(char); break; - case x_short: + case x_int8: oracleType = SQLT_INT; - size = sizeof(short); + size = sizeof(int8_t); break; - case x_integer: + case x_uint8: + oracleType = SQLT_UIN; + size = sizeof(uint8_t); + break; + case x_int16: oracleType = SQLT_INT; - size = sizeof(int); + size = sizeof(int16_t); + break; + case x_uint16: + oracleType = SQLT_UIN; + size = sizeof(uint16_t); + break; + case x_int32: + oracleType = SQLT_INT; + size = sizeof(int32_t); + break; + case x_uint32: + oracleType = SQLT_UIN; + size = sizeof(uint32_t); break; case x_double: oracleType = statement_.session_.get_double_sql_type(); @@ -84,8 +101,8 @@ void oracle_standard_into_type_backend::define_by_pos( break; // cases that require adjustments and buffer management - case x_long_long: - case x_unsigned_long_long: + case x_int64: + case x_uint64: oracleType = SQLT_STR; size = 100; // arbitrary buffer length buf_ = new char[size]; @@ -248,18 +265,18 @@ void oracle_standard_into_type_backend::post_fetch( exchange_type_cast(data_) = buf_; } } - else if (type_ == x_long_long) + else if (type_ == x_int64) { if (indOCIHolder_ != -1) { - exchange_type_cast(data_) = std::strtoll(buf_, NULL, 10); + exchange_type_cast(data_) = std::strtoll(buf_, NULL, 10); } } - else if (type_ == x_unsigned_long_long) + else if (type_ == x_uint64) { if (indOCIHolder_ != -1) { - exchange_type_cast(data_) = std::strtoull(buf_, NULL, 10); + exchange_type_cast(data_) = std::strtoull(buf_, NULL, 10); } } else if (type_ == x_stdtm) diff --git a/src/backends/oracle/standard-use-type.cpp b/src/backends/oracle/standard-use-type.cpp index b25d6531c..0aac00e10 100644 --- a/src/backends/oracle/standard-use-type.cpp +++ b/src/backends/oracle/standard-use-type.cpp @@ -20,6 +20,7 @@ #include "soci-mktime.h" #include +#include #include #include #include @@ -52,18 +53,54 @@ void oracle_standard_use_type_backend::prepare_for_bind( data = buf_; } break; - case x_short: + case x_int8: oracleType = SQLT_INT; - size = sizeof(short); + size = sizeof(int8_t); if (readOnly) { buf_ = new char[size]; data = buf_; } break; - case x_integer: + case x_uint8: + oracleType = SQLT_UIN; + size = sizeof(uint8_t); + if (readOnly) + { + buf_ = new char[size]; + data = buf_; + } + break; + case x_int16: + oracleType = SQLT_INT; + size = sizeof(int16_t); + if (readOnly) + { + buf_ = new char[size]; + data = buf_; + } + break; + case x_uint16: + oracleType = SQLT_UIN; + size = sizeof(uint16_t); + if (readOnly) + { + buf_ = new char[size]; + data = buf_; + } + break; + case x_int32: oracleType = SQLT_INT; - size = sizeof(int); + size = sizeof(int32_t); + if (readOnly) + { + buf_ = new char[size]; + data = buf_; + } + break; + case x_uint32: + oracleType = SQLT_UIN; + size = sizeof(uint32_t); if (readOnly) { buf_ = new char[size]; @@ -81,8 +118,8 @@ void oracle_standard_use_type_backend::prepare_for_bind( break; // cases that require adjustments and buffer management - case x_long_long: - case x_unsigned_long_long: + case x_int64: + case x_uint64: oracleType = SQLT_STR; size = 100; // arbitrary buffer length buf_ = new char[size]; @@ -333,28 +370,54 @@ void oracle_standard_use_type_backend::pre_use(indicator const *ind) buf_[0] = exchange_type_cast(data_); } break; - case x_short: + case x_int8: if (readOnly_) { - exchange_type_cast(buf_) = exchange_type_cast(data_); + exchange_type_cast(buf_) = exchange_type_cast(data_); } break; - case x_integer: + case x_uint8: if (readOnly_) { - exchange_type_cast(buf_) = exchange_type_cast(data_); + exchange_type_cast(buf_) = exchange_type_cast(data_); } break; - case x_long_long: + case x_int16: + if (readOnly_) + { + exchange_type_cast(buf_) = exchange_type_cast(data_); + } + break; + case x_uint16: + if (readOnly_) + { + exchange_type_cast(buf_) = exchange_type_cast(data_); + } + break; + case x_int32: + if (readOnly_) + { + exchange_type_cast(buf_) = exchange_type_cast(data_); + } + break; + case x_uint32: + if (readOnly_) + { + exchange_type_cast(buf_) = exchange_type_cast(data_); + } + break; + case x_int64: { size_t const size = 100; // arbitrary, but consistent with prepare_for_bind - snprintf(buf_, size, "%" LL_FMT_FLAGS "d", exchange_type_cast(data_)); + snprintf(buf_, size, "%" LL_FMT_FLAGS "d", + static_cast(exchange_type_cast(data_))); } break; - case x_unsigned_long_long: + case x_uint64: { size_t const size = 100; // arbitrary, but consistent with prepare_for_bind - snprintf(buf_, size, "%" LL_FMT_FLAGS "u", exchange_type_cast(data_)); + snprintf(buf_, size, "%" LL_FMT_FLAGS "u", + static_cast(exchange_type_cast(data_))); } break; case x_double: @@ -442,11 +505,59 @@ void oracle_standard_use_type_backend::post_use(bool gotData, indicator *ind) } } break; - case x_short: + case x_int8: + if (readOnly_) + { + const int8_t original = exchange_type_cast(data_); + const int8_t bound = exchange_type_cast(buf_); + + if (original != bound) + { + throw soci_error("Attempted modification of const use element"); + } + } + break; + case x_uint8: + if (readOnly_) + { + const uint8_t original = exchange_type_cast(data_); + const uint8_t bound = exchange_type_cast(buf_); + + if (original != bound) + { + throw soci_error("Attempted modification of const use element"); + } + } + break; + case x_int16: + if (readOnly_) + { + const int16_t original = exchange_type_cast(data_); + const int16_t bound = exchange_type_cast(buf_); + + if (original != bound) + { + throw soci_error("Attempted modification of const use element"); + } + } + break; + case x_uint16: + if (readOnly_) + { + const uint16_t original = exchange_type_cast(data_); + const uint16_t bound = exchange_type_cast(buf_); + + if (original != bound) + { + throw soci_error("Attempted modification of const use element"); + } + } + break; + case x_int32: if (readOnly_) { - const short original = exchange_type_cast(data_); - const short bound = exchange_type_cast(buf_); + const int32_t original = exchange_type_cast(data_); + const int32_t bound = exchange_type_cast(buf_); if (original != bound) { @@ -454,11 +565,11 @@ void oracle_standard_use_type_backend::post_use(bool gotData, indicator *ind) } } break; - case x_integer: + case x_uint32: if (readOnly_) { - const int original = exchange_type_cast(data_); - const int bound = exchange_type_cast(buf_); + const uint32_t original = exchange_type_cast(data_); + const uint32_t bound = exchange_type_cast(buf_); if (original != bound) { @@ -466,11 +577,11 @@ void oracle_standard_use_type_backend::post_use(bool gotData, indicator *ind) } } break; - case x_long_long: + case x_int64: if (readOnly_) { - long long const original = exchange_type_cast(data_); - long long const bound = std::strtoll(buf_, NULL, 10); + int64_t const original = exchange_type_cast(data_); + int64_t const bound = std::strtoll(buf_, NULL, 10); if (original != bound) { @@ -478,11 +589,11 @@ void oracle_standard_use_type_backend::post_use(bool gotData, indicator *ind) } } break; - case x_unsigned_long_long: + case x_uint64: if (readOnly_) { - unsigned long long const original = exchange_type_cast(data_); - unsigned long long const bound = std::strtoull(buf_, NULL, 10); + uint64_t const original = exchange_type_cast(data_); + uint64_t const bound = std::strtoull(buf_, NULL, 10); if (original != bound) { diff --git a/src/backends/oracle/statement.cpp b/src/backends/oracle/statement.cpp index b0a4815cf..4a506bc71 100644 --- a/src/backends/oracle/statement.cpp +++ b/src/backends/oracle/statement.cpp @@ -185,6 +185,7 @@ int oracle_statement_backend::prepare_for_describe() } void oracle_statement_backend::describe_column(int colNum, data_type &type, + db_type &xdbtype, std::string &columnName) { ub2 dbtype; @@ -286,6 +287,7 @@ void oracle_statement_backend::describe_column(int colNum, data_type &type, case SQLT_CHR: case SQLT_AFC: type = dt_string; + xdbtype = db_string; break; case SQLT_NUM: if (dbscale > 0) @@ -293,30 +295,37 @@ void oracle_statement_backend::describe_column(int colNum, data_type &type, if (session_.get_option_decimals_as_strings()) { type = dt_string; + xdbtype = db_string; } else { type = dt_double; + xdbtype = db_double; } } - else if (dbprec <= std::numeric_limits::digits10) + else if (dbprec <= std::numeric_limits::digits10) { type = dt_integer; + xdbtype = db_int32; } else { type = dt_long_long; + xdbtype = db_int64; } break; case OCI_TYPECODE_BDOUBLE: type = dt_double; + xdbtype = db_double; break; case SQLT_DAT: type = dt_date; + xdbtype = db_date; break; default: // Unknown oracle types will just be represented by a string type = dt_string; + xdbtype = db_string; } } diff --git a/src/backends/oracle/vector-into-type.cpp b/src/backends/oracle/vector-into-type.cpp index 23ddc52f8..d838b6849 100644 --- a/src/backends/oracle/vector-into-type.cpp +++ b/src/backends/oracle/vector-into-type.cpp @@ -14,6 +14,7 @@ #include "soci-mktime.h" #include "soci-vector-helpers.h" #include +#include #include #include #include @@ -69,22 +70,62 @@ void oracle_vector_into_type_backend::define_by_pos_bulk( dataBuf = &v[begin_]; } break; - case x_short: + case x_int8: { oracleType = SQLT_INT; - elementSize = sizeof(short); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + elementSize = sizeof(int8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(size()); dataBuf = &v[begin_]; } break; - case x_integer: + case x_uint8: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint8_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(size()); + dataBuf = &v[begin_]; + } + break; + case x_int16: { oracleType = SQLT_INT; - elementSize = sizeof(int); - std::vector *vp = static_cast *>(data); - std::vector &v(*vp); + elementSize = sizeof(int16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(size()); + dataBuf = &v[begin_]; + } + break; + case x_uint16: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint16_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(size()); + dataBuf = &v[begin_]; + } + break; + case x_int32: + { + oracleType = SQLT_INT; + elementSize = sizeof(int32_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); + prepare_indicators(size()); + dataBuf = &v[begin_]; + } + break; + case x_uint32: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint32_t); + std::vector *vp = static_cast *>(data); + std::vector &v(*vp); prepare_indicators(size()); dataBuf = &v[begin_]; } @@ -102,7 +143,7 @@ void oracle_vector_into_type_backend::define_by_pos_bulk( // cases that require adjustments and buffer management - case x_long_long: + case x_int64: { oracleType = SQLT_STR; const std::size_t vecSize = size(); @@ -116,7 +157,7 @@ void oracle_vector_into_type_backend::define_by_pos_bulk( dataBuf = buf_; } break; - case x_unsigned_long_long: + case x_uint64: { oracleType = SQLT_STR; const std::size_t vecSize = size(); @@ -216,7 +257,7 @@ void oracle_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) { // first, deal with data - // only std::string, std::tm, long long and Statement need special handling + // only std::string, std::tm, int64 and Statement need special handling if (type_ == x_stdstring) { std::vector *vp @@ -235,12 +276,12 @@ void oracle_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) pos += colSize_; } } - else if (type_ == x_long_long) + else if (type_ == x_int64) { - std::vector *vp - = static_cast *>(data_); + std::vector *vp + = static_cast *>(data_); - std::vector &v(*vp); + std::vector &v(*vp); char *pos = buf_; std::size_t const vecSize = size(); @@ -253,12 +294,12 @@ void oracle_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) pos += colSize_; } } - else if (type_ == x_unsigned_long_long) + else if (type_ == x_uint64) { - std::vector *vp - = static_cast *>(data_); + std::vector *vp + = static_cast *>(data_); - std::vector &v(*vp); + std::vector &v(*vp); char *pos = buf_; std::size_t const vecSize = size(); diff --git a/src/backends/oracle/vector-use-type.cpp b/src/backends/oracle/vector-use-type.cpp index b13eec2b6..11fda2e11 100644 --- a/src/backends/oracle/vector-use-type.cpp +++ b/src/backends/oracle/vector-use-type.cpp @@ -12,6 +12,7 @@ #include "soci/soci-platform.h" #include "soci-vector-helpers.h" #include +#include #include #include #include @@ -52,22 +53,62 @@ void oracle_vector_use_type_backend::prepare_for_bind( data = &v[begin_]; } break; - case x_short: + case x_int8: { oracleType = SQLT_INT; - elementSize = sizeof(short); - std::vector *vp = static_cast *>(data_); - std::vector &v(*vp); + elementSize = sizeof(int8_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); prepare_indicators(size()); data = &v[begin_]; } break; - case x_integer: + case x_uint8: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint8_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(size()); + data = &v[begin_]; + } + break; + case x_int16: { oracleType = SQLT_INT; - elementSize = sizeof(int); - std::vector *vp = static_cast *>(data_); - std::vector &v(*vp); + elementSize = sizeof(int16_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(size()); + data = &v[begin_]; + } + break; + case x_uint16: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint16_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(size()); + data = &v[begin_]; + } + break; + case x_int32: + { + oracleType = SQLT_INT; + elementSize = sizeof(int32_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); + prepare_indicators(size()); + data = &v[begin_]; + } + break; + case x_uint32: + { + oracleType = SQLT_UIN; + elementSize = sizeof(uint32_t); + std::vector *vp = static_cast *>(data_); + std::vector &v(*vp); prepare_indicators(size()); data = &v[begin_]; } @@ -85,7 +126,7 @@ void oracle_vector_use_type_backend::prepare_for_bind( // cases that require adjustments and buffer management - case x_long_long: + case x_int64: { std::size_t const vecSize = size(); std::size_t const entrySize = 100; // arbitrary @@ -99,7 +140,7 @@ void oracle_vector_use_type_backend::prepare_for_bind( prepare_indicators(vecSize); } break; - case x_unsigned_long_long: + case x_uint64: { std::size_t const vecSize = size(); std::size_t const entrySize = 100; // arbitrary @@ -225,33 +266,35 @@ void oracle_vector_use_type_backend::pre_use(indicator const *ind) { // nothing to do - already done in prepare_for_bind() } - else if (type_ == x_long_long) + else if (type_ == x_int64) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; std::size_t const entrySize = 100; // arbitrary, but consistent std::size_t const vecSize = size(); for (std::size_t i = 0; i != vecSize; ++i) { - snprintf(pos, entrySize, "%" LL_FMT_FLAGS "d", v[begin_ + i]); + snprintf(pos, entrySize, "%" LL_FMT_FLAGS "d", + static_cast(v[begin_ + i])); pos += entrySize; } } - else if (type_ == x_unsigned_long_long) + else if (type_ == x_uint64) { - std::vector *vp - = static_cast *>(data_); - std::vector &v(*vp); + std::vector *vp + = static_cast *>(data_); + std::vector &v(*vp); char *pos = buf_; std::size_t const entrySize = 100; // arbitrary, but consistent std::size_t const vecSize = size(); for (std::size_t i = 0; i != vecSize; ++i) { - snprintf(pos, entrySize, "%" LL_FMT_FLAGS "u", v[begin_ + i]); + snprintf(pos, entrySize, "%" LL_FMT_FLAGS "u", + static_cast(v[begin_ + i])); pos += entrySize; } } diff --git a/src/backends/postgresql/standard-into-type.cpp b/src/backends/postgresql/standard-into-type.cpp index b21cfbb57..023b1dda1 100644 --- a/src/backends/postgresql/standard-into-type.cpp +++ b/src/backends/postgresql/standard-into-type.cpp @@ -17,6 +17,7 @@ #include "soci-exchange-cast.h" #include // libpq #include +#include #include #include #include @@ -90,17 +91,29 @@ void postgresql_standard_into_type_backend::post_fetch( case x_stdstring: exchange_type_cast(data_) = buf; break; - case x_short: - exchange_type_cast(data_) = string_to_integer(buf); + case x_int8: + exchange_type_cast(data_) = string_to_integer(buf); break; - case x_integer: - exchange_type_cast(data_) = string_to_integer(buf); + case x_uint8: + exchange_type_cast(data_) = string_to_integer(buf); break; - case x_long_long: - exchange_type_cast(data_) = string_to_integer(buf); + case x_int16: + exchange_type_cast(data_) = string_to_integer(buf); break; - case x_unsigned_long_long: - exchange_type_cast(data_) = string_to_unsigned_integer(buf); + case x_uint16: + exchange_type_cast(data_) = string_to_integer(buf); + break; + case x_int32: + exchange_type_cast(data_) = string_to_integer(buf); + break; + case x_uint32: + exchange_type_cast(data_) = string_to_integer(buf); + break; + case x_int64: + exchange_type_cast(data_) = string_to_integer(buf); + break; + case x_uint64: + exchange_type_cast(data_) = string_to_unsigned_integer(buf); break; case x_double: exchange_type_cast(data_) = cstring_to_double(buf); diff --git a/src/backends/postgresql/standard-use-type.cpp b/src/backends/postgresql/standard-use-type.cpp index c032fec95..9cff41eee 100644 --- a/src/backends/postgresql/standard-use-type.cpp +++ b/src/backends/postgresql/standard-use-type.cpp @@ -15,6 +15,7 @@ #include "soci-exchange-cast.h" #include // libpq #include +#include #include #include #include @@ -67,40 +68,70 @@ void postgresql_standard_use_type_backend::pre_use(indicator const * ind) case x_stdstring: copy_from_string(exchange_type_cast(data_)); break; - case x_short: + case x_int8: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - static_cast(exchange_type_cast(data_))); + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); } break; - case x_integer: + case x_uint8: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; - snprintf(buf_, bufSize, "%d", - exchange_type_cast(data_)); + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); } break; - case x_long_long: + case x_int16: { std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); + } + break; + case x_uint16: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); + } + break; + case x_int32: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%d", exchange_type_cast(data_)); + } + break; + case x_uint32: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf_ = new char[bufSize]; + snprintf(buf_, bufSize, "%u", exchange_type_cast(data_)); + } + break; + case x_int64: + { + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "d", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); } break; - case x_unsigned_long_long: + case x_uint64: { std::size_t const bufSize - = std::numeric_limits::digits10 + 2; + = std::numeric_limits::digits10 + 2; buf_ = new char[bufSize]; snprintf(buf_, bufSize, "%" LL_FMT_FLAGS "u", - exchange_type_cast(data_)); + static_cast(exchange_type_cast(data_))); } break; case x_double: diff --git a/src/backends/postgresql/statement.cpp b/src/backends/postgresql/statement.cpp index a3b20339c..388661094 100644 --- a/src/backends/postgresql/statement.cpp +++ b/src/backends/postgresql/statement.cpp @@ -741,7 +741,7 @@ void throw_soci_type_error(Oid typeOid, int colNum, char category, const char* t } void postgresql_statement_backend::describe_column(int colNum, data_type & type, - std::string & columnName) + db_type & dbtype, std::string & columnName) { // In postgresql_ column numbers start from 0 int const pos = colNum - 1; @@ -765,6 +765,7 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 17: // bytea case 2950: // uuid type = dt_string; + dbtype = db_string; break; case 702: // abstime @@ -775,23 +776,35 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 1184: // timestamptz case 1266: // timetz type = dt_date; + dbtype = db_date; break; case 700: // float4 case 701: // float8 case 1700: // numeric type = dt_double; + dbtype = db_double; break; case 16: // bool + type = dt_integer; + dbtype = db_int8; + break; + case 21: // int2 + type = dt_integer; + dbtype = db_int16; + break; + case 23: // int4 case 26: // oid type = dt_integer; + dbtype = db_int32; break; case 20: // int8 type = dt_long_long; + dbtype = db_int64; break; default: @@ -827,6 +840,7 @@ void postgresql_statement_backend::describe_column(int colNum, data_type & type, case 'S': // string type case 'U': // user type type = dt_string; + dbtype = db_string; break; default: diff --git a/src/backends/postgresql/vector-into-type.cpp b/src/backends/postgresql/vector-into-type.cpp index cd024884f..fcdbadb19 100644 --- a/src/backends/postgresql/vector-into-type.cpp +++ b/src/backends/postgresql/vector-into-type.cpp @@ -14,6 +14,7 @@ #include "soci/type-wrappers.h" #include // libpq #include +#include #include #include #include @@ -115,28 +116,52 @@ void postgresql_vector_into_type_backend::post_fetch(bool gotData, indicator * i case x_stdstring: set_invector_(data_, i, buf); break; - case x_short: + case x_int8: { - short const val = string_to_integer(buf); + int8_t const val = string_to_integer(buf); set_invector_(data_, i, val); } break; - case x_integer: + case x_uint8: { - int const val = string_to_integer(buf); + uint8_t const val = string_to_integer(buf); set_invector_(data_, i, val); } break; - case x_long_long: + case x_int16: { - long long const val = string_to_integer(buf); + int16_t const val = string_to_integer(buf); set_invector_(data_, i, val); } break; - case x_unsigned_long_long: + case x_uint16: { - unsigned long long const val = - string_to_unsigned_integer(buf); + uint16_t const val = string_to_integer(buf); + set_invector_(data_, i, val); + } + break; + case x_int32: + { + int32_t const val = string_to_integer(buf); + set_invector_(data_, i, val); + } + break; + case x_uint32: + { + uint32_t const val = string_to_integer(buf); + set_invector_(data_, i, val); + } + break; + case x_int64: + { + int64_t const val = string_to_integer(buf); + set_invector_(data_, i, val); + } + break; + case x_uint64: + { + uint64_t val = + string_to_unsigned_integer(buf); set_invector_(data_, i, val); } break; @@ -199,17 +224,29 @@ void postgresql_vector_into_type_backend::resize(std::size_t sz) case x_char: resizevector_(data_, sz); break; - case x_short: - resizevector_(data_, sz); + case x_int8: + resizevector_(data_, sz); + break; + case x_uint8: + resizevector_(data_, sz); + break; + case x_int16: + resizevector_(data_, sz); break; - case x_integer: - resizevector_(data_, sz); + case x_uint16: + resizevector_(data_, sz); break; - case x_long_long: - resizevector_(data_, sz); + case x_int32: + resizevector_(data_, sz); break; - case x_unsigned_long_long: - resizevector_(data_, sz); + case x_uint32: + resizevector_(data_, sz); + break; + case x_int64: + resizevector_(data_, sz); + break; + case x_uint64: + resizevector_(data_, sz); break; case x_double: resizevector_(data_, sz); @@ -267,17 +304,29 @@ std::size_t postgresql_vector_into_type_backend::full_size() case x_char: sz = get_vector_size(data_); break; - case x_short: - sz = get_vector_size(data_); + case x_int8: + sz = get_vector_size(data_); + break; + case x_uint8: + sz = get_vector_size(data_); + break; + case x_int16: + sz = get_vector_size(data_); + break; + case x_uint16: + sz = get_vector_size(data_); + break; + case x_int32: + sz = get_vector_size(data_); break; - case x_integer: - sz = get_vector_size(data_); + case x_uint32: + sz = get_vector_size(data_); break; - case x_long_long: - sz = get_vector_size(data_); + case x_int64: + sz = get_vector_size(data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); + case x_uint64: + sz = get_vector_size(data_); break; case x_double: sz = get_vector_size(data_); diff --git a/src/backends/postgresql/vector-use-type.cpp b/src/backends/postgresql/vector-use-type.cpp index 3af7ae73e..332b7ebab 100644 --- a/src/backends/postgresql/vector-use-type.cpp +++ b/src/backends/postgresql/vector-use-type.cpp @@ -13,6 +13,7 @@ #include "soci/type-wrappers.h" #include // libpq #include +#include #include #include #include @@ -98,52 +99,102 @@ void postgresql_vector_use_type_backend::pre_use(indicator const * ind) std::strcpy(buf, v[i].c_str()); } break; - case x_short: + case x_int8: { - std::vector * pv - = static_cast *>(data_); - std::vector & v = *pv; + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%d", static_cast(v[i])); + snprintf(buf, bufSize, "%d", v[i]); + } + break; + case x_uint8: + { + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%u", v[i]); + } + break; + case x_int16: + { + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%d", v[i]); + } + break; + case x_uint16: + { + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 3; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%u", v[i]); } break; - case x_integer: + case x_int32: { - std::vector * pv - = static_cast *>(data_); - std::vector & v = *pv; + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; snprintf(buf, bufSize, "%d", v[i]); } break; - case x_long_long: + case x_uint32: { - std::vector* pv - = static_cast*>(data_); - std::vector& v = *pv; + std::vector * pv + = static_cast *>(data_); + std::vector & v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 3; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%" LL_FMT_FLAGS "d", v[i]); + snprintf(buf, bufSize, "%u", v[i]); } break; - case x_unsigned_long_long: + case x_int64: { - std::vector* pv - = static_cast*>(data_); - std::vector& v = *pv; + std::vector* pv + = static_cast*>(data_); + std::vector& v = *pv; std::size_t const bufSize - = std::numeric_limits::digits10 + 2; + = std::numeric_limits::digits10 + 3; buf = new char[bufSize]; - snprintf(buf, bufSize, "%" LL_FMT_FLAGS "u", v[i]); + snprintf(buf, bufSize, "%" LL_FMT_FLAGS "d", + static_cast(v[i])); + } + break; + case x_uint64: + { + std::vector* pv + = static_cast*>(data_); + std::vector& v = *pv; + + std::size_t const bufSize + = std::numeric_limits::digits10 + 2; + buf = new char[bufSize]; + snprintf(buf, bufSize, "%" LL_FMT_FLAGS "u", + static_cast(v[i])); } break; case x_double: @@ -244,17 +295,29 @@ std::size_t postgresql_vector_use_type_backend::full_size() case x_char: sz = get_vector_size(data_); break; - case x_short: - sz = get_vector_size(data_); + case x_int8: + sz = get_vector_size(data_); + break; + case x_uint8: + sz = get_vector_size(data_); + break; + case x_int16: + sz = get_vector_size(data_); + break; + case x_uint16: + sz = get_vector_size(data_); + break; + case x_int32: + sz = get_vector_size(data_); break; - case x_integer: - sz = get_vector_size(data_); + case x_uint32: + sz = get_vector_size(data_); break; - case x_long_long: - sz = get_vector_size(data_); + case x_int64: + sz = get_vector_size(data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); + case x_uint64: + sz = get_vector_size(data_); break; case x_double: sz = get_vector_size(data_); diff --git a/src/backends/sqlite3/standard-into-type.cpp b/src/backends/sqlite3/standard-into-type.cpp index 7d22d9b25..a5e581e9b 100644 --- a/src/backends/sqlite3/standard-into-type.cpp +++ b/src/backends/sqlite3/standard-into-type.cpp @@ -96,30 +96,58 @@ void sqlite3_standard_into_type_backend::post_fetch(bool gotData, break; } - case x_short: - exchange_type_cast(data_) - = static_cast::value_type >( + case x_int8: + exchange_type_cast(data_) + = static_cast::value_type >( sqlite3_column_int(statement_.stmt_, pos) ); break; - case x_integer: - exchange_type_cast(data_) - = static_cast::value_type >( + case x_uint8: + exchange_type_cast(data_) + = static_cast::value_type >( + sqlite3_column_int(statement_.stmt_, pos) + ); + break; + + case x_int16: + exchange_type_cast(data_) + = static_cast::value_type >( + sqlite3_column_int(statement_.stmt_, pos) + ); + break; + + case x_uint16: + exchange_type_cast(data_) + = static_cast::value_type >( + sqlite3_column_int(statement_.stmt_, pos) + ); + break; + + case x_int32: + exchange_type_cast(data_) + = static_cast::value_type >( sqlite3_column_int(statement_.stmt_, pos) ); break; - case x_long_long: - exchange_type_cast(data_) - = static_cast::value_type >( + case x_uint32: + exchange_type_cast(data_) + = static_cast::value_type >( + sqlite3_column_int(statement_.stmt_, pos) + ); + break; + + case x_int64: + exchange_type_cast(data_) + = static_cast::value_type >( sqlite3_column_int64(statement_.stmt_, pos) ); break; - case x_unsigned_long_long: - exchange_type_cast(data_) - = static_cast::value_type >( + case x_uint64: + exchange_type_cast(data_) + = static_cast::value_type >( sqlite3_column_int64(statement_.stmt_, pos) ); break; diff --git a/src/backends/sqlite3/standard-use-type.cpp b/src/backends/sqlite3/standard-use-type.cpp index adbb0581e..016f4da6e 100644 --- a/src/backends/sqlite3/standard-use-type.cpp +++ b/src/backends/sqlite3/standard-use-type.cpp @@ -26,7 +26,7 @@ using namespace soci::details; sqlite3_standard_use_type_backend::sqlite3_standard_use_type_backend( sqlite3_statement_backend &st) - : statement_(st), data_(NULL), type_(x_integer), position_(-1) + : statement_(st), data_(NULL), type_(x_int32), position_(-1) { } @@ -99,6 +99,7 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) { case x_char: col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = &exchange_type_cast(data_); col.buffer_.size_ = 1; break; @@ -107,39 +108,70 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) { const std::string &s = exchange_type_cast(data_); col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = s.c_str(); col.buffer_.size_ = s.size(); break; } - case x_short: + case x_int8: col.type_ = dt_integer; - col.int32_ = exchange_type_cast(data_); + col.dataType_ = db_int8; + col.int8_ = exchange_type_cast(data_); break; - case x_integer: + case x_uint8: col.type_ = dt_integer; - col.int32_ = exchange_type_cast(data_); + col.dataType_ = db_uint8; + col.uint8_ = exchange_type_cast(data_); break; - case x_long_long: + case x_int16: + col.type_ = dt_integer; + col.dataType_ = db_int16; + col.int16_ = exchange_type_cast(data_); + break; + + case x_uint16: + col.type_ = dt_integer; + col.dataType_ = db_uint16; + col.uint16_ = exchange_type_cast(data_); + break; + + case x_int32: + col.type_ = dt_integer; + col.dataType_ = db_int32; + col.int32_ = exchange_type_cast(data_); + break; + + case x_uint32: col.type_ = dt_long_long; - col.int64_ = exchange_type_cast(data_); + col.dataType_ = db_uint32; + col.uint32_ = exchange_type_cast(data_); break; - case x_unsigned_long_long: + case x_int64: col.type_ = dt_long_long; - col.int64_ = exchange_type_cast(data_); + col.dataType_ = db_int64; + col.int64_ = exchange_type_cast(data_); + break; + + case x_uint64: + col.type_ = dt_unsigned_long_long; + col.dataType_ = db_uint64; + col.uint64_ = exchange_type_cast(data_); break; case x_double: col.type_ = dt_double; + col.dataType_ = db_double; col.double_ = exchange_type_cast(data_); break; case x_stdtm: { col.type_ = dt_date; + col.dataType_ = db_date; static const size_t bufSize = 20; std::tm &t = exchange_type_cast(data_); @@ -156,6 +188,7 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) case x_rowid: { col.type_ = dt_long_long; + col.dataType_ = db_int64; // RowID is internally identical to unsigned long rowid *rid = static_cast(data_); sqlite3_rowid_backend *rbe = static_cast(rid->get_backend()); @@ -167,6 +200,7 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) case x_blob: { col.type_ = dt_blob; + col.dataType_ = db_blob; blob *b = static_cast(data_); sqlite3_blob_backend *bbe = static_cast(b->get_backend()); @@ -179,6 +213,7 @@ void sqlite3_standard_use_type_backend::pre_use(indicator const * ind) { const soci::xml_type &xml = exchange_type_cast(data_); col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = xml.value.c_str(); col.buffer_.size_ = xml.value.size(); break; diff --git a/src/backends/sqlite3/statement.cpp b/src/backends/sqlite3/statement.cpp index b97c7e694..8b1db7145 100644 --- a/src/backends/sqlite3/statement.cpp +++ b/src/backends/sqlite3/statement.cpp @@ -10,6 +10,7 @@ // std #include #include +#include #include #include #include @@ -116,9 +117,10 @@ sqlite3_statement_backend::load_rowset(int totalRows) { numCols = sqlite3_column_count(stmt_); data_type type; + db_type dbtype; std::string name; for (int c = 1; c <= numCols; ++c) - describe_column(c, type, name); + describe_column(c, type, dbtype, name); } else numCols = static_cast(columns_.size()); @@ -163,36 +165,53 @@ sqlite3_statement_backend::load_rowset(int totalRows) col.isNull_ = false; col.type_ = coldef.type_; + col.dataType_ = coldef.dataType_; - switch (coldef.type_) + switch (coldef.dataType_) { - case dt_string: - case dt_date: + case db_string: + case db_date: col.buffer_.size_ = sqlite3_column_bytes(stmt_, c); col.buffer_.data_ = new char[col.buffer_.size_+1]; memcpy(col.buffer_.data_, sqlite3_column_text(stmt_, c), col.buffer_.size_+1); break; - case dt_double: + case db_double: col.double_ = sqlite3_column_double(stmt_, c); break; - case dt_integer: - col.int32_ = sqlite3_column_int(stmt_, c); + case db_int8: + col.int8_ = static_cast(sqlite3_column_int(stmt_, c)); break; - - case dt_long_long: - case dt_unsigned_long_long: + case db_uint8: + col.uint8_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case db_int16: + col.int16_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case db_uint16: + col.uint16_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case db_int32: + col.int32_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case db_uint32: + col.uint32_ = static_cast(sqlite3_column_int(stmt_, c)); + break; + case db_int64: col.int64_ = sqlite3_column_int64(stmt_, c); break; + case db_uint64: + col.uint64_ = static_cast(sqlite3_column_int64(stmt_, c)); + break; - case dt_blob: + case db_blob: col.buffer_.size_ = sqlite3_column_bytes(stmt_, c); col.buffer_.data_ = (col.buffer_.size_ > 0 ? new char[col.buffer_.size_] : NULL); memcpy(col.buffer_.data_, sqlite3_column_blob(stmt_, c), col.buffer_.size_); break; - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); } } @@ -269,34 +288,50 @@ sqlite3_statement_backend::bind_and_execute(int number) } else { - switch (col.type_) + switch (col.dataType_) { - case dt_string: + case db_string: bindRes = sqlite3_bind_text(stmt_, pos, col.buffer_.constData_, static_cast(col.buffer_.size_), NULL); break; - case dt_date: + case db_date: bindRes = sqlite3_bind_text(stmt_, pos, col.buffer_.constData_, static_cast(col.buffer_.size_), SQLITE_TRANSIENT); break; - case dt_double: + case db_double: bindRes = sqlite3_bind_double(stmt_, pos, col.double_); break; - case dt_integer: - bindRes = sqlite3_bind_int(stmt_, pos, col.int32_); + case db_int8: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int8_)); break; - - case dt_long_long: - case dt_unsigned_long_long: + case db_uint8: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.uint8_)); + break; + case db_int16: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int16_)); + break; + case db_uint16: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.uint16_)); + break; + case db_int32: + bindRes = sqlite3_bind_int(stmt_, pos, static_cast(col.int32_)); + break; + case db_uint32: + bindRes = sqlite3_bind_int64(stmt_, pos, static_cast(col.uint32_)); + break; + case db_int64: bindRes = sqlite3_bind_int64(stmt_, pos, col.int64_); break; + case db_uint64: + bindRes = sqlite3_bind_int64(stmt_, pos, static_cast(col.int64_)); + break; - case dt_blob: + case db_blob: bindRes = sqlite3_bind_blob(stmt_, pos, col.buffer_.constData_, static_cast(col.buffer_.size_), NULL); break; - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); } } @@ -408,63 +443,58 @@ int sqlite3_statement_backend::prepare_for_describe() return sqlite3_column_count(stmt_); } -typedef std::map sqlite3_data_type_map; +typedef std::map> sqlite3_data_type_map; static sqlite3_data_type_map get_data_type_map() { sqlite3_data_type_map m; // Spaces are removed from decltype before looking up in this map, so we don't use them here as well - // dt_blob - m["blob"] = dt_blob; - - // dt_date - m["date"] = dt_date; - m["time"] = dt_date; - m["datetime"] = dt_date; - m["timestamp"] = dt_date; - - // dt_double - m["decimal"] = dt_double; - m["double"] = dt_double; - m["doubleprecision"] = dt_double; - m["float"] = dt_double; - m["number"] = dt_double; - m["numeric"] = dt_double; - m["real"] = dt_double; - - // dt_integer - m["boolean"] = dt_integer; - m["int"] = dt_integer; - m["integer"] = dt_integer; - m["int2"] = dt_integer; - m["mediumint"] = dt_integer; - m["smallint"] = dt_integer; - m["tinyint"] = dt_integer; - - // dt_long_long - m["bigint"] = dt_long_long; - m["int8"] = dt_long_long; - - // dt_string - m["char"] = dt_string; - m["character"] = dt_string; - m["clob"] = dt_string; - m["nativecharacter"] = dt_string; - m["nchar"] = dt_string; - m["nvarchar"] = dt_string; - m["text"] = dt_string; - m["varchar"] = dt_string; - m["varyingcharacter"] = dt_string; - - // dt_unsigned_long_long - m["unsignedbigint"] = dt_unsigned_long_long; + m["blob"] = { dt_blob, db_blob }; + + m["date"] = { dt_date, db_date }; + m["time"] = { dt_date, db_date }; + m["datetime"] = { dt_date, db_date }; + m["timestamp"] = { dt_date, db_date }; + + m["decimal"] = { dt_double, db_double }; + m["double"] = { dt_double, db_double }; + m["doubleprecision"] = { dt_double, db_double }; + m["float"] = { dt_double, db_double }; + m["number"] = { dt_double, db_double }; + m["numeric"] = { dt_double, db_double }; + m["real"] = { dt_double, db_double }; + + m["tinyint"] = { dt_integer, db_int8 }; + + m["smallint"] = { dt_integer, db_int16 }; + + m["boolean"] = { dt_integer, db_int32 }; + m["int"] = { dt_integer, db_int32 }; + m["integer"] = { dt_integer, db_int32 }; + m["int2"] = { dt_integer, db_int32 }; + m["mediumint"] = { dt_integer, db_int32 }; + + m["bigint"] = { dt_long_long, db_int64 }; + m["int8"] = { dt_long_long, db_int64 }; + + m["char"] = { dt_string, db_string }; + m["character"] = { dt_string, db_string }; + m["clob"] = { dt_string, db_string }; + m["nativecharacter"] = { dt_string, db_string }; + m["nchar"] = { dt_string, db_string }; + m["nvarchar"] = { dt_string, db_string }; + m["text"] = { dt_string, db_string }; + m["varchar"] = { dt_string, db_string }; + m["varyingcharacter"] = { dt_string, db_string }; + m["unsignedbigint"] = { dt_unsigned_long_long, db_uint64 }; return m; } void sqlite3_statement_backend::describe_column(int colNum, data_type & type, + db_type & dbtype, std::string & columnName) { static const sqlite3_data_type_map dataTypeMap = get_data_type_map(); @@ -477,6 +507,7 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, { columnName = coldef.name_; type = coldef.type_; + dbtype = coldef.dataType_; return; } @@ -510,7 +541,8 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, sqlite3_data_type_map::const_iterator iter = dataTypeMap.find(dt); if (iter != dataTypeMap.end()) { - coldef.type_ = type = iter->second; + coldef.type_ = type = iter->second.first; + coldef.dataType_ = dbtype = iter->second.second; return; } @@ -525,19 +557,24 @@ void sqlite3_statement_backend::describe_column(int colNum, data_type & type, { case SQLITE_INTEGER: type = dt_integer; + dbtype = db_int32; break; case SQLITE_FLOAT: type = dt_double; + dbtype = db_double; break; case SQLITE_BLOB: case SQLITE_TEXT: type = dt_string; + dbtype = db_string; break; default: type = dt_string; + dbtype = db_string; break; } coldef.type_ = type; + coldef.dataType_ = dbtype; sqlite3_reset(stmt_); } diff --git a/src/backends/sqlite3/vector-into-type.cpp b/src/backends/sqlite3/vector-into-type.cpp index 8feb99d00..fb67a252d 100644 --- a/src/backends/sqlite3/vector-into-type.cpp +++ b/src/backends/sqlite3/vector-into-type.cpp @@ -22,6 +22,7 @@ #include "common.h" // std #include +#include #include #include #include @@ -87,31 +88,47 @@ void set_number_in_vector(void *p, int idx, const sqlite3_column &col) using namespace details; using namespace details::sqlite3; - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: set_in_vector(p, idx, parse_number_from_string(col.buffer_.size_ > 0 ? col.buffer_.constData_ : "")); break; - case dt_double: + case db_double: set_in_vector(p, idx, static_cast(col.double_)); break; - case dt_integer: + case db_int8: + set_in_vector(p, idx, static_cast(col.int8_)); + break; + case db_uint8: + set_in_vector(p, idx, static_cast(col.uint8_)); + break; + case db_int16: + set_in_vector(p, idx, static_cast(col.int16_)); + break; + case db_uint16: + set_in_vector(p, idx, static_cast(col.uint16_)); + break; + case db_int32: set_in_vector(p, idx, static_cast(col.int32_)); break; - - case dt_long_long: - case dt_unsigned_long_long: + case db_uint32: + set_in_vector(p, idx, static_cast(col.uint32_)); + break; + case db_int64: set_in_vector(p, idx, static_cast(col.int64_)); break; + case db_uint64: + set_in_vector(p, idx, static_cast(col.uint64_)); + break; - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); }; } @@ -155,36 +172,76 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) { case x_char: { - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: set_in_vector(data_, i, (col.buffer_.size_ > 0 ? col.buffer_.constData_[0] : '\0')); break; - case dt_double: + case db_double: set_in_vector(data_, i, double_to_cstring(col.double_)[0]); break; - case dt_integer: + case db_int8: + { + std::ostringstream ss; + ss << col.int8_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case db_uint8: + { + std::ostringstream ss; + ss << col.uint8_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case db_int16: + { + std::ostringstream ss; + ss << col.int16_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case db_uint16: + { + std::ostringstream ss; + ss << col.uint16_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case db_int32: { std::ostringstream ss; ss << col.int32_; set_in_vector(data_, i, ss.str()[0]); break; } - - case dt_long_long: - case dt_unsigned_long_long: + case db_uint32: + { + std::ostringstream ss; + ss << col.uint32_; + set_in_vector(data_, i, ss.str()[0]); + break; + } + case db_int64: { std::ostringstream ss; ss << col.int64_; set_in_vector(data_, i, ss.str()[0]); break; } + case db_uint64: + { + std::ostringstream ss; + ss << col.uint64_; + set_in_vector(data_, i, ss.str()[0]); + break; + } - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); }; break; @@ -192,36 +249,76 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) case x_stdstring: { - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: set_in_vector(data_, i, std::string(col.buffer_.constData_, col.buffer_.size_)); break; - case dt_double: + case db_double: set_in_vector(data_, i, double_to_cstring(col.double_)); break; - case dt_integer: + case db_int8: + { + std::ostringstream ss; + ss << col.int8_; + set_in_vector(data_, i, ss.str()); + break; + } + case db_uint8: + { + std::ostringstream ss; + ss << col.uint8_; + set_in_vector(data_, i, ss.str()); + break; + } + case db_int16: + { + std::ostringstream ss; + ss << col.int16_; + set_in_vector(data_, i, ss.str()); + break; + } + case db_uint16: + { + std::ostringstream ss; + ss << col.uint16_; + set_in_vector(data_, i, ss.str()); + break; + } + case db_int32: { std::ostringstream ss; ss << col.int32_; set_in_vector(data_, i, ss.str()); break; } - - case dt_long_long: - case dt_unsigned_long_long: + case db_uint32: + { + std::ostringstream ss; + ss << col.uint32_; + set_in_vector(data_, i, ss.str()); + break; + } + case db_int64: { std::ostringstream ss; ss << col.int64_; set_in_vector(data_, i, ss.str()); break; } + case db_uint64: + { + std::ostringstream ss; + ss << col.uint64_; + set_in_vector(data_, i, ss.str()); + break; + } - case dt_xml: + case db_xml: { soci::xml_type xml; xml.value = std::string(col.buffer_.constData_, col.buffer_.size_); @@ -234,11 +331,11 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) case x_xmltype: { - switch (col.type_) + switch (col.dataType_) { - case dt_string: - case dt_blob: - case dt_xml: + case db_string: + case db_blob: + case db_xml: { soci::xml_type xml; xml.value = std::string(col.buffer_.constData_, col.buffer_.size_); @@ -251,20 +348,36 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) break; } // x_xmltype - case x_short: - set_number_in_vector::value_type>(data_, i, col); + case x_int8: + set_number_in_vector::value_type>(data_, i, col); + break; + + case x_uint8: + set_number_in_vector::value_type>(data_, i, col); + break; + + case x_int16: + set_number_in_vector::value_type>(data_, i, col); + break; + + case x_uint16: + set_number_in_vector::value_type>(data_, i, col); break; - case x_integer: - set_number_in_vector::value_type>(data_, i, col); + case x_int32: + set_number_in_vector::value_type>(data_, i, col); break; - case x_long_long: - set_number_in_vector::value_type>(data_, i, col); + case x_uint32: + set_number_in_vector::value_type>(data_, i, col); break; - case x_unsigned_long_long: - set_number_in_vector::value_type>(data_, i, col); + case x_int64: + set_number_in_vector::value_type>(data_, i, col); + break; + + case x_uint64: + set_number_in_vector::value_type>(data_, i, col); break; case x_double: @@ -273,11 +386,11 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) case x_stdtm: { - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: { // attempt to parse the string and convert to std::tm std::tm t = std::tm(); @@ -287,13 +400,18 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) break; } - case dt_double: - case dt_integer: - case dt_long_long: - case dt_unsigned_long_long: + case db_double: + case db_int8: + case db_uint8: + case db_int16: + case db_uint16: + case db_int32: + case db_uint32: + case db_int64: + case db_uint64: throw soci_error("Into element used with non-convertible type."); - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); }; break; @@ -304,22 +422,27 @@ void sqlite3_vector_into_type_backend::post_fetch(bool gotData, indicator * ind) } // cleanup data - switch (col.type_) + switch (col.dataType_) { - case dt_date: - case dt_string: - case dt_blob: + case db_date: + case db_string: + case db_blob: delete[] col.buffer_.data_; col.buffer_.data_ = NULL; break; - case dt_double: - case dt_integer: - case dt_long_long: - case dt_unsigned_long_long: + case db_double: + case db_int8: + case db_uint8: + case db_int16: + case db_uint16: + case db_int32: + case db_uint32: + case db_int64: + case db_uint64: break; - case dt_xml: + case db_xml: throw soci_error("XML data type is not supported"); } } @@ -336,17 +459,29 @@ void sqlite3_vector_into_type_backend::resize(std::size_t sz) case x_char: resize_vector(data_, sz); break; - case x_short: - resize_vector(data_, sz); + case x_int8: + resize_vector(data_, sz); + break; + case x_uint8: + resize_vector(data_, sz); + break; + case x_int16: + resize_vector(data_, sz); + break; + case x_uint16: + resize_vector(data_, sz); break; - case x_integer: - resize_vector(data_, sz); + case x_int32: + resize_vector(data_, sz); break; - case x_long_long: - resize_vector(data_, sz); + case x_uint32: + resize_vector(data_, sz); break; - case x_unsigned_long_long: - resize_vector(data_, sz); + case x_int64: + resize_vector(data_, sz); + break; + case x_uint64: + resize_vector(data_, sz); break; case x_double: resize_vector(data_, sz); @@ -377,17 +512,29 @@ std::size_t sqlite3_vector_into_type_backend::size() case x_char: sz = get_vector_size(data_); break; - case x_short: - sz = get_vector_size(data_); + case x_int8: + sz = get_vector_size(data_); + break; + case x_uint8: + sz = get_vector_size(data_); + break; + case x_int16: + sz = get_vector_size(data_); + break; + case x_uint16: + sz = get_vector_size(data_); + break; + case x_int32: + sz = get_vector_size(data_); break; - case x_integer: - sz = get_vector_size(data_); + case x_uint32: + sz = get_vector_size(data_); break; - case x_long_long: - sz = get_vector_size(data_); + case x_int64: + sz = get_vector_size(data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); + case x_uint64: + sz = get_vector_size(data_); break; case x_double: sz = get_vector_size(data_); diff --git a/src/backends/sqlite3/vector-use-type.cpp b/src/backends/sqlite3/vector-use-type.cpp index c98a3abf9..71c2ea624 100644 --- a/src/backends/sqlite3/vector-use-type.cpp +++ b/src/backends/sqlite3/vector-use-type.cpp @@ -13,6 +13,7 @@ #include "common.h" // std #include +#include #include #include #include @@ -98,6 +99,7 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) { case x_char: col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = &(*static_cast::value_type> *>(data_))[i]; col.buffer_.size_ = 1; break; @@ -106,33 +108,63 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) { std::string &s = (*static_cast::value_type> *>(data_))[i]; col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = s.c_str(); col.buffer_.size_ = s.size(); break; } - case x_short: + case x_int8: col.type_ = dt_integer; - col.int32_ = (*static_cast::value_type> *>(data_))[i]; + col.dataType_ = db_int8; + col.int8_ = (*static_cast::value_type> *>(data_))[i]; break; - case x_integer: + case x_uint8: col.type_ = dt_integer; - col.int32_ = (*static_cast::value_type> *>(data_))[i]; + col.dataType_ = db_uint8; + col.uint8_ = (*static_cast::value_type> *>(data_))[i]; break; - case x_long_long: + case x_int16: + col.type_ = dt_integer; + col.dataType_ = db_int16; + col.int16_ = (*static_cast::value_type> *>(data_))[i]; + break; + + case x_uint16: + col.type_ = dt_integer; + col.dataType_ = db_uint16; + col.uint16_ = (*static_cast::value_type> *>(data_))[i]; + break; + + case x_int32: + col.type_ = dt_integer; + col.dataType_ = db_int32; + col.int32_ = (*static_cast::value_type> *>(data_))[i]; + break; + + case x_uint32: col.type_ = dt_long_long; - col.int64_ = (*static_cast::value_type> *>(data_))[i]; + col.dataType_ = db_uint32; + col.uint32_ = (*static_cast::value_type> *>(data_))[i]; break; - case x_unsigned_long_long: + case x_int64: col.type_ = dt_long_long; - col.int64_ = (*static_cast::value_type> *>(data_))[i]; + col.dataType_ = db_int64; + col.int64_ = (*static_cast::value_type> *>(data_))[i]; + break; + + case x_uint64: + col.type_ = dt_unsigned_long_long; + col.dataType_ = db_uint64; + col.uint64_ = (*static_cast::value_type> *>(data_))[i]; break; case x_double: col.type_ = dt_double; + col.dataType_ = db_double; col.double_ = (*static_cast::value_type> *>(data_))[i]; break; @@ -142,6 +174,7 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) static const size_t bufSize = 20; col.type_ = dt_date; + col.dataType_ = db_date; col.buffer_.data_ = new char[bufSize]; col.buffer_.size_ = snprintf(col.buffer_.data_, bufSize, "%d-%02d-%02d %02d:%02d:%02d", @@ -155,6 +188,7 @@ void sqlite3_vector_use_type_backend::pre_use(indicator const * ind) { soci::xml_type &xml = (*static_cast::value_type> *>(data_))[i]; col.type_ = dt_string; + col.dataType_ = db_string; col.buffer_.constData_ = xml.value.c_str(); col.buffer_.size_ = xml.value.size(); break; @@ -176,17 +210,29 @@ std::size_t sqlite3_vector_use_type_backend::size() case x_char: sz = get_vector_size(data_); break; - case x_short: - sz = get_vector_size(data_); + case x_int8: + sz = get_vector_size(data_); + break; + case x_uint8: + sz = get_vector_size(data_); + break; + case x_int16: + sz = get_vector_size(data_); + break; + case x_uint16: + sz = get_vector_size(data_); + break; + case x_int32: + sz = get_vector_size(data_); break; - case x_integer: - sz = get_vector_size(data_); + case x_uint32: + sz = get_vector_size(data_); break; - case x_long_long: - sz = get_vector_size(data_); + case x_int64: + sz = get_vector_size(data_); break; - case x_unsigned_long_long: - sz = get_vector_size(data_); + case x_uint64: + sz = get_vector_size(data_); break; case x_double: sz = get_vector_size(data_); diff --git a/src/core/once-temp-type.cpp b/src/core/once-temp-type.cpp index 6fd189f68..5e3597c62 100644 --- a/src/core/once-temp-type.cpp +++ b/src/core/once-temp-type.cpp @@ -126,6 +126,24 @@ ddl_type & ddl_type::column(const std::string & columnName, data_type dt, return *this; } +ddl_type & ddl_type::column(const std::string & columnName, db_type dt, + int precision, int scale) +{ + if (rcst_->get_need_comma()) + { + rcst_->accumulate(", "); + } + + rcst_->accumulate(columnName); + rcst_->accumulate(" "); + rcst_->accumulate( + s_->get_backend()->create_column_type(dt, precision, scale)); + + rcst_->set_need_comma(true); + + return *this; +} + ddl_type & ddl_type::unique(const std::string & name, const std::string & columnNames) { diff --git a/src/core/soci-simple.cpp b/src/core/soci-simple.cpp index 80b6d579d..99397ec8a 100644 --- a/src/core/soci-simple.cpp +++ b/src/core/soci-simple.cpp @@ -353,35 +353,59 @@ struct statement_wrapper // into elements int next_position; - std::vector into_types; // for both single and bulk + std::vector into_types; // for both single and bulk std::vector into_indicators; std::map into_strings; - std::map into_ints; - std::map into_longlongs; + std::map into_int8; + std::map into_uint8; + std::map into_int16; + std::map into_uint16; + std::map into_int32; + std::map into_uint32; + std::map into_int64; + std::map into_uint64; std::map into_doubles; std::map into_dates; std::map into_blob; std::vector > into_indicators_v; std::map > into_strings_v; - std::map > into_ints_v; - std::map > into_longlongs_v; + std::map > into_int8_v; + std::map > into_uint8_v; + std::map > into_int16_v; + std::map > into_uint16_v; + std::map > into_int32_v; + std::map > into_uint32_v; + std::map > into_int64_v; + std::map > into_uint64_v; std::map > into_doubles_v; std::map > into_dates_v; // use elements std::map use_indicators; std::map use_strings; - std::map use_ints; - std::map use_longlongs; + std::map use_int8; + std::map use_uint8; + std::map use_int16; + std::map use_uint16; + std::map use_int32; + std::map use_uint32; + std::map use_int64; + std::map use_uint64; std::map use_doubles; std::map use_dates; std::map use_blob; std::map > use_indicators_v; std::map > use_strings_v; - std::map > use_ints_v; - std::map > use_longlongs_v; + std::map > use_int8_v; + std::map > use_uint8_v; + std::map > use_int16_v; + std::map > use_uint16_v; + std::map > use_int32_v; + std::map > use_uint32_v; + std::map > use_int64_v; + std::map > use_uint64_v; std::map > use_doubles_v; std::map > use_dates_v; @@ -464,7 +488,7 @@ bool cannot_add_elements(statement_wrapper & wrapper, statement_wrapper::kind k, // helper for checking if the expected into element exists on the given position bool position_check_failed(statement_wrapper & wrapper, statement_wrapper::kind k, - int position, data_type expected_type, char const * type_name) + int position, db_type expected_type, char const * type_name) { if (position < 0 || position >= wrapper.next_position) { @@ -575,7 +599,7 @@ bool name_unique_check_failed(statement_wrapper & wrapper, // helper for checking if the use element with the given name exists bool name_exists_check_failed(statement_wrapper & wrapper, - char const * name, data_type expected_type, + char const * name, db_type expected_type, statement_wrapper::kind k, char const * type_name) { bool name_exists = false; @@ -583,7 +607,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, { switch (expected_type) { - case dt_string: + case db_string: { typedef std::map < @@ -594,43 +618,85 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_strings.end()); } break; - case dt_integer: + case db_int8: { - typedef std::map::const_iterator iterator; - iterator const it = wrapper.use_ints.find(name); - name_exists = (it != wrapper.use_ints.end()); + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_int8.find(name); + name_exists = (it != wrapper.use_int8.end()); } break; - case dt_long_long: - case dt_unsigned_long_long: + case db_uint8: { - typedef std::map::const_iterator + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_uint8.find(name); + name_exists = (it != wrapper.use_uint8.end()); + } + break; + case db_int16: + { + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_int16.find(name); + name_exists = (it != wrapper.use_int16.end()); + } + break; + case db_uint16: + { + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_uint16.find(name); + name_exists = (it != wrapper.use_uint16.end()); + } + break; + case db_int32: + { + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_int32.find(name); + name_exists = (it != wrapper.use_int32.end()); + } + break; + case db_uint32: + { + typedef std::map::const_iterator iterator; + iterator const it = wrapper.use_uint32.find(name); + name_exists = (it != wrapper.use_uint32.end()); + } + break; + case db_int64: + { + typedef std::map::const_iterator + iterator; + iterator const it = wrapper.use_int64.find(name); + name_exists = (it != wrapper.use_int64.end()); + } + break; + case db_uint64: + { + typedef std::map::const_iterator iterator; - iterator const it = wrapper.use_longlongs.find(name); - name_exists = (it != wrapper.use_longlongs.end()); + iterator const it = wrapper.use_uint64.find(name); + name_exists = (it != wrapper.use_uint64.end()); } break; - case dt_double: + case db_double: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_doubles.find(name); name_exists = (it != wrapper.use_doubles.end()); } break; - case dt_date: + case db_date: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_dates.find(name); name_exists = (it != wrapper.use_dates.end()); } break; - case dt_blob: + case db_blob: { typedef std::map::const_iterator iterator; iterator const it = wrapper.use_blob.find(name); name_exists = (it != wrapper.use_blob.end()); } - case dt_xml: + case db_xml: // no support for xml break; } @@ -641,7 +707,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, switch (expected_type) { - case dt_string: + case db_string: { typedef std::map < @@ -652,30 +718,95 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_strings_v.end()); } break; - case dt_integer: + case db_int8: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_int8_v.find(name); + name_exists = (it != wrapper.use_int8_v.end()); + } + break; + case db_uint8: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_uint8_v.find(name); + name_exists = (it != wrapper.use_uint8_v.end()); + } + break; + case db_int16: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_int16_v.find(name); + name_exists = (it != wrapper.use_int16_v.end()); + } + break; + case db_uint16: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_uint16_v.find(name); + name_exists = (it != wrapper.use_uint16_v.end()); + } + break; + case db_int32: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_int32_v.find(name); + name_exists = (it != wrapper.use_int32_v.end()); + } + break; + case db_uint32: + { + typedef std::map + < + std::string, + std::vector + >::const_iterator iterator; + iterator const it = wrapper.use_uint32_v.find(name); + name_exists = (it != wrapper.use_uint32_v.end()); + } + break; + case db_int64: { typedef std::map < std::string, - std::vector + std::vector >::const_iterator iterator; - iterator const it = wrapper.use_ints_v.find(name); - name_exists = (it != wrapper.use_ints_v.end()); + iterator const it = wrapper.use_int64_v.find(name); + name_exists = (it != wrapper.use_int64_v.end()); } break; - case dt_long_long: - case dt_unsigned_long_long: + case db_uint64: { typedef std::map < std::string, - std::vector + std::vector >::const_iterator iterator; - iterator const it = wrapper.use_longlongs_v.find(name); - name_exists = (it != wrapper.use_longlongs_v.end()); + iterator const it = wrapper.use_uint64_v.find(name); + name_exists = (it != wrapper.use_uint64_v.end()); } break; - case dt_double: + case db_double: { typedef std::map >::const_iterator iterator; @@ -683,7 +814,7 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_doubles_v.end()); } break; - case dt_date: + case db_date: { typedef std::map >::const_iterator iterator; @@ -691,8 +822,8 @@ bool name_exists_check_failed(statement_wrapper & wrapper, name_exists = (it != wrapper.use_dates_v.end()); } break; - case dt_blob: - case dt_xml: + case db_blob: + case db_xml: // no support for bulk and xml load break; } @@ -805,13 +936,23 @@ SOCI_DECL int soci_into_string(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_string); + wrapper->into_types.push_back(db_string); wrapper->into_indicators.push_back(i_ok); wrapper->into_strings[wrapper->next_position]; // create new entry return wrapper->next_position++; } SOCI_DECL int soci_into_int(statement_handle st) +{ + return soci_into_int32(st); +} + +SOCI_DECL int soci_into_long_long(statement_handle st) +{ + return soci_into_int64(st); +} + +SOCI_DECL int soci_into_int8(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -823,13 +964,103 @@ SOCI_DECL int soci_into_int(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_integer); + wrapper->into_types.push_back(db_int8); wrapper->into_indicators.push_back(i_ok); - wrapper->into_ints[wrapper->next_position]; // create new entry + wrapper->into_int8[wrapper->next_position]; // create new entry return wrapper->next_position++; } -SOCI_DECL int soci_into_long_long(statement_handle st) +SOCI_DECL int soci_into_uint8(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(db_uint8); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_uint8[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int16(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(db_int16); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_int16[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint16(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(db_uint16); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_uint16[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int32(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(db_int32); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_int32[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint32(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(db_uint32); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_uint32[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_int64(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -841,9 +1072,27 @@ SOCI_DECL int soci_into_long_long(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_long_long); + wrapper->into_types.push_back(db_int64); wrapper->into_indicators.push_back(i_ok); - wrapper->into_longlongs[wrapper->next_position]; // create new entry + wrapper->into_int64[wrapper->next_position]; // create new entry + return wrapper->next_position++; +} + +SOCI_DECL int soci_into_uint64(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, true)) + { + return -1; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::single; + + wrapper->into_types.push_back(db_uint64); + wrapper->into_indicators.push_back(i_ok); + wrapper->into_uint64[wrapper->next_position]; // create new entry return wrapper->next_position++; } @@ -859,7 +1108,7 @@ SOCI_DECL int soci_into_double(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_double); + wrapper->into_types.push_back(db_double); wrapper->into_indicators.push_back(i_ok); wrapper->into_doubles[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -877,7 +1126,7 @@ SOCI_DECL int soci_into_date(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_date); + wrapper->into_types.push_back(db_date); wrapper->into_indicators.push_back(i_ok); wrapper->into_dates[wrapper->next_position]; // create new entry return wrapper->next_position++; @@ -895,7 +1144,7 @@ SOCI_DECL int soci_into_blob(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::single; - wrapper->into_types.push_back(dt_blob); + wrapper->into_types.push_back(db_blob); wrapper->into_indicators.push_back(i_ok); wrapper->into_blob[wrapper->next_position] = soci_create_blob_session(wrapper->sql); // create new entry return wrapper->next_position++; @@ -913,13 +1162,23 @@ SOCI_DECL int soci_into_string_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_string); + wrapper->into_types.push_back(db_string); wrapper->into_indicators_v.push_back(std::vector()); wrapper->into_strings_v[wrapper->next_position]; return wrapper->next_position++; } SOCI_DECL int soci_into_int_v(statement_handle st) +{ + return soci_into_int32_v(st); +} + +SOCI_DECL int soci_into_long_long_v(statement_handle st) +{ + return soci_into_int64_v(st); +} + +SOCI_DECL int soci_into_int8_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -931,13 +1190,13 @@ SOCI_DECL int soci_into_int_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_integer); + wrapper->into_types.push_back(db_int8); wrapper->into_indicators_v.push_back(std::vector()); - wrapper->into_ints_v[wrapper->next_position]; + wrapper->into_int8_v[wrapper->next_position]; return wrapper->next_position++; } -SOCI_DECL int soci_into_long_long_v(statement_handle st) +SOCI_DECL int soci_into_uint8_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -949,13 +1208,13 @@ SOCI_DECL int soci_into_long_long_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_long_long); + wrapper->into_types.push_back(db_uint8); wrapper->into_indicators_v.push_back(std::vector()); - wrapper->into_longlongs_v[wrapper->next_position]; + wrapper->into_uint8_v[wrapper->next_position]; return wrapper->next_position++; } -SOCI_DECL int soci_into_double_v(statement_handle st) +SOCI_DECL int soci_into_int16_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -967,13 +1226,13 @@ SOCI_DECL int soci_into_double_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_double); + wrapper->into_types.push_back(db_int16); wrapper->into_indicators_v.push_back(std::vector()); - wrapper->into_doubles_v[wrapper->next_position]; + wrapper->into_int16_v[wrapper->next_position]; return wrapper->next_position++; } -SOCI_DECL int soci_into_date_v(statement_handle st) +SOCI_DECL int soci_into_uint16_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); @@ -985,109 +1244,311 @@ SOCI_DECL int soci_into_date_v(statement_handle st) wrapper->statement_state = statement_wrapper::defining; wrapper->into_kind = statement_wrapper::bulk; - wrapper->into_types.push_back(dt_date); + wrapper->into_types.push_back(db_uint16); wrapper->into_indicators_v.push_back(std::vector()); - wrapper->into_dates_v[wrapper->next_position]; + wrapper->into_uint16_v[wrapper->next_position]; return wrapper->next_position++; } -SOCI_DECL int soci_get_into_state(statement_handle st, int position) +SOCI_DECL int soci_into_int32_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); - if (position < 0 || position >= wrapper->next_position) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) { - wrapper->is_ok = false; - wrapper->error_message = "Invalid position."; - return 0; + return -1; } - wrapper->is_ok = true; - return wrapper->into_indicators[position] == i_ok ? 1 : 0; + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(db_int32); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_int32_v[wrapper->next_position]; + return wrapper->next_position++; } -SOCI_DECL char const * soci_get_into_string(statement_handle st, int position) +SOCI_DECL int soci_into_uint32_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); - if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_string, "string") || - not_null_check_failed(*wrapper, position)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) { - return ""; + return -1; } - return wrapper->into_strings[position].c_str(); + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(db_uint32); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_uint32_v[wrapper->next_position]; + return wrapper->next_position++; } -SOCI_DECL int soci_get_into_int(statement_handle st, int position) +SOCI_DECL int soci_into_int64_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); - if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_integer, "int") || - not_null_check_failed(*wrapper, position)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) { - return 0; + return -1; } - return wrapper->into_ints[position]; + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(db_int64); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_int64_v[wrapper->next_position]; + return wrapper->next_position++; } -SOCI_DECL long long soci_get_into_long_long(statement_handle st, int position) +SOCI_DECL int soci_into_uint64_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); - if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_long_long, "long long") || - not_null_check_failed(*wrapper, position)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) { - return 0LL; + return -1; } - return wrapper->into_longlongs[position]; + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(db_uint64); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_uint64_v[wrapper->next_position]; + return wrapper->next_position++; } -SOCI_DECL double soci_get_into_double(statement_handle st, int position) +SOCI_DECL int soci_into_double_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); - if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_double, "double") || - not_null_check_failed(*wrapper, position)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) { - return 0.0; + return -1; } - return wrapper->into_doubles[position]; + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(db_double); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_doubles_v[wrapper->next_position]; + return wrapper->next_position++; } -SOCI_DECL char const * soci_get_into_date(statement_handle st, int position) +SOCI_DECL int soci_into_date_v(statement_handle st) { statement_wrapper * wrapper = static_cast(st); - if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_date, "date") || - not_null_check_failed(*wrapper, position)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, true)) { - return ""; + return -1; } - // format is: "YYYY MM DD hh mm ss" - std::tm const & d = wrapper->into_dates[position]; - return format_date(*wrapper, d); + wrapper->statement_state = statement_wrapper::defining; + wrapper->into_kind = statement_wrapper::bulk; + + wrapper->into_types.push_back(db_date); + wrapper->into_indicators_v.push_back(std::vector()); + wrapper->into_dates_v[wrapper->next_position]; + return wrapper->next_position++; } -SOCI_DECL blob_handle soci_get_into_blob(statement_handle st, int position) +SOCI_DECL int soci_get_into_state(statement_handle st, int position) { statement_wrapper * wrapper = static_cast(st); - if (position_check_failed(*wrapper, - statement_wrapper::single, position, dt_blob, "blob") || - not_null_check_failed(*wrapper, position)) + if (position < 0 || position >= wrapper->next_position) { - return NULL; - } + wrapper->is_ok = false; + wrapper->error_message = "Invalid position."; + return 0; + } + + wrapper->is_ok = true; + return wrapper->into_indicators[position] == i_ok ? 1 : 0; +} + +SOCI_DECL char const * soci_get_into_string(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_string, "string") || + not_null_check_failed(*wrapper, position)) + { + return ""; + } + + return wrapper->into_strings[position].c_str(); +} + +SOCI_DECL int soci_get_into_int(statement_handle st, int position) +{ + return static_cast(soci_get_into_int32(st, position)); +} + +SOCI_DECL long long soci_get_into_long_long(statement_handle st, int position) +{ + return static_cast(soci_get_into_int64(st, position)); +} + +SOCI_DECL int8_t soci_get_into_int8(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_int8, "int8") || + not_null_check_failed(*wrapper, position)) + { + return 0; + } + + return wrapper->into_int8[position]; +} + +SOCI_DECL uint8_t soci_get_into_uint8(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_uint8, "uint8") || + not_null_check_failed(*wrapper, position)) + { + return 0; + } + + return wrapper->into_uint8[position]; +} + +SOCI_DECL int16_t soci_get_into_int16(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_int16, "int16") || + not_null_check_failed(*wrapper, position)) + { + return 0; + } + + return wrapper->into_int16[position]; +} + +SOCI_DECL uint16_t soci_get_into_uint16(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_uint16, "uint16") || + not_null_check_failed(*wrapper, position)) + { + return 0; + } + + return wrapper->into_uint16[position]; +} + +SOCI_DECL int32_t soci_get_into_int32(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_int32, "int32") || + not_null_check_failed(*wrapper, position)) + { + return 0; + } + + return wrapper->into_int32[position]; +} + +SOCI_DECL uint32_t soci_get_into_uint32(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_uint32, "uint32") || + not_null_check_failed(*wrapper, position)) + { + return 0; + } + + return wrapper->into_uint32[position]; +} + +SOCI_DECL int64_t soci_get_into_int64(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_int64, "int64") || + not_null_check_failed(*wrapper, position)) + { + return 0LL; + } + + return wrapper->into_int64[position]; +} + +SOCI_DECL uint64_t soci_get_into_uint64(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_uint64, "uint64") || + not_null_check_failed(*wrapper, position)) + { + return 0LL; + } + + return wrapper->into_uint64[position]; +} + +SOCI_DECL double soci_get_into_double(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_double, "double") || + not_null_check_failed(*wrapper, position)) + { + return 0.0; + } + + return wrapper->into_doubles[position]; +} + +SOCI_DECL char const * soci_get_into_date(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_date, "date") || + not_null_check_failed(*wrapper, position)) + { + return ""; + } + + // format is: "YYYY MM DD hh mm ss" + std::tm const & d = wrapper->into_dates[position]; + return format_date(*wrapper, d); +} + +SOCI_DECL blob_handle soci_get_into_blob(statement_handle st, int position) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::single, position, db_blob, "blob") || + not_null_check_failed(*wrapper, position)) + { + return NULL; + } return wrapper->into_blob[position]; } @@ -1130,24 +1591,41 @@ SOCI_DECL void soci_into_resize_v(statement_handle st, int new_size) switch (wrapper->into_types[i]) { - case dt_string: + case db_string: wrapper->into_strings_v[i].resize(new_size); break; - case dt_integer: - wrapper->into_ints_v[i].resize(new_size); + case db_int8: + wrapper->into_int8_v[i].resize(new_size); + break; + case db_uint8: + wrapper->into_uint8_v[i].resize(new_size); + break; + case db_int16: + wrapper->into_int16_v[i].resize(new_size); break; - case dt_long_long: - case dt_unsigned_long_long: - wrapper->into_longlongs_v[i].resize(new_size); + case db_uint16: + wrapper->into_uint16_v[i].resize(new_size); break; - case dt_double: + case db_int32: + wrapper->into_int32_v[i].resize(new_size); + break; + case db_uint32: + wrapper->into_uint32_v[i].resize(new_size); + break; + case db_int64: + wrapper->into_int64_v[i].resize(new_size); + break; + case db_uint64: + wrapper->into_uint64_v[i].resize(new_size); + break; + case db_double: wrapper->into_doubles_v[i].resize(new_size); break; - case dt_date: + case db_date: wrapper->into_dates_v[i].resize(new_size); break; - case dt_blob: - case dt_xml: + case db_blob: + case db_xml: // no support for bulk blob break; } @@ -1181,7 +1659,7 @@ SOCI_DECL char const * soci_get_into_string_v(statement_handle st, int position, statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_string, "string")) + statement_wrapper::bulk, position, db_string, "string")) { return ""; } @@ -1197,16 +1675,26 @@ SOCI_DECL char const * soci_get_into_string_v(statement_handle st, int position, } SOCI_DECL int soci_get_into_int_v(statement_handle st, int position, int index) +{ + return static_cast(soci_get_into_int32_v(st, position, index)); +} + +SOCI_DECL long long soci_get_into_long_long_v(statement_handle st, int position, int index) +{ + return static_cast(soci_get_into_int64_v(st, position, index)); +} + +SOCI_DECL int8_t soci_get_into_int8_v(statement_handle st, int position, int index) { statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_integer, "int")) + statement_wrapper::bulk, position, db_int8, "int8")) { return 0; } - std::vector const & v = wrapper->into_ints_v[position]; + std::vector const & v = wrapper->into_int8_v[position]; if (index_check_failed(v, *wrapper, index) || not_null_check_failed(*wrapper, position, index)) { @@ -1216,17 +1704,137 @@ SOCI_DECL int soci_get_into_int_v(statement_handle st, int position, int index) return v[index]; } -SOCI_DECL long long soci_get_into_long_long_v(statement_handle st, int position, int index) +SOCI_DECL uint8_t soci_get_into_uint8_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, db_uint8, "uint8")) + { + return 0; + } + + std::vector const & v = wrapper->into_uint8_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL int16_t soci_get_into_int16_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, db_int16, "int16")) + { + return 0; + } + + std::vector const & v = wrapper->into_int16_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL uint16_t soci_get_into_uint16_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, db_uint16, "uint16")) + { + return 0; + } + + std::vector const & v = wrapper->into_uint16_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL int32_t soci_get_into_int32_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, db_int32, "int32")) + { + return 0; + } + + std::vector const & v = wrapper->into_int32_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL uint32_t soci_get_into_uint32_v(statement_handle st, int position, int index) { statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_long_long, "long long")) + statement_wrapper::bulk, position, db_uint32, "uint32")) { return 0; } - std::vector const & v = wrapper->into_longlongs_v[position]; + std::vector const & v = wrapper->into_uint32_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL int64_t soci_get_into_int64_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, db_int64, "int64")) + { + return 0; + } + + std::vector const & v = wrapper->into_int64_v[position]; + if (index_check_failed(v, *wrapper, index) || + not_null_check_failed(*wrapper, position, index)) + { + return 0; + } + + return v[index]; +} + +SOCI_DECL uint64_t soci_get_into_uint64_v(statement_handle st, int position, int index) +{ + statement_wrapper * wrapper = static_cast(st); + + if (position_check_failed(*wrapper, + statement_wrapper::bulk, position, db_uint64, "uint64")) + { + return 0; + } + + std::vector const & v = wrapper->into_uint64_v[position]; if (index_check_failed(v, *wrapper, index) || not_null_check_failed(*wrapper, position, index)) { @@ -1241,7 +1849,7 @@ SOCI_DECL double soci_get_into_double_v(statement_handle st, int position, int i statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_double, "double")) + statement_wrapper::bulk, position, db_double, "double")) { return 0.0; } @@ -1261,7 +1869,7 @@ SOCI_DECL char const * soci_get_into_date_v(statement_handle st, int position, i statement_wrapper * wrapper = static_cast(st); if (position_check_failed(*wrapper, - statement_wrapper::bulk, position, dt_date, "date")) + statement_wrapper::bulk, position, db_date, "date")) { return ""; } @@ -1294,6 +1902,186 @@ SOCI_DECL void soci_use_string(statement_handle st, char const * name) } SOCI_DECL void soci_use_int(statement_handle st, char const * name) +{ + soci_use_int32(st, name); +} + +SOCI_DECL void soci_use_long_long(statement_handle st, char const * name) +{ + soci_use_int64(st, name); +} + +SOCI_DECL void soci_use_int8(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_int8[name]; // create new entry +} + +SOCI_DECL void soci_use_uint8(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_uint8[name]; // create new entry +} + +SOCI_DECL void soci_use_int16(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_int16[name]; // create new entry +} + +SOCI_DECL void soci_use_uint16(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_uint16[name]; // create new entry +} + +SOCI_DECL void soci_use_int32(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_int32[name]; // create new entry +} + +SOCI_DECL void soci_use_uint32(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_uint32[name]; // create new entry +} + +SOCI_DECL void soci_use_int64(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_int64[name]; // create new entry +} + +SOCI_DECL void soci_use_uint64(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_uint64[name]; // create new entry +} + +SOCI_DECL void soci_use_double(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_doubles[name]; // create new entry +} + +SOCI_DECL void soci_use_date(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || + name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_ok; // create new entry + wrapper->use_dates[name]; // create new entry +} + +SOCI_DECL void soci_use_blob(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1304,81 +2092,125 @@ SOCI_DECL void soci_use_int(statement_handle st, char const * name) } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::single; + wrapper->use_kind = statement_wrapper::single; + + wrapper->use_indicators[name] = i_null; // create new entry + wrapper->use_blob[name] = soci_create_blob_session(wrapper->sql); // create new entry +} + +SOCI_DECL void soci_use_string_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; + + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_strings_v[name]; // create new entry +} + +SOCI_DECL void soci_use_int_v(statement_handle st, char const * name) +{ + soci_use_int32_v(st, name); +} + +SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name) +{ + soci_use_int64_v(st, name); +} + +SOCI_DECL void soci_use_int8_v(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) + { + return; + } + + wrapper->statement_state = statement_wrapper::defining; + wrapper->use_kind = statement_wrapper::bulk; - wrapper->use_indicators[name] = i_ok; // create new entry - wrapper->use_ints[name]; // create new entry + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_int8_v[name]; // create new entry } -SOCI_DECL void soci_use_long_long(statement_handle st, char const * name) +SOCI_DECL void soci_use_uint8_v(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || - name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::single; + wrapper->use_kind = statement_wrapper::bulk; - wrapper->use_indicators[name] = i_ok; // create new entry - wrapper->use_longlongs[name]; // create new entry + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_uint8_v[name]; // create new entry } -SOCI_DECL void soci_use_double(statement_handle st, char const * name) +SOCI_DECL void soci_use_int16_v(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || - name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::single; + wrapper->use_kind = statement_wrapper::bulk; - wrapper->use_indicators[name] = i_ok; // create new entry - wrapper->use_doubles[name]; // create new entry + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_int16_v[name]; // create new entry } -SOCI_DECL void soci_use_date(statement_handle st, char const * name) +SOCI_DECL void soci_use_uint16_v(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || - name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::single; + wrapper->use_kind = statement_wrapper::bulk; - wrapper->use_indicators[name] = i_ok; // create new entry - wrapper->use_dates[name]; // create new entry + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_uint16_v[name]; // create new entry } -SOCI_DECL void soci_use_blob(statement_handle st, char const * name) +SOCI_DECL void soci_use_int32_v(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); - if (cannot_add_elements(*wrapper, statement_wrapper::single, false) || - name_unique_check_failed(*wrapper, statement_wrapper::single, name)) + if (cannot_add_elements(*wrapper, statement_wrapper::bulk, false) || + name_unique_check_failed(*wrapper, statement_wrapper::bulk, name)) { return; } wrapper->statement_state = statement_wrapper::defining; - wrapper->use_kind = statement_wrapper::single; + wrapper->use_kind = statement_wrapper::bulk; - wrapper->use_indicators[name] = i_null; // create new entry - wrapper->use_blob[name] = soci_create_blob_session(wrapper->sql); // create new entry + wrapper->use_indicators_v[name]; // create new entry + wrapper->use_int32_v[name]; // create new entry } -SOCI_DECL void soci_use_string_v(statement_handle st, char const * name) +SOCI_DECL void soci_use_uint32_v(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1392,10 +2224,10 @@ SOCI_DECL void soci_use_string_v(statement_handle st, char const * name) wrapper->use_kind = statement_wrapper::bulk; wrapper->use_indicators_v[name]; // create new entry - wrapper->use_strings_v[name]; // create new entry + wrapper->use_uint32_v[name]; // create new entry } -SOCI_DECL void soci_use_int_v(statement_handle st, char const * name) +SOCI_DECL void soci_use_int64_v(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1409,10 +2241,10 @@ SOCI_DECL void soci_use_int_v(statement_handle st, char const * name) wrapper->use_kind = statement_wrapper::bulk; wrapper->use_indicators_v[name]; // create new entry - wrapper->use_ints_v[name]; // create new entry + wrapper->use_int64_v[name]; // create new entry } -SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name) +SOCI_DECL void soci_use_uint64_v(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); @@ -1426,7 +2258,7 @@ SOCI_DECL void soci_use_long_long_v(statement_handle st, char const * name) wrapper->use_kind = statement_wrapper::bulk; wrapper->use_indicators_v[name]; // create new entry - wrapper->use_longlongs_v[name]; // create new entry + wrapper->use_uint64_v[name]; // create new entry } SOCI_DECL void soci_use_double_v(statement_handle st, char const * name) @@ -1485,7 +2317,7 @@ SOCI_DECL void soci_set_use_string(statement_handle st, char const * name, char statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_string, statement_wrapper::single, "string")) + name, db_string, statement_wrapper::single, "string")) { return; } @@ -1494,32 +2326,126 @@ SOCI_DECL void soci_set_use_string(statement_handle st, char const * name, char wrapper->use_strings[name] = val; } -SOCI_DECL void soci_set_use_int(statement_handle st, char const * name, int val) +SOCI_DECL void soci_set_use_int(statement_handle st, char const * name, int32_t val) +{ + soci_set_use_int32(st, name, static_cast(val)); +} + +SOCI_DECL void soci_set_use_long_long(statement_handle st, char const * name, long long val) +{ + soci_set_use_int64(st, name, static_cast(val)); +} + +SOCI_DECL void soci_set_use_int8(statement_handle st, char const * name, int8_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_integer, statement_wrapper::single, "int")) + name, db_int8, statement_wrapper::single, "int8")) { return; } wrapper->use_indicators[name] = i_ok; - wrapper->use_ints[name] = val; + wrapper->use_int8[name] = val; } -SOCI_DECL void soci_set_use_long_long(statement_handle st, char const * name, long long val) +SOCI_DECL void soci_set_use_uint8(statement_handle st, char const * name, uint32_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_uint32, statement_wrapper::single, "uint32")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_uint32[name] = val; +} + +SOCI_DECL void soci_set_use_int16(statement_handle st, char const * name, int16_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_int16, statement_wrapper::single, "int16")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_int16[name] = val; +} + +SOCI_DECL void soci_set_use_uint16(statement_handle st, char const * name, uint16_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_uint16, statement_wrapper::single, "uint16")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_uint16[name] = val; +} + +SOCI_DECL void soci_set_use_int32(statement_handle st, char const * name, int32_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_int32, statement_wrapper::single, "int32")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_int32[name] = val; +} + +SOCI_DECL void soci_set_use_uint32(statement_handle st, char const * name, uint32_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_uint32, statement_wrapper::single, "uint32")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_uint32[name] = val; +} + +SOCI_DECL void soci_set_use_int64(statement_handle st, char const * name, int64_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_int64, statement_wrapper::single, "int64")) + { + return; + } + + wrapper->use_indicators[name] = i_ok; + wrapper->use_int64[name] = val; +} + +SOCI_DECL void soci_set_use_uint64(statement_handle st, char const * name, uint64_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_long_long, statement_wrapper::single, "long long")) + name, db_uint64, statement_wrapper::single, "uint64")) { return; } wrapper->use_indicators[name] = i_ok; - wrapper->use_longlongs[name] = val; + wrapper->use_uint64[name] = val; } SOCI_DECL void soci_set_use_double(statement_handle st, char const * name, double val) @@ -1527,7 +2453,7 @@ SOCI_DECL void soci_set_use_double(statement_handle st, char const * name, doubl statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_double, statement_wrapper::single, "double")) + name, db_double, statement_wrapper::single, "double")) { return; } @@ -1541,7 +2467,7 @@ SOCI_DECL void soci_set_use_date(statement_handle st, char const * name, char co statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_date, statement_wrapper::single, "date")) + name, db_date, statement_wrapper::single, "date")) { return; } @@ -1562,7 +2488,7 @@ SOCI_DECL void soci_set_use_blob(statement_handle st, char const * name, blob_ha statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_blob, statement_wrapper::single, "blob")) + name, db_blob, statement_wrapper::single, "blob")) { return; } @@ -1572,94 +2498,238 @@ SOCI_DECL void soci_set_use_blob(statement_handle st, char const * name, blob_ha if (ind == i_null && blob != NULL) soci_destroy_blob(blob); - ind = i_ok; - blob = static_cast(b); + ind = i_ok; + blob = static_cast(b); +} + +SOCI_DECL int soci_use_get_size_v(statement_handle st) +{ + statement_wrapper * wrapper = static_cast(st); + + if (wrapper->use_kind != statement_wrapper::bulk) + { + wrapper->is_ok = false; + wrapper->error_message = "No vector use elements."; + return -1; + } + + if (wrapper->use_indicators_v.empty()) + { + wrapper->is_ok = false; + wrapper->error_message = "Empty indicators vector."; + return -1; + } + + return static_cast(wrapper->use_indicators_v.begin()->second.size()); +} + +SOCI_DECL void soci_use_resize_v(statement_handle st, int new_size) +{ + statement_wrapper * wrapper = static_cast(st); + + if (new_size <= 0) + { + wrapper->is_ok = false; + wrapper->error_message = "Invalid size."; + return; + } + + if (wrapper->use_kind != statement_wrapper::bulk) + { + wrapper->is_ok = false; + wrapper->error_message = "No vector use elements."; + return; + } + + resize_in_map(wrapper->use_indicators_v, new_size); + resize_in_map(wrapper->use_strings_v, new_size); + resize_in_map(wrapper->use_int8_v, new_size); + resize_in_map(wrapper->use_uint8_v, new_size); + resize_in_map(wrapper->use_int16_v, new_size); + resize_in_map(wrapper->use_uint16_v, new_size); + resize_in_map(wrapper->use_int32_v, new_size); + resize_in_map(wrapper->use_uint32_v, new_size); + resize_in_map(wrapper->use_int64_v, new_size); + resize_in_map(wrapper->use_uint64_v, new_size); + resize_in_map(wrapper->use_doubles_v, new_size); + resize_in_map(wrapper->use_dates_v, new_size); + + wrapper->is_ok = true; +} + +SOCI_DECL void soci_set_use_state_v(statement_handle st, + char const * name, int index, int state) +{ + statement_wrapper * wrapper = static_cast(st); + + typedef std::map >::iterator iterator; + iterator const it = wrapper->use_indicators_v.find(name); + if (it == wrapper->use_indicators_v.end()) + { + wrapper->is_ok = false; + wrapper->error_message = "Invalid name."; + return; + } + + std::vector & v = it->second; + if (index_check_failed(v, *wrapper, index)) + { + return; + } + + v[index] = (state != 0 ? i_ok : i_null); +} + +SOCI_DECL void soci_set_use_string_v(statement_handle st, + char const * name, int index, char const * val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_string, statement_wrapper::bulk, "vector string")) + { + return; + } + + std::vector & v = wrapper->use_strings_v[name]; + if (index_check_failed(v, *wrapper, index)) + { + return; + } + + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; +} + +SOCI_DECL void soci_set_use_int_v(statement_handle st, + char const * name, int index, int val) +{ + soci_set_use_int32_v(st, name, index, static_cast(val)); +} + +SOCI_DECL void soci_set_use_long_long_v(statement_handle st, + char const * name, int index, long long val) +{ + soci_set_use_int64_v(st, name, index, static_cast(val)); +} + +SOCI_DECL void soci_set_use_int8_v(statement_handle st, + char const * name, int index, int8_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_int8, statement_wrapper::bulk, "vector int8")) + { + return; + } + + std::vector & v = wrapper->use_int8_v[name]; + if (index_check_failed(v, *wrapper, index)) + { + return; + } + + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; +} + +SOCI_DECL void soci_set_use_uint8_v(statement_handle st, + char const * name, int index, uint8_t val) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_uint8, statement_wrapper::bulk, "vector uint8")) + { + return; + } + + std::vector & v = wrapper->use_uint8_v[name]; + if (index_check_failed(v, *wrapper, index)) + { + return; + } + + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; } -SOCI_DECL int soci_use_get_size_v(statement_handle st) +SOCI_DECL void soci_set_use_int16_v(statement_handle st, + char const * name, int index, int16_t val) { statement_wrapper * wrapper = static_cast(st); - if (wrapper->use_kind != statement_wrapper::bulk) + if (name_exists_check_failed(*wrapper, + name, db_int16, statement_wrapper::bulk, "vector int16")) { - wrapper->is_ok = false; - wrapper->error_message = "No vector use elements."; - return -1; + return; } - if (wrapper->use_indicators_v.empty()) + std::vector & v = wrapper->use_int16_v[name]; + if (index_check_failed(v, *wrapper, index)) { - wrapper->is_ok = false; - wrapper->error_message = "Empty indicators vector."; - return -1; + return; } - return static_cast(wrapper->use_indicators_v.begin()->second.size()); + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; } -SOCI_DECL void soci_use_resize_v(statement_handle st, int new_size) +SOCI_DECL void soci_set_use_uint16_v(statement_handle st, + char const * name, int index, uint16_t val) { statement_wrapper * wrapper = static_cast(st); - if (new_size <= 0) + if (name_exists_check_failed(*wrapper, + name, db_uint16, statement_wrapper::bulk, "vector uint16")) { - wrapper->is_ok = false; - wrapper->error_message = "Invalid size."; return; } - if (wrapper->use_kind != statement_wrapper::bulk) + std::vector & v = wrapper->use_uint16_v[name]; + if (index_check_failed(v, *wrapper, index)) { - wrapper->is_ok = false; - wrapper->error_message = "No vector use elements."; return; } - resize_in_map(wrapper->use_indicators_v, new_size); - resize_in_map(wrapper->use_strings_v, new_size); - resize_in_map(wrapper->use_ints_v, new_size); - resize_in_map(wrapper->use_longlongs_v, new_size); - resize_in_map(wrapper->use_doubles_v, new_size); - resize_in_map(wrapper->use_dates_v, new_size); - - wrapper->is_ok = true; + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; } -SOCI_DECL void soci_set_use_state_v(statement_handle st, - char const * name, int index, int state) +SOCI_DECL void soci_set_use_int32_v(statement_handle st, + char const * name, int index, int32_t val) { statement_wrapper * wrapper = static_cast(st); - typedef std::map >::iterator iterator; - iterator const it = wrapper->use_indicators_v.find(name); - if (it == wrapper->use_indicators_v.end()) + if (name_exists_check_failed(*wrapper, + name, db_int32, statement_wrapper::bulk, "vector int32")) { - wrapper->is_ok = false; - wrapper->error_message = "Invalid name."; return; } - std::vector & v = it->second; + std::vector & v = wrapper->use_int32_v[name]; if (index_check_failed(v, *wrapper, index)) { return; } - v[index] = (state != 0 ? i_ok : i_null); + wrapper->use_indicators_v[name][index] = i_ok; + v[index] = val; } -SOCI_DECL void soci_set_use_string_v(statement_handle st, - char const * name, int index, char const * val) +SOCI_DECL void soci_set_use_uint32_v(statement_handle st, + char const * name, int index, uint32_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_string, statement_wrapper::bulk, "vector string")) + name, db_uint32, statement_wrapper::bulk, "vector uint32")) { return; } - std::vector & v = wrapper->use_strings_v[name]; + std::vector & v = wrapper->use_uint32_v[name]; if (index_check_failed(v, *wrapper, index)) { return; @@ -1669,18 +2739,18 @@ SOCI_DECL void soci_set_use_string_v(statement_handle st, v[index] = val; } -SOCI_DECL void soci_set_use_int_v(statement_handle st, - char const * name, int index, int val) +SOCI_DECL void soci_set_use_int64_v(statement_handle st, + char const * name, int index, int64_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_integer, statement_wrapper::bulk, "vector int")) + name, db_int64, statement_wrapper::bulk, "vector int64")) { return; } - std::vector & v = wrapper->use_ints_v[name]; + std::vector & v = wrapper->use_int64_v[name]; if (index_check_failed(v, *wrapper, index)) { return; @@ -1690,18 +2760,18 @@ SOCI_DECL void soci_set_use_int_v(statement_handle st, v[index] = val; } -SOCI_DECL void soci_set_use_long_long_v(statement_handle st, - char const * name, int index, long long val) +SOCI_DECL void soci_set_use_uint64_v(statement_handle st, + char const * name, int index, uint64_t val) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_long_long, statement_wrapper::bulk, "vector long long")) + name, db_uint64, statement_wrapper::bulk, "vector uint64")) { return; } - std::vector & v = wrapper->use_longlongs_v[name]; + std::vector & v = wrapper->use_uint64_v[name]; if (index_check_failed(v, *wrapper, index)) { return; @@ -1717,7 +2787,7 @@ SOCI_DECL void soci_set_use_double_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_double, statement_wrapper::bulk, "vector double")) + name, db_double, statement_wrapper::bulk, "vector double")) { return; } @@ -1738,7 +2808,7 @@ SOCI_DECL void soci_set_use_date_v(statement_handle st, statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_date, statement_wrapper::bulk, "vector date")) + name, db_date, statement_wrapper::bulk, "vector date")) { return; } @@ -1782,7 +2852,7 @@ SOCI_DECL char const * soci_get_use_string(statement_handle st, char const * nam statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_string, statement_wrapper::bulk, "string")) + name, db_string, statement_wrapper::bulk, "string")) { return ""; } @@ -1791,29 +2861,117 @@ SOCI_DECL char const * soci_get_use_string(statement_handle st, char const * nam } SOCI_DECL int soci_get_use_int(statement_handle st, char const * name) +{ + return static_cast(soci_get_use_int32(st, name)); +} + +SOCI_DECL long long soci_get_use_long_long(statement_handle st, char const * name) +{ + return static_cast(soci_get_use_int64(st, name)); +} + +SOCI_DECL int8_t soci_get_use_int8(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_integer, statement_wrapper::bulk, "int")) + name, db_int8, statement_wrapper::bulk, "int8")) { return 0; } - return wrapper->use_ints[name]; + return wrapper->use_int8[name]; } -SOCI_DECL long long soci_get_use_long_long(statement_handle st, char const * name) +SOCI_DECL uint8_t soci_get_use_uint8(statement_handle st, char const * name) { statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_long_long, statement_wrapper::bulk, "long long")) + name, db_uint8, statement_wrapper::bulk, "uint8")) + { + return 0; + } + + return wrapper->use_uint8[name]; +} + +SOCI_DECL int16_t soci_get_use_int16(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_int16, statement_wrapper::bulk, "int16")) + { + return 0; + } + + return wrapper->use_int16[name]; +} + +SOCI_DECL uint16_t soci_get_use_uint16(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_uint16, statement_wrapper::bulk, "uint16")) + { + return 0; + } + + return wrapper->use_uint16[name]; +} + +SOCI_DECL int32_t soci_get_use_int32(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_int32, statement_wrapper::bulk, "int32")) + { + return 0; + } + + return wrapper->use_int32[name]; +} + +SOCI_DECL uint32_t soci_get_use_uint32(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_uint32, statement_wrapper::bulk, "uint32")) + { + return 0; + } + + return wrapper->use_uint32[name]; +} + +SOCI_DECL int64_t soci_get_use_int64(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_int64, statement_wrapper::bulk, "int64")) + { + return 0LL; + } + + return wrapper->use_int64[name]; +} + +SOCI_DECL uint64_t soci_get_use_uint64(statement_handle st, char const * name) +{ + statement_wrapper * wrapper = static_cast(st); + + if (name_exists_check_failed(*wrapper, + name, db_uint64, statement_wrapper::bulk, "uint64")) { return 0LL; } - return wrapper->use_longlongs[name]; + return wrapper->use_uint64[name]; } SOCI_DECL double soci_get_use_double(statement_handle st, char const * name) @@ -1821,7 +2979,7 @@ SOCI_DECL double soci_get_use_double(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_double, statement_wrapper::bulk, "double")) + name, db_double, statement_wrapper::bulk, "double")) { return 0.0; } @@ -1834,7 +2992,7 @@ SOCI_DECL char const * soci_get_use_date(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_date, statement_wrapper::bulk, "date")) + name, db_date, statement_wrapper::bulk, "date")) { return ""; } @@ -1853,7 +3011,7 @@ SOCI_DECL blob_handle soci_get_use_blob(statement_handle st, char const * name) statement_wrapper * wrapper = static_cast(st); if (name_exists_check_failed(*wrapper, - name, dt_blob, statement_wrapper::bulk, "blob")) + name, db_blob, statement_wrapper::bulk, "blob")) { return NULL; } @@ -1878,32 +3036,55 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) { switch (wrapper->into_types[i]) { - case dt_string: + case db_string: wrapper->st.exchange( into(wrapper->into_strings[i], wrapper->into_indicators[i])); break; - case dt_integer: + case db_int8: + wrapper->st.exchange( + into(wrapper->into_int8[i], wrapper->into_indicators[i])); + break; + case db_uint8: + wrapper->st.exchange( + into(wrapper->into_uint8[i], wrapper->into_indicators[i])); + break; + case db_int16: wrapper->st.exchange( - into(wrapper->into_ints[i], wrapper->into_indicators[i])); + into(wrapper->into_int16[i], wrapper->into_indicators[i])); break; - case dt_long_long: - case dt_unsigned_long_long: + case db_uint16: wrapper->st.exchange( - into(wrapper->into_longlongs[i], wrapper->into_indicators[i])); + into(wrapper->into_uint16[i], wrapper->into_indicators[i])); break; - case dt_double: + case db_int32: + wrapper->st.exchange( + into(wrapper->into_int32[i], wrapper->into_indicators[i])); + break; + case db_uint32: + wrapper->st.exchange( + into(wrapper->into_uint32[i], wrapper->into_indicators[i])); + break; + case db_int64: + wrapper->st.exchange( + into(wrapper->into_int64[i], wrapper->into_indicators[i])); + break; + case db_uint64: + wrapper->st.exchange( + into(wrapper->into_uint64[i], wrapper->into_indicators[i])); + break; + case db_double: wrapper->st.exchange( into(wrapper->into_doubles[i], wrapper->into_indicators[i])); break; - case dt_date: + case db_date: wrapper->st.exchange( into(wrapper->into_dates[i], wrapper->into_indicators[i])); break; - case dt_blob: + case db_blob: wrapper->st.exchange( into(wrapper->into_blob[i]->blob_, wrapper->into_indicators[i])); break; - case dt_xml: + case db_xml: // no support for xml break; } @@ -1916,29 +3097,52 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) { switch (wrapper->into_types[i]) { - case dt_string: + case db_string: wrapper->st.exchange( into(wrapper->into_strings_v[i], wrapper->into_indicators_v[i])); break; - case dt_integer: + case db_int8: + wrapper->st.exchange( + into(wrapper->into_int8_v[i], wrapper->into_indicators_v[i])); + break; + case db_uint8: + wrapper->st.exchange( + into(wrapper->into_uint8_v[i], wrapper->into_indicators_v[i])); + break; + case db_int16: + wrapper->st.exchange( + into(wrapper->into_int16_v[i], wrapper->into_indicators_v[i])); + break; + case db_uint16: + wrapper->st.exchange( + into(wrapper->into_uint16_v[i], wrapper->into_indicators_v[i])); + break; + case db_int32: wrapper->st.exchange( - into(wrapper->into_ints_v[i], wrapper->into_indicators_v[i])); + into(wrapper->into_int32_v[i], wrapper->into_indicators_v[i])); break; - case dt_long_long: - case dt_unsigned_long_long: + case db_uint32: wrapper->st.exchange( - into(wrapper->into_longlongs_v[i], wrapper->into_indicators_v[i])); + into(wrapper->into_uint32_v[i], wrapper->into_indicators_v[i])); break; - case dt_double: + case db_int64: + wrapper->st.exchange( + into(wrapper->into_int64_v[i], wrapper->into_indicators_v[i])); + break; + case db_uint64: + wrapper->st.exchange( + into(wrapper->into_uint64_v[i], wrapper->into_indicators_v[i])); + break; + case db_double: wrapper->st.exchange( into(wrapper->into_doubles_v[i], wrapper->into_indicators_v[i])); break; - case dt_date: + case db_date: wrapper->st.exchange( into(wrapper->into_dates_v[i], wrapper->into_indicators_v[i])); break; - case dt_blob: - case dt_xml: + case db_blob: + case db_xml: // no support for bulk blob and xml break; } @@ -1960,27 +3164,105 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) } } { - // ints - typedef std::map::iterator iterator; - iterator uit = wrapper->use_ints.begin(); - iterator const uend = wrapper->use_ints.end(); + // int8 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_int8.begin(); + iterator const uend = wrapper->use_int8.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + int8_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint8 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_uint8.begin(); + iterator const uend = wrapper->use_uint8.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + uint8_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // int16 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_int16.begin(); + iterator const uend = wrapper->use_int16.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + int16_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint16 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_uint16.begin(); + iterator const uend = wrapper->use_uint16.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + uint16_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // int32 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_int32.begin(); + iterator const uend = wrapper->use_int32.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + int32_t & use_int = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint32 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_uint32.begin(); + iterator const uend = wrapper->use_uint32.end(); for ( ; uit != uend; ++uit) { std::string const & use_name = uit->first; - int & use_int = uit->second; + uint32_t & use_int = uit->second; indicator & use_ind = wrapper->use_indicators[use_name]; wrapper->st.exchange(use(use_int, use_ind, use_name)); } } { - // longlongs - typedef std::map::iterator iterator; - iterator uit = wrapper->use_longlongs.begin(); - iterator const uend = wrapper->use_longlongs.end(); + // int64 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_int64.begin(); + iterator const uend = wrapper->use_int64.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + int64_t & use_longlong = uit->second; + indicator & use_ind = wrapper->use_indicators[use_name]; + wrapper->st.exchange(use(use_longlong, use_ind, use_name)); + } + } + { + // uint64 + typedef std::map::iterator iterator; + iterator uit = wrapper->use_uint64.begin(); + iterator const uend = wrapper->use_uint64.end(); for ( ; uit != uend; ++uit) { std::string const & use_name = uit->first; - long long & use_longlong = uit->second; + uint64_t & use_longlong = uit->second; indicator & use_ind = wrapper->use_indicators[use_name]; wrapper->st.exchange(use(use_longlong, use_ind, use_name)); } @@ -2025,7 +3307,7 @@ SOCI_DECL void soci_prepare(statement_handle st, char const * query) } } - // bind all use vecctor elements + // bind all use vector elements { // strings typedef std::map >::iterator iterator; + iterator uit = wrapper->use_int8_v.begin(); + iterator const uend = wrapper->use_int8_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint8 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_uint8_v.begin(); + iterator const uend = wrapper->use_uint8_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // int16 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_int16_v.begin(); + iterator const uend = wrapper->use_int16_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint16 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_uint16_v.begin(); + iterator const uend = wrapper->use_uint16_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // int32 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_int32_v.begin(); + iterator const uend = wrapper->use_int32_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_int = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_int, use_ind, use_name)); + } + } + { + // uint32 typedef std::map >::iterator iterator; - iterator uit = wrapper->use_ints_v.begin(); - iterator const uend = wrapper->use_ints_v.end(); + std::vector >::iterator iterator; + iterator uit = wrapper->use_uint32_v.begin(); + iterator const uend = wrapper->use_uint32_v.end(); for ( ; uit != uend; ++uit) { std::string const & use_name = uit->first; - std::vector & use_int = uit->second; + std::vector & use_int = uit->second; std::vector & use_ind = wrapper->use_indicators_v[use_name]; wrapper->st.exchange(use(use_int, use_ind, use_name)); } } { - // longlongs + // int64 + typedef std::map >::iterator iterator; + iterator uit = wrapper->use_int64_v.begin(); + iterator const uend = wrapper->use_int64_v.end(); + for ( ; uit != uend; ++uit) + { + std::string const & use_name = uit->first; + std::vector & use_longlong = uit->second; + std::vector & use_ind = + wrapper->use_indicators_v[use_name]; + wrapper->st.exchange(use(use_longlong, use_ind, use_name)); + } + } + { + // uint64 typedef std::map >::iterator iterator; - iterator uit = wrapper->use_longlongs_v.begin(); - iterator const uend = wrapper->use_longlongs_v.end(); + std::vector >::iterator iterator; + iterator uit = wrapper->use_uint64_v.begin(); + iterator const uend = wrapper->use_uint64_v.end(); for ( ; uit != uend; ++uit) { std::string const & use_name = uit->first; - std::vector & use_longlong = uit->second; + std::vector & use_longlong = uit->second; std::vector & use_ind = wrapper->use_indicators_v[use_name]; wrapper->st.exchange(use(use_longlong, use_ind, use_name)); diff --git a/src/core/statement.cpp b/src/core/statement.cpp index 4bf9f0e79..f5a7000f6 100644 --- a/src/core/statement.cpp +++ b/src/core/statement.cpp @@ -14,6 +14,7 @@ #include "soci-compiler.h" #include #include +#include using namespace soci; using namespace soci::details; @@ -629,37 +630,67 @@ namespace details // Map data_types to stock types for dynamic result set support template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { - into_row(); + into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { - into_row(); + into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() { - into_row(); + into_row(); } template<> -void statement_impl::bind_into() +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() +{ + into_row(); +} + +template<> +void statement_impl::bind_into() { into_row(); } @@ -672,39 +703,52 @@ void statement_impl::describe() for (int i = 1; i <= numcols; ++i) { data_type dtype; + db_type dbtype; std::string columnName; - backEnd_->describe_column(i, dtype, columnName); + backEnd_->describe_column(i, dtype, dbtype, columnName); column_properties props; props.set_name(columnName); props.set_data_type(dtype); + props.set_db_type(dbtype); - switch (dtype) + switch (dbtype) { - case dt_string: - bind_into(); + case db_string: + case db_blob: + case db_xml: + bind_into(); + break; + case db_double: + bind_into(); + break; + case db_int8: + bind_into(); + break; + case db_uint8: + bind_into(); break; - case dt_blob: - bind_into(); + case db_int16: + bind_into(); break; - case dt_xml: - bind_into(); + case db_uint16: + bind_into(); break; - case dt_double: - bind_into(); + case db_int32: + bind_into(); break; - case dt_integer: - bind_into(); + case db_uint32: + bind_into(); break; - case dt_long_long: - bind_into(); + case db_int64: + bind_into(); break; - case dt_unsigned_long_long: - bind_into(); + case db_uint64: + bind_into(); break; - case dt_date: - bind_into(); + case db_date: + bind_into(); break; default: std::ostringstream msg; diff --git a/src/core/use-type.cpp b/src/core/use-type.cpp index b865f74f4..26d165dc5 100644 --- a/src/core/use-type.cpp +++ b/src/core/use-type.cpp @@ -57,20 +57,36 @@ void standard_use_type::dump_value(std::ostream& os) const os << "\"" << exchange_type_cast(data_) << "\""; return; - case x_short: - os << exchange_type_cast(data_); + case x_int8: + os << exchange_type_cast(data_); return; - case x_integer: - os << exchange_type_cast(data_); + case x_uint8: + os << exchange_type_cast(data_); return; - case x_long_long: - os << exchange_type_cast(data_); + case x_int16: + os << exchange_type_cast(data_); return; - case x_unsigned_long_long: - os << exchange_type_cast(data_); + case x_uint16: + os << exchange_type_cast(data_); + return; + + case x_int32: + os << exchange_type_cast(data_); + return; + + case x_uint32: + os << exchange_type_cast(data_); + return; + + case x_int64: + os << exchange_type_cast(data_); + return; + + case x_uint64: + os << exchange_type_cast(data_); return; case x_double: diff --git a/tests/common-tests.h b/tests/common-tests.h index ee791d591..714b274ee 100644 --- a/tests/common-tests.h +++ b/tests/common-tests.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -465,6 +466,14 @@ class test_context_base // strings (Oracle does this). virtual bool treats_empty_strings_as_null() const { return false; } + // Override this if the backend does not store values bigger than INT64_MAX + // correctly. This can lead to an unexpected ordering of values as larger + // values might be stored as overflown and therefore negative integer. + virtual bool has_uint64_storage_bug() const { return false; } + + // Override this if the backend truncates integer values bigger than INT64_MAX. + virtual bool truncates_uint64_to_int64() const { return false; } + // Override this to call commit() if it's necessary for the DDL statements // to be taken into account (currently this is only the case for Firebird). virtual void on_after_ddl(session&) const { } @@ -1512,6 +1521,68 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(str == "Hello SOCI!"); } + SECTION("int8_t") + { + int8_t i = 123; + sql << "insert into soci_test(id) values(:id)", use(i); + + int8_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == 123); + + sql << "delete from soci_test"; + + i = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(i); + + i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::min)()); + + sql << "delete from soci_test"; + + i = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(i); + + i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::max)()); + } + + SECTION("uint8_t") + { + uint8_t ui = 123; + sql << "insert into soci_test(id) values(:id)", use(ui); + + uint8_t ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == 123); + + sql << "delete from soci_test"; + + ui = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(ui); + + ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == (std::numeric_limits::min)()); + + sql << "delete from soci_test"; + + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(ui); + + ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == (std::numeric_limits::max)()); + } + SECTION("short") { short s = 123; @@ -1523,6 +1594,68 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(s2 == 123); } + SECTION("int16_t") + { + int16_t i = 123; + sql << "insert into soci_test(id) values(:id)", use(i); + + int16_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == 123); + + sql << "delete from soci_test"; + + i = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(i); + + i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::min)()); + + sql << "delete from soci_test"; + + i = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(i); + + i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::max)()); + } + + SECTION("uint16_t") + { + uint16_t ui = 123; + sql << "insert into soci_test(id) values(:id)", use(ui); + + uint16_t ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == 123); + + sql << "delete from soci_test"; + + ui = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:id)", use(ui); + + ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == (std::numeric_limits::min)()); + + sql << "delete from soci_test"; + + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:id)", use(ui); + + ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == (std::numeric_limits::max)()); + } + SECTION("int") { int i = -12345678; @@ -1534,6 +1667,68 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(i2 == -12345678); } + SECTION("int32_t") + { + int32_t i = -12345678; + sql << "insert into soci_test(id) values(:i)", use(i); + + int32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == -12345678); + + sql << "delete from soci_test"; + + i = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:i)", use(i); + + i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::min)()); + + sql << "delete from soci_test"; + + i = (std::numeric_limits::max)(); + sql << "insert into soci_test(id) values(:i)", use(i); + + i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::max)()); + } + + SECTION("uint32_t") + { + uint32_t ui = 12345678; + sql << "insert into soci_test(id) values(:i)", use(ui); + + uint32_t ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == 12345678); + + sql << "delete from soci_test"; + + ui = (std::numeric_limits::min)(); + sql << "insert into soci_test(id) values(:i)", use(ui); + + ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == (std::numeric_limits::min)()); + + sql << "delete from soci_test"; + + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(ul) values(:i)", use(ui); + + ui2 = 0; + sql << "select ul from soci_test", into(ui2); + + CHECK(ui2 == (std::numeric_limits::max)()); + } + SECTION("unsigned long") { unsigned long ul = 4000000000ul; @@ -1545,6 +1740,75 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(ul2 == 4000000000ul); } + SECTION("int64_t") + { + int64_t i = 4000000000ll; + sql << "insert into soci_test(ll) values(:num)", use(i); + + int64_t i2 = 0; + sql << "select ll from soci_test", into(i2); + + CHECK(i2 == 4000000000ll); + + sql << "delete from soci_test"; + + i = (std::numeric_limits::min)(); + sql << "insert into soci_test(ll) values(:num)", use(i); + + i2 = 0; + sql << "select ll from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::min)()); + + sql << "delete from soci_test"; + + i = (std::numeric_limits::max)(); + sql << "insert into soci_test(ll) values(:num)", use(i); + + i2 = 0; + sql << "select ll from soci_test", into(i2); + + CHECK(i2 == (std::numeric_limits::max)()); + } + + SECTION("uint64_t") + { + uint64_t ui = 4000000000ull; + sql << "insert into soci_test(ul) values(:num)", use(ui); + + uint64_t ui2 = 0; + sql << "select ul from soci_test", into(ui2); + + CHECK(ui2 == 4000000000ull); + + sql << "delete from soci_test"; + + ui = (std::numeric_limits::min)(); + sql << "insert into soci_test(ul) values(:num)", use(ui); + + ui2 = 0; + sql << "select ul from soci_test", into(ui2); + + CHECK(ui2 == (std::numeric_limits::min)()); + + sql << "delete from soci_test"; + + ui = (std::numeric_limits::max)(); + sql << "insert into soci_test(ul) values(:num)", use(ui); + + ui2 = 0; + sql << "select ul from soci_test", into(ui2); + + if (tc_.truncates_uint64_to_int64()) + { + CHECK(ui2 == static_cast((std::numeric_limits::max)())); + } + else + { + CHECK(ui2 == (std::numeric_limits::max)()); + } + } + SECTION("double") { double d = 3.14159265; @@ -1631,6 +1895,28 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(str == "Hello const SOCI!"); } + SECTION("const int8_t") + { + int8_t const i = 123; + sql << "insert into soci_test(id) values(:id)", use(i); + + int8_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == 123); + } + + SECTION("const uint8_t") + { + uint8_t const ui = 123; + sql << "insert into soci_test(id) values(:id)", use(ui); + + uint8_t ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == 123); + } + SECTION("const short") { short const s = 123; @@ -1642,6 +1928,28 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(s2 == 123); } + SECTION("const int16_t") + { + int16_t const i = 123; + sql << "insert into soci_test(id) values(:id)", use(i); + + int16_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == 123); + } + + SECTION("const uint16_t") + { + uint16_t const ui = 123; + sql << "insert into soci_test(id) values(:id)", use(ui); + + uint16_t ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == 123); + } + SECTION("const int") { int const i = -12345678; @@ -1653,6 +1961,28 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(i2 == -12345678); } + SECTION("const int32_t") + { + int32_t const i = -12345678; + sql << "insert into soci_test(id) values(:i)", use(i); + + int32_t i2 = 0; + sql << "select id from soci_test", into(i2); + + CHECK(i2 == -12345678); + } + + SECTION("const uint32_t") + { + uint32_t const ui = 12345678; + sql << "insert into soci_test(id) values(:i)", use(ui); + + uint32_t ui2 = 0; + sql << "select id from soci_test", into(ui2); + + CHECK(ui2 == 12345678); + } + SECTION("const unsigned long") { unsigned long const ul = 4000000000ul; @@ -1664,6 +1994,28 @@ TEST_CASE_METHOD(common_tests, "Use type conversion", "[core][use]") CHECK(ul2 == 4000000000ul); } + SECTION("const int64_t") + { + int64_t const i = 4000000000ll; + sql << "insert into soci_test(ul) values(:num)", use(i); + + int64_t i2 = 0; + sql << "select ul from soci_test", into(i2); + + CHECK(i2 == 4000000000ll); + } + + SECTION("const uint64_t") + { + uint64_t const ui = 4000000000ull; + sql << "insert into soci_test(ul) values(:num)", use(ui); + + uint64_t ui2 = 0; + sql << "select ul from soci_test", into(ui2); + + CHECK(ui2 == 4000000000ull); + } + SECTION("const double") { double const d = 3.14159265; @@ -1821,6 +2173,46 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[2] == "ma"); } + SECTION("int8_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(-5); + v.push_back(123); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(sh) values(:sh)", use(v); + + std::vector v2(4); + + sql << "select sh from soci_test order by sh", into(v2); + CHECK(v2.size() == 4); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == -5); + CHECK(v2[2] == 123); + CHECK(v2[3] == (std::numeric_limits::max)()); + } + + SECTION("uint8_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(6); + v.push_back(123); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(sh) values(:sh)", use(v); + + std::vector v2(4); + + sql << "select sh from soci_test order by sh", into(v2); + CHECK(v2.size() == 4); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 6); + CHECK(v2[2] == 123); + CHECK(v2[3] == (std::numeric_limits::max)()); + } + SECTION("short") { std::vector v; @@ -1841,6 +2233,46 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[3] == 123); } + SECTION("int16_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(-5); + v.push_back(123); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(sh) values(:sh)", use(v); + + std::vector v2(4); + + sql << "select sh from soci_test order by sh", into(v2); + CHECK(v2.size() == 4); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == -5); + CHECK(v2[2] == 123); + CHECK(v2[3] == (std::numeric_limits::max)()); + } + + SECTION("uint16_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(6); + v.push_back(123); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(val) values(:val)", use(v); + + std::vector v2(4); + + sql << "select val from soci_test order by val", into(v2); + CHECK(v2.size() == 4); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 6); + CHECK(v2[2] == 123); + CHECK(v2[3] == (std::numeric_limits::max)()); + } + SECTION("int") { std::vector v; @@ -1861,6 +2293,30 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[3] == 2000000000); } + SECTION("int32_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(-2000000000); + v.push_back(0); + v.push_back(1); + v.push_back(2000000000); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(id) values(:i)", use(v); + + std::vector v2(6); + + sql << "select id from soci_test order by id", into(v2); + CHECK(v2.size() == 6); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == -2000000000); + CHECK(v2[2] == 0); + CHECK(v2[3] == 1); + CHECK(v2[4] == 2000000000); + CHECK(v2[5] == (std::numeric_limits::max)()); + } + SECTION("unsigned int") { std::vector v; @@ -1881,6 +2337,30 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[3] == 1000); } + SECTION("uint32_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(0); + v.push_back(1); + v.push_back(123); + v.push_back(1000); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(ul) values(:ul)", use(v); + + std::vector v2(6); + + sql << "select ul from soci_test order by ul", into(v2); + CHECK(v2.size() == 6); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 0); + CHECK(v2[2] == 1); + CHECK(v2[3] == 123); + CHECK(v2[4] == 1000); + CHECK(v2[5] == (std::numeric_limits::max)()); + } + SECTION("unsigned long long") { std::vector v; @@ -1901,6 +2381,73 @@ TEST_CASE_METHOD(common_tests, "Use vector", "[core][use][vector]") CHECK(v2[3] == 1000); } + SECTION("int64_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(0); + v.push_back(1); + v.push_back(123); + v.push_back(1000); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(ll) values(:ll)", use(v); + + std::vector v2(6); + + sql << "select ll from soci_test order by ll", into(v2); + CHECK(v2.size() == 6); + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 0); + CHECK(v2[2] == 1); + CHECK(v2[3] == 123); + CHECK(v2[4] == 1000); + CHECK(v2[5] == (std::numeric_limits::max)()); + } + + SECTION("uint64_t") + { + std::vector v; + v.push_back((std::numeric_limits::min)()); + v.push_back(0); + v.push_back(1); + v.push_back(123); + v.push_back(1000); + v.push_back((std::numeric_limits::max)()); + + sql << "insert into soci_test(ul) values(:ul)", use(v); + + std::vector v2(6); + + sql << "select ul from soci_test order by ul", into(v2); + CHECK(v2.size() == 6); + if (tc_.has_uint64_storage_bug()) + { + CHECK(v2[0] == (std::numeric_limits::max)()); + CHECK(v2[1] == (std::numeric_limits::min)()); + CHECK(v2[2] == 0); + CHECK(v2[3] == 1); + CHECK(v2[4] == 123); + CHECK(v2[5] == 1000); + } + else + { + CHECK(v2[0] == (std::numeric_limits::min)()); + CHECK(v2[1] == 0); + CHECK(v2[2] == 1); + CHECK(v2[3] == 123); + CHECK(v2[4] == 1000); + if (tc_.truncates_uint64_to_int64()) + { + CHECK(v2[5] == static_cast((std::numeric_limits::max)())); + } + else + { + CHECK(v2[5] == (std::numeric_limits::max)()); + } + } + } + SECTION("double") { std::vector v; @@ -2389,15 +2936,21 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 5); CHECK(r.get_properties(0).get_data_type() == dt_double); + CHECK(r.get_properties(0).get_db_type() == db_double); CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_db_type() == db_int32); CHECK(r.get_properties(2).get_data_type() == dt_string); + CHECK(r.get_properties(2).get_db_type() == db_string); CHECK(r.get_properties(3).get_data_type() == dt_date); + CHECK(r.get_properties(3).get_db_type() == db_date); // type char is visible as string // - to comply with the implementation for Oracle CHECK(r.get_properties(4).get_data_type() == dt_string); + CHECK(r.get_properties(4).get_db_type() == db_string); CHECK(r.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r.get_properties("NUM_INT").get_db_type() == db_int32); CHECK(r.get_properties(0).get_name() == "NUM_FLOAT"); CHECK(r.get_properties(1).get_name() == "NUM_INT"); @@ -2463,16 +3016,22 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 5); CHECK(r.get_properties(0).get_data_type() == dt_double); + CHECK(r.get_properties(0).get_db_type() == db_double); CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_db_type() == db_int32); CHECK(r.get_properties(2).get_data_type() == dt_string); + CHECK(r.get_properties(2).get_db_type() == db_string); CHECK(r.get_properties(3).get_data_type() == dt_date); + CHECK(r.get_properties(3).get_db_type() == db_date); sql << "select name, num_int from soci_test", into(r); CHECK(r.size() == 2); CHECK(r.get_properties(0).get_data_type() == dt_string); + CHECK(r.get_properties(0).get_db_type() == db_string); CHECK(r.get_properties(1).get_data_type() == dt_integer); + CHECK(r.get_properties(1).get_db_type() == db_int32); // Check if row object is movable row moved = std::move(r); @@ -2482,7 +3041,9 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding", "[core][dynamic]") CHECK(r.size() == 0); CHECK(moved.get_properties(0).get_data_type() == dt_string); + CHECK(moved.get_properties(0).get_db_type() == db_string); CHECK(moved.get_properties(1).get_data_type() == dt_integer); + CHECK(moved.get_properties(1).get_db_type() == db_int32); } } @@ -2504,7 +3065,9 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding 2", "[core][dynamic]") CHECK(r.size() == 1); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get(0) == 20); + CHECK(r.get(0) == 20); } { int id; @@ -2516,19 +3079,25 @@ TEST_CASE_METHOD(common_tests, "Dynamic row binding 2", "[core][dynamic]") st.execute(true); CHECK(r.size() == 1); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get(0) == 20); + CHECK(r.get(0) == 20); id = 3; st.execute(true); CHECK(r.size() == 1); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get(0) == 30); + CHECK(r.get(0) == 30); id = 1; st.execute(true); CHECK(r.size() == 1); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get(0) == 10); + CHECK(r.get(0) == 10); } } @@ -2952,11 +3521,17 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r1.size() == 5); CHECK(r1.get_properties(0).get_data_type() == dt_double); + CHECK(r1.get_properties(0).get_db_type() == db_double); CHECK(r1.get_properties(1).get_data_type() == dt_integer); + CHECK(r1.get_properties(1).get_db_type() == db_int32); CHECK(r1.get_properties(2).get_data_type() == dt_string); + CHECK(r1.get_properties(2).get_db_type() == db_string); CHECK(r1.get_properties(3).get_data_type() == dt_date); + CHECK(r1.get_properties(3).get_db_type() == db_date); CHECK(r1.get_properties(4).get_data_type() == dt_string); + CHECK(r1.get_properties(4).get_db_type() == db_string); CHECK(r1.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r1.get_properties("NUM_INT").get_db_type() == db_int32); // Data @@ -3015,11 +3590,17 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r2.size() == 5); CHECK(r2.get_properties(0).get_data_type() == dt_double); + CHECK(r2.get_properties(0).get_db_type() == db_double); CHECK(r2.get_properties(1).get_data_type() == dt_integer); + CHECK(r2.get_properties(1).get_db_type() == db_int32); CHECK(r2.get_properties(2).get_data_type() == dt_string); + CHECK(r2.get_properties(2).get_db_type() == db_string); CHECK(r2.get_properties(3).get_data_type() == dt_date); + CHECK(r2.get_properties(3).get_db_type() == db_date); CHECK(r2.get_properties(4).get_data_type() == dt_string); + CHECK(r2.get_properties(4).get_db_type() == db_string); CHECK(r2.get_properties("NUM_INT").get_data_type() == dt_integer); + CHECK(r2.get_properties("NUM_INT").get_db_type() == db_int32); std::string newName = r2.get(2); CHECK(name != newName); @@ -3078,10 +3659,15 @@ TEST_CASE_METHOD(common_tests, "Reading rows from rowset", "[core][row][rowset]" // Properties CHECK(r1.size() == 5); CHECK(r1.get_properties(0).get_data_type() == dt_integer); + CHECK(r1.get_properties(0).get_db_type() == db_int32); CHECK(r1.get_properties(1).get_data_type() == dt_double); + CHECK(r1.get_properties(1).get_db_type() == db_double); CHECK(r1.get_properties(2).get_data_type() == dt_string); + CHECK(r1.get_properties(2).get_db_type() == db_string); CHECK(r1.get_properties(3).get_data_type() == dt_date); + CHECK(r1.get_properties(3).get_db_type() == db_date); CHECK(r1.get_properties(4).get_data_type() == dt_string); + CHECK(r1.get_properties(4).get_db_type() == db_string); // Data CHECK(r1.get_indicator(0) == soci::i_ok); @@ -3427,8 +4013,11 @@ TEST_CASE_METHOD(common_tests, "NULL with optional", "[core][boost][null]") // and tests the remaining column only. //CHECK(r1.get_properties(0).get_data_type() == dt_integer); + //CHECK(r1.get_properties(0).get_exchnage_data_type() == db_int32); CHECK(r1.get_properties(1).get_data_type() == dt_integer); + CHECK(r1.get_properties(1).get_db_type() == db_int32); CHECK(r1.get_properties(2).get_data_type() == dt_string); + CHECK(r1.get_properties(2).get_db_type() == db_string); //CHECK(r1.get(0) == 1); CHECK(r1.get(1) == 5); CHECK(r1.get(2) == "abc"); @@ -3444,8 +4033,11 @@ TEST_CASE_METHOD(common_tests, "NULL with optional", "[core][boost][null]") CHECK(r2.size() == 3); // CHECK(r2.get_properties(0).get_data_type() == dt_integer); + // CHECK(r2.get_properties(0).get_db_type() == db_int32); CHECK(r2.get_properties(1).get_data_type() == dt_integer); + CHECK(r2.get_properties(1).get_db_type() == db_int32); CHECK(r2.get_properties(2).get_data_type() == dt_string); + CHECK(r2.get_properties(2).get_db_type() == db_string); //CHECK(r2.get(0) == 2); try { @@ -3900,8 +4492,11 @@ TEST_CASE_METHOD(common_tests, "NULL with std optional", "[core][null]") // and tests the remaining column only. //CHECK(r1.get_properties(0).get_data_type() == dt_integer); + //CHECK(r1.get_properties(0).get_db_type() == db_int32); CHECK(r1.get_properties(1).get_data_type() == dt_integer); + CHECK(r1.get_properties(1).get_db_type() == db_int32); CHECK(r1.get_properties(2).get_data_type() == dt_string); + CHECK(r1.get_properties(2).get_db_type() == db_string); //CHECK(r1.get(0) == 1); CHECK(r1.get(1) == 5); CHECK(r1.get(2) == "abc"); @@ -3917,8 +4512,11 @@ TEST_CASE_METHOD(common_tests, "NULL with std optional", "[core][null]") CHECK(r2.size() == 3); // CHECK(r2.get_properties(0).get_data_type() == dt_integer); + // CHECK(r2.get_properties(0).get_db_type() == db_int32); CHECK(r2.get_properties(1).get_data_type() == dt_integer); + CHECK(r2.get_properties(1).get_db_type() == db_int32); CHECK(r2.get_properties(2).get_data_type() == dt_string); + CHECK(r2.get_properties(2).get_db_type() == db_string); //CHECK(r2.get(0) == 2); try { diff --git a/tests/db2/test-db2.cpp b/tests/db2/test-db2.cpp index fa84241fe..5501f1da1 100644 --- a/tests/db2/test-db2.cpp +++ b/tests/db2/test-db2.cpp @@ -29,8 +29,8 @@ struct table_creator_one : public table_creator_base table_creator_one(soci::session & sql) : table_creator_base(sql) { - sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, UL NUMERIC(20), D DOUBLE, " - "NUM76 NUMERIC(7,6), " + sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, LL BIGINT, UL NUMERIC(20), " + "D DOUBLE, NUM76 NUMERIC(7,6), " "TM TIMESTAMP, I1 INTEGER, I2 INTEGER, I3 INTEGER, NAME VARCHAR(20))"; } }; diff --git a/tests/firebird/test-firebird.cpp b/tests/firebird/test-firebird.cpp index 09c74fa14..769ae0d8f 100644 --- a/tests/firebird/test-firebird.cpp +++ b/tests/firebird/test-firebird.cpp @@ -773,8 +773,11 @@ TEST_CASE("Firebird dynamic binding", "[firebird][dynamic]") CHECK(r.get_properties(2).get_name() == "NTEST"); CHECK(r.get_properties(0).get_data_type() == dt_integer); + CHECK(r.get_properties(0).get_db_type() == db_int32); CHECK(r.get_properties(1).get_data_type() == dt_string); + CHECK(r.get_properties(1).get_db_type() == db_string); CHECK(r.get_properties(2).get_data_type() == dt_double); + CHECK(r.get_properties(2).get_db_type() == db_double); // get properties by name CHECK(r.get_properties("ID").get_name() == "ID"); @@ -782,8 +785,11 @@ TEST_CASE("Firebird dynamic binding", "[firebird][dynamic]") CHECK(r.get_properties("NTEST").get_name() == "NTEST"); CHECK(r.get_properties("ID").get_data_type() == dt_integer); + CHECK(r.get_properties("ID").get_db_type() == db_int32); CHECK(r.get_properties("MSG").get_data_type() == dt_string); + CHECK(r.get_properties("MSG").get_db_type() == db_string); CHECK(r.get_properties("NTEST").get_data_type() == dt_double); + CHECK(r.get_properties("NTEST").get_db_type() == db_double); // get values by position CHECK(r.get(0) == 1); @@ -1190,18 +1196,24 @@ TEST_CASE("Firebird decimals as strings", "[firebird][decimal][string]") // get properties by position CHECK(r.get_properties(0).get_name() == "NTEST1"); CHECK(r.get_properties(0).get_data_type() == dt_string); + CHECK(r.get_properties(0).get_db_type() == db_string); CHECK(r.get_properties(1).get_name() == "NTEST2"); CHECK(r.get_properties(1).get_data_type() == dt_string); + CHECK(r.get_properties(1).get_db_type() == db_string); CHECK(r.get_properties(2).get_name() == "NTEST3"); CHECK(r.get_properties(2).get_data_type() == dt_string); + CHECK(r.get_properties(2).get_db_type() == db_string); // get properties by name CHECK(r.get_properties("NTEST1").get_name() == "NTEST1"); CHECK(r.get_properties("NTEST1").get_data_type() == dt_string); + CHECK(r.get_properties("NTEST1").get_db_type() == db_string); CHECK(r.get_properties("NTEST2").get_name() == "NTEST2"); CHECK(r.get_properties("NTEST2").get_data_type() == dt_string); + CHECK(r.get_properties("NTEST2").get_db_type() == db_string); CHECK(r.get_properties("NTEST3").get_name() == "NTEST3"); CHECK(r.get_properties("NTEST3").get_data_type() == dt_string); + CHECK(r.get_properties("NTEST3").get_db_type() == db_string); // get values by position CHECK(r.get(0) == d_str1); @@ -1231,8 +1243,8 @@ struct TableCreator1 : public tests::table_creator_base : tests::table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh smallint, ul bigint, d double precision, " - "num76 numeric(7,6), " + "str varchar(20), sh smallint, ll bigint, ul bigint, " + "d double precision, num76 numeric(7,6), " "tm timestamp, i1 integer, i2 integer, i3 integer, name varchar(20))"; sql.commit(); sql.begin(); @@ -1339,6 +1351,17 @@ class test_context : public tests::test_context_base return "'" + datdt_string + "'"; } + bool has_uint64_storage_bug() const override + { + // Firebird does not support unsigned integer types. + // We're using Firebird 3, which does not yet support a data + // type that can correctly store a UINT64_MAX. The biggest + // numeric data type available is numeric(18,0). + // Firebird 4 introduces the data type int128 and numeric(36,0), + // which will be sufficient for that in the future. + return true; + } + void on_after_ddl(soci::session& sql) const override { sql.commit(); diff --git a/tests/mysql/test-mysql.cpp b/tests/mysql/test-mysql.cpp index 32af3ad7c..7e933432e 100644 --- a/tests/mysql/test-mysql.cpp +++ b/tests/mysql/test-mysql.cpp @@ -22,6 +22,7 @@ #include #include #include +#include std::string connectString; backend_factory const &backEnd = *soci::factory_mysql(); @@ -449,32 +450,44 @@ TEST_CASE("MySQL text and blob", "[mysql][text][blob]") "from soci_test order by id"); rowset::const_iterator r = rs.begin(); CHECK(r->get_properties(0).get_data_type() == dt_string); + CHECK(r->get_properties(0).get_db_type() == db_string); CHECK(r->get(0) == "foo"); CHECK(r->get_properties(1).get_data_type() == dt_string); + CHECK(r->get_properties(1).get_db_type() == db_string); CHECK(r->get(1) == "bar"); CHECK(r->get_properties(2).get_data_type() == dt_string); + CHECK(r->get_properties(2).get_db_type() == db_string); CHECK(r->get(2) == "baz"); ++r; CHECK(r->get_properties(0).get_data_type() == dt_string); + CHECK(r->get_properties(0).get_db_type() == db_string); CHECK(r->get(0) == std::string("qwerty\0uiop", 11)); CHECK(r->get_properties(1).get_data_type() == dt_string); + CHECK(r->get_properties(1).get_db_type() == db_string); CHECK(r->get(1) == std::string("zxcv\0bnm", 8)); CHECK(r->get_properties(2).get_data_type() == dt_string); + CHECK(r->get_properties(2).get_db_type() == db_string); CHECK(r->get(2) == std::string("qwerty\0uiop\0zxcvbnm\0", 20)); ++r; CHECK(r->get_properties(0).get_data_type() == dt_string); + CHECK(r->get_properties(0).get_db_type() == db_string); CHECK(r->get(0) == a); CHECK(r->get_properties(1).get_data_type() == dt_string); + CHECK(r->get_properties(1).get_db_type() == db_string); CHECK(r->get(1) == b); CHECK(r->get_properties(2).get_data_type() == dt_string); + CHECK(r->get_properties(2).get_db_type() == db_string); CHECK(r->get(2) == c); ++r; CHECK(r->get_properties(0).get_data_type() == dt_string); + CHECK(r->get_properties(0).get_db_type() == db_string); CHECK(r->get(0) == x); CHECK(r->get_properties(1).get_data_type() == dt_string); + CHECK(r->get_properties(1).get_db_type() == db_string); CHECK(r->get(1) == y); CHECK(r->get_properties(2).get_data_type() == dt_string); + CHECK(r->get_properties(2).get_db_type() == db_string); CHECK(r->get(2) == z); ++r; CHECK(r == rs.end()); @@ -688,8 +701,9 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); CHECK(r.get_properties("val").get_data_type() == dt_long_long); - CHECK(r.get("val") == 0xffffff00); + CHECK(r.get_properties("val").get_db_type() == db_uint32); CHECK(r.get("val") == 0xffffff00); + CHECK(r.get("val") == 0xffffff00); } { soci::session sql(backEnd, connectString); @@ -699,7 +713,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); CHECK(r.get_properties("val").get_data_type() == dt_integer); - CHECK(r.get("val") == -123); + CHECK(r.get_properties("val").get_db_type() == db_int8); + CHECK(r.get("val") == -123); } { soci::session sql(backEnd, connectString); @@ -709,7 +724,8 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); CHECK(r.get_properties("val").get_data_type() == dt_integer); - CHECK(r.get("val") == 123); + CHECK(r.get_properties("val").get_db_type() == db_uint8); + CHECK(r.get("val") == 123); } { soci::session sql(backEnd, connectString); @@ -719,7 +735,9 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); CHECK(r.get_properties("val").get_data_type() == dt_unsigned_long_long); + CHECK(r.get_properties("val").get_db_type() == db_uint64); CHECK(r.get("val") == 123456789012345ULL); + CHECK(r.get("val") == 123456789012345ULL); } { soci::session sql(backEnd, connectString); @@ -729,7 +747,9 @@ TEST_CASE("MySQL tinyint", "[mysql][int][tinyint]") sql << "select val from soci_test", into(r); REQUIRE(r.size() == 1); CHECK(r.get_properties("val").get_data_type() == dt_long_long); + CHECK(r.get_properties("val").get_db_type() == db_int64); CHECK(r.get("val") == -123456789012345LL); + CHECK(r.get("val") == -123456789012345LL); } } @@ -764,6 +784,7 @@ TEST_CASE("MySQL strings", "[mysql][string]") REQUIRE(r.size() == 13); for (int i = 0; i < 13; i++) { CHECK(r.get_properties(i).get_data_type() == dt_string); + CHECK(r.get_properties(i).get_db_type() == db_string); if (i < 6) { CHECK(r.get(i) == text); } else if (i < 12) { diff --git a/tests/mysql/test-mysql.h b/tests/mysql/test-mysql.h index 0fda454b2..8d120c3f8 100644 --- a/tests/mysql/test-mysql.h +++ b/tests/mysql/test-mysql.h @@ -13,8 +13,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh int2, ul numeric(20), d float8, " - "num76 numeric(7,6), " + "str varchar(20), sh int2, ll bigint, ul bigint unsigned, " + "d float8, num76 numeric(7,6), " "tm datetime, i1 integer, i2 integer, i3 integer, " "name varchar(20)) engine=InnoDB"; } diff --git a/tests/odbc/test-odbc-access.cpp b/tests/odbc/test-odbc-access.cpp index b4ec39870..2783646f4 100644 --- a/tests/odbc/test-odbc-access.cpp +++ b/tests/odbc/test-odbc-access.cpp @@ -26,8 +26,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh integer, ul number, d float, " - "num76 numeric(7,6), " + "str varchar(20), sh integer, ll number, ul number, " + "d float, num76 numeric(7,6), " "tm timestamp, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } diff --git a/tests/odbc/test-odbc-db2.cpp b/tests/odbc/test-odbc-db2.cpp index bcd771d9b..91788949e 100644 --- a/tests/odbc/test-odbc-db2.cpp +++ b/tests/odbc/test-odbc-db2.cpp @@ -25,8 +25,8 @@ struct table_creator_one : public table_creator_base table_creator_one(soci::session & sql) : table_creator_base(sql) { - sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, UL NUMERIC(20), D DOUBLE, " - "NUM76 NUMERIC(7,6), " + sql << "CREATE TABLE SOCI_TEST(ID INTEGER, VAL SMALLINT, C CHAR, STR VARCHAR(20), SH SMALLINT, LL BIGINT, UL NUMERIC(20), " + "D DOUBLE, NUM76 NUMERIC(7,6), " "TM TIMESTAMP(9), I1 INTEGER, I2 INTEGER, I3 INTEGER, NAME VARCHAR(20))"; } }; diff --git a/tests/odbc/test-odbc-mssql.cpp b/tests/odbc/test-odbc-mssql.cpp index 252ac17fe..8b3ecd740 100644 --- a/tests/odbc/test-odbc-mssql.cpp +++ b/tests/odbc/test-odbc-mssql.cpp @@ -82,8 +82,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh smallint, ul numeric(20), d float, " - "num76 numeric(7,6), " + "str varchar(20), sh smallint, ll bigint, ul numeric(20), " + "d float, num76 numeric(7,6), " "tm datetime, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } diff --git a/tests/odbc/test-odbc-mysql.cpp b/tests/odbc/test-odbc-mysql.cpp index 9ea70adf6..5b14e7ea4 100644 --- a/tests/odbc/test-odbc-mysql.cpp +++ b/tests/odbc/test-odbc-mysql.cpp @@ -16,6 +16,23 @@ std::string connectString; backend_factory const &backEnd = *soci::factory_odbc(); +class test_context_odbc : public test_context +{ +public: + using test_context::test_context; + + bool truncates_uint64_to_int64() const override + { + // The ODBC driver of MySQL truncates values bigger then INT64_MAX. + // There are open bugs related to this issue: + // - https://bugs.mysql.com/bug.php?id=95978 + // - https://bugs.mysql.com/bug.php?id=61114 + // Driver version 8.0.31 seems to have fixed this (https://github.com/mysql/mysql-connector-odbc/commit/e78da1344247752f76a082de51cfd36d5d2dd98f), + // but we use an older version in the AppVeyor builds. + return true; + } +}; + int main(int argc, char** argv) { #ifdef _MSC_VER @@ -43,7 +60,7 @@ int main(int argc, char** argv) connectString = "FILEDSN=./test-mysql.dsn"; } - test_context tc(backEnd, connectString); + test_context_odbc tc(backEnd, connectString); return Catch::Session().run(argc, argv); } diff --git a/tests/odbc/test-odbc-postgresql.cpp b/tests/odbc/test-odbc-postgresql.cpp index 64da86861..4dbfa3c46 100644 --- a/tests/odbc/test-odbc-postgresql.cpp +++ b/tests/odbc/test-odbc-postgresql.cpp @@ -92,8 +92,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh int2, ul numeric(20), d float8, " - "num76 numeric(7,6), " + "str varchar(20), sh int2, ll bigint, ul numeric(20), " + "d float8, num76 numeric(7,6), " "tm timestamp, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } diff --git a/tests/oracle/test-oracle.cpp b/tests/oracle/test-oracle.cpp index fcb952e53..ca6918188 100644 --- a/tests/oracle/test-oracle.cpp +++ b/tests/oracle/test-oracle.cpp @@ -1397,8 +1397,8 @@ struct table_creator_one : public table_creator_base table_creator_one(soci::session & sql) : table_creator_base(sql) { - sql << "create table soci_test(id number(10,0), val number(4,0), c char, " - "str varchar2(20), sh number, ul number, d number, " + sql << "create table soci_test(id number(10,0), val number(8,0), c char, " + "str varchar2(20), sh number, ll number, ul number, d number, " "num76 numeric(7,6), " "tm date, i1 number, i2 number, i3 number, name varchar2(20))"; } diff --git a/tests/postgresql/test-postgresql.cpp b/tests/postgresql/test-postgresql.cpp index fc98f5b79..a69459c49 100644 --- a/tests/postgresql/test-postgresql.cpp +++ b/tests/postgresql/test-postgresql.cpp @@ -369,13 +369,18 @@ TEST_CASE("PostgreSQL boolean", "[postgresql][boolean]") sql << "insert into soci_test(val) values(:val)", use(i1); int i2 = 7; + row r; sql << "select val from soci_test", into(i2); + sql << "select val from soci_test", into(r); CHECK(i2 == i1); + CHECK(r.get(0) == i1); sql << "update soci_test set val = true"; sql << "select val from soci_test", into(i2); + sql << "select val from soci_test", into(r); CHECK(i2 == 1); + CHECK(r.get(0) == 1); } struct uuid_table_creator : table_creator_base @@ -632,6 +637,7 @@ TEST_CASE("PostgreSQL bytea", "[postgresql][bytea]") REQUIRE(r.size() == 1); column_properties const& props = r.get_properties(0); CHECK(props.get_data_type() == soci::dt_string); + CHECK(props.get_db_type() == soci::db_string); std::string bin2 = r.get(0); CHECK(bin2 == expectedBytea); } @@ -781,12 +787,14 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") if (ci.name == "i") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); i_found = true; } else if (ci.name == "j") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); j_found = true; } @@ -859,18 +867,21 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") if (ci.name == "j") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); j_found = true; } else if (ci.name == "k") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); k_found = true; } else if (ci.name == "big") { CHECK(ci.type == soci::dt_string); + CHECK(ci.dataType == soci::db_string); CHECK(ci.precision == 0); // "unlimited" for strings big_found = true; } @@ -900,24 +911,28 @@ TEST_CASE("PostgreSQL DDL with metadata", "[postgresql][ddl]") if (ci.name == "i") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable); i_found = true; } else if (ci.name == "j") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable == false); // primary key j_found = true; } else if (ci.name == "k") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable == false); k_found = true; } else if (ci.name == "m") { CHECK(ci.type == soci::dt_integer); + CHECK(ci.dataType == soci::db_int32); CHECK(ci.nullable == false); m_found = true; } @@ -1158,7 +1173,7 @@ TEST_CASE("test_enum_with_explicit_custom_type_string_rowset", "[postgresql][bin statement s2 = (sql.prepare << "SELECT Type FROM soci_test;"); s1.execute(false); - + soci::row result; s2.define_and_bind(); s2.exchange_for_rowset(soci::into(result)); @@ -1199,7 +1214,7 @@ struct test_enum_with_explicit_custom_type_int_rowset : table_creator_base try { - sql << "CREATE TABLE soci_test( Type smallint)"; + sql << "CREATE TABLE soci_test( Type integer)"; ; } catch (...) @@ -1312,8 +1327,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh int2, ul numeric(20), d float8, " - "num76 numeric(7,6), " + "str varchar(20), sh int2, ll bigint, ul numeric(20), " + "d float8, num76 numeric(7,6), " "tm timestamp, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } diff --git a/tests/sqlite3/test-sqlite3.cpp b/tests/sqlite3/test-sqlite3.cpp index dcd34dc10..3d2ada131 100644 --- a/tests/sqlite3/test-sqlite3.cpp +++ b/tests/sqlite3/test-sqlite3.cpp @@ -14,6 +14,7 @@ #include #include #include +#include using namespace soci; using namespace soci::tests; @@ -548,8 +549,8 @@ struct table_creator_one : public table_creator_base : table_creator_base(sql) { sql << "create table soci_test(id integer, val integer, c char, " - "str varchar(20), sh smallint, ul numeric(20), d float, " - "num76 numeric(7,6), " + "str varchar(20), sh smallint, ll bigint, ul unsigned bigint, " + "d float, num76 numeric(7,6), " "tm datetime, i1 integer, i2 integer, i3 integer, " "name varchar(20))"; } @@ -664,6 +665,13 @@ class test_context : public test_context_base return true; } + bool has_uint64_storage_bug() const override + { + // SQLite processes integers as 8-byte signed values. Values bigger + // than INT64_MAX therefore overflow and are stored as negative values. + return true; + } + bool enable_std_char_padding(soci::session&) const override { // SQLite does not support right padded char type.