Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 绑定一个';无符号长';(uint64)在sqlite3语句中?C++;_C++_Sqlite_Bind_Unsigned Integer - Fatal编程技术网

C++ 绑定一个';无符号长';(uint64)在sqlite3语句中?C++;

C++ 绑定一个';无符号长';(uint64)在sqlite3语句中?C++;,c++,sqlite,bind,unsigned-integer,C++,Sqlite,Bind,Unsigned Integer,我正在使用sqlite3库,该库可在上获得 我有一些未签名的long,我想存储在数据库中。我不想自己构造查询,而让它接受某种注入(无论是偶然的还是非偶然的)。因此,我使用这些函数来“清理”我的参数 问题是没有无符号长整数的函数类型,只有整数 intsqlite3\u bind\u int(sqlite3\u stmt*,int,int) intsqlite3\u bind\u int64(sqlite3\u stmt*,int,sqlite3\u int64) 如果我不能以未签名的方式存储数字,

我正在使用sqlite3库,该库可在上获得

我有一些未签名的long,我想存储在数据库中。我不想自己构造查询,而让它接受某种注入(无论是偶然的还是非偶然的)。因此,我使用这些函数来“清理”我的参数

问题是没有无符号长整数的函数类型,只有整数

intsqlite3\u bind\u int(sqlite3\u stmt*,int,int)

intsqlite3\u bind\u int64(sqlite3\u stmt*,int,sqlite3\u int64)

如果我不能以未签名的方式存储数字,我肯定会有溢出的数字

我需要自己处理吗?(即,从db中选择后转换为无符号类型,或在插入数据库之前转换为有符号类型)

如果我必须自己处理这个问题,那么当比较实际上是在无符号范围内时,如何执行一些存储为有符号长整数的比较查询呢

查看转换后的数据,人们会认为无符号long可以毫无问题地表示

如果还有其他解决方案,请告诉我!
谢谢

这是一个hack,但int和unsigned具有相同的位深度,因此您可以

int i=static_cast<int>(unsigned_int);
或者使用特定的宽度

#include <stdint.h>
uint32_t
int32_t 
#包括
uint32\u t
int32\u t

就我个人而言,我发现在允许数据库执行比较等操作的同时处理此问题的最简单方法是使用
sqlite3\u bind\u int64
函数在数据库中存储无符号整数。我假设您使用的是32位无符号整数,它可以轻松地存储在64位有符号整数中

例如:

uint32_t x = 0xFFFFFFFF;
sqlite3_bind_int64( stmt, 1, x );
然后检索变量(假设您使用的是boost,否则您必须编写自己的溢出检查代码):

#包括
...
uint32\u t x=boost::numeric\u cast(sqlite3\u column\u int64(stmt,0));

当然,如果您想存储未签名的int64,这会有问题,但这是sqlite的一个限制。

uint32\u t
完全适合
int64\u t
的内部,因此您可以做一个简单的赋值

    int64_t i64;
    uint32_t u32 = 32;
    i64 = u32;
以另一种方式分配时,应检查
int64\t
的边界,以便尽早捕获对数据库中的值所做的任何更改

    int64_t i64 = 32;
    uint32_t u32;
    if (i64 < 0 || i64 > std::numeric_limits<uint32_t>::max())
        throw std::runtime_error("invalid uint32_t");
    u32 = i64;
int64\u t i64=32;
uint32_t u32;
如果(i64<0 | | i64>std::numeric_limits::max())
抛出标准::运行时错误(“无效uint32错误”);
u32=i64;

然后,您可以像平常一样将
int64
发送到sqlite数据库。

sqlite数据库不能在其中存储无符号的64位整数。这只是数据的限制

你的选择是:

  • 将其存储为字符串,并根据需要进行转换
  • 将其存储为二进制blob,并根据需要进行转换
  • 假设它是一个带强制转换的有符号64位整数,从而根据需要进行转换
  • 将两条信息存储为两列:无符号63位整数(较低的63位)和表示符号位的值

因为这些是散列,所以除了相等性测试之外,您可能不关心比较。因此,这些方法中的大多数都很适合您。

如果您希望在sqlite数据库中存储uint64,并且仍然允许它在SQL中用作uint64,那么您可能需要编写一些自定义函数

在向数据库发送数据和从数据库发送数据时,只需将uint64转换为int64,然后编写自定义函数来执行所需的任何比较等操作。例如,要进行大于的比较:

void greaterThan( sqlite3_context* ctx, sqlite3_value** values )
{
    uint64_t value1 = boost::numeric_cast< uint64_t >( sqlite3_value_int64( value[ 0 ] ) );
    uint64_t value2 = boost::numeric_cast< uint64_t >( sqlite3_value_int64( value[ 1 ] ) );
    sqlite3_result_int( ctx, value1 > value2 );
}

//Register this function using sqlite3_create_function
sqlite3_create_function( db, "UINT_GT", 2, SQLITE3_ANY, NULL, &greaterThan, NULL, NULL );
或者,如果需要基于uint64\u t的自定义排序规则,则应该能够以类似的方式使用sqlite3\u create\u排序规则


这不是一个完美的解决方案,因为您需要为想要执行的每个操作编写一个自定义函数,但它至少应该可以工作。

我尝试了许多不同的方法,主要是尝试让列类型作为sqlite3\u uint64工作,如中所述

没有运气,因为uint64未作为uint64存储在表中。当我查看存储的数据时,它是经过签名的,所以我假设它存储为int64


最后,我用一个字符作为值的前缀,强制sqlite将其存储为文本,而不进行任何转换。只需将char添加到select查询值中进行比较就容易多了。因此,9223360144090060712变成了A9223360144090060712,我可以简单地做一个SELECT WHERE HASH='A9223360144090060712'

我想如果你被困在一个不支持unsigned int的数据库中,像这样的一个小技巧是你最不关心的。不确定在写入db之前是否必须进行转换,因为无符号所做的一切都是更改一位的含义。如果要对值使用基本SQL以外的任何东西,这不是一个好主意。SQLite会认为任何大的UINT实际上都是负数。因此,排序和比较就不存在了。更不用说不小心忘记了强制转换之类的东西了。的确,如果您要比较值,它会导致问题,如果您只是将SQLite用作存储文件,我不会担心。@111111如果没有其他简单的解决方案来解决这个特定问题,我同意您的看法。限制您使用SQL的能力毫无意义-即使您现在不使用它,您也永远不知道它何时会改变。g++在这两种转换中都给了我
无效强制转换
。感谢您的回复。我无法控制我的数据源,很可能会有int64以外的值。当然,我可以毫无问题地存储数据,但是进行比较查询是不可能的。如果我的数据适合
int64
的话,我就没有ha了
    int64_t i64;
    uint32_t u32 = 32;
    i64 = u32;
    int64_t i64 = 32;
    uint32_t u32;
    if (i64 < 0 || i64 > std::numeric_limits<uint32_t>::max())
        throw std::runtime_error("invalid uint32_t");
    u32 = i64;
void greaterThan( sqlite3_context* ctx, sqlite3_value** values )
{
    uint64_t value1 = boost::numeric_cast< uint64_t >( sqlite3_value_int64( value[ 0 ] ) );
    uint64_t value2 = boost::numeric_cast< uint64_t >( sqlite3_value_int64( value[ 1 ] ) );
    sqlite3_result_int( ctx, value1 > value2 );
}

//Register this function using sqlite3_create_function
sqlite3_create_function( db, "UINT_GT", 2, SQLITE3_ANY, NULL, &greaterThan, NULL, NULL );
SELECT something FROM aTable WHERE UINT_GT(value1,value2);