qt addBindValue 访问sqlite数据库,NOT NULL constraint failed问题处理

遇到一个奇怪的问题
qt5 QSqlQuery addBindValue 写sqlite table数据时,
报错 NOT NULL constraint failed: Unable to fetch row
原因也清楚,此表的text类型字段都限制为非空
诡异的是,如果从db获得数据后,写入db,空字符串就没事
从excel提取后,空字符串写入db就不行

后来查到QString 的isNull()的返回值才发现差别。
代码改为以下就正常了

	for (int i = 0; i < excel_col_count; ++i)
	{
		if (row_data[i].isNull())
		{
			row_data[i] = "";//sqlite部分列要求非空,此时需要初始化
		}
		query.addBindValue(row_data[i]);
	}

个人觉得这事有点奇怪,查了下从excel提取数据的代码如下

			if (xlsx_temp.cellAt(i, j))
			{
				const QString sTemp = xlsx_temp.cellAt(i, j)->value().toString();
				row_temp.push_back(sTemp);//此处获得空字符串
			}
			else
			{
				row_temp.push_back("");
			}

跟踪push_back
查到源码如下

push_back是如下拷贝
::memcpy(n, static_cast<const void *>(&t), sizeof(T));

isNull()背后的源码是判断是否是公共的NULL数据指针。
    static const QArrayData shared_null[2];
    static QArrayData *sharedNull() Q_DECL_NOTHROW { return const_cast<QArrayData*>(shared_null); }

猜测是qt源码为了提高效率(节约内存和时间),默认是将所有""字符串都指向一个static指针,QArrayData 共享内存如下

struct Q_CORE_EXPORT QArrayData
{
    QtPrivate::RefCount ref;
    int size;
    uint alloc : 31;
    uint capacityReserved : 1;

    qptrdiff offset; // in bytes from beginning of header

待续

个人不太理解sqlite addBindValue QString isNull()的坑,,个人觉得是qt的bug,有时间再查下。暂时记得QString有isNull()这个坑就行了。

你可能感兴趣的:(qt,db,sqlite,数据库,qt)