插入protobuf时SQLite无法识别的令牌错误:要处理哪些令牌以及如何处理?

SQLite unrecognized token error while inserting protobuf: Which tokens to be handled & How?

本文关键字:令牌 处理 何处理 SQLite protobuf 识别 错误 插入      更新时间:2023-10-16

我正在使用sqlite3_exec()函数来执行查询。我知道根据以下帖子,最好将_prepare, _bind, _step, _finalize组合用于各种好处。

sqllite查询使用加密的std :: string(未识别的令牌)

但是,就我而言,我已经有一个库,该库围绕sqlite3_exec()紧密耦合,很难更改。我想知道,即使出于教育目的,我如何在SQLite3数据库中输入特殊令牌。目前,我正在使用C 从文件中读取此语句,并使用sqlite3_exec()

插入DB

当前,以下语句给出错误:

INSERT INTO Convey(username, data, id, type)  
VALUES('12345', '^Z^Dfine* ^HºÉÙ<98>ö÷×^B2^@', 'abcd', 31);

错误在此符号^@作为SQL error: unrecognized token:出现。当我拆除该声明并检查每个字符的ASCII时,它显示了0代替^@data的类型,无论是TEXT还是BLOB都没有区别。

请注意,"数据",我试图在此处输入以序列化形式的Google Protobuf消息。

当一个人必须使用 sqlite3_exec()

[注意:1方法是用一些预定义的模式替换0,在二进制字符串中发现的模式较少,然后在阅读时还原它们。我也对此解决方案开放。]

似乎不可能INSERT具有斑点性质的数据,即包含nul(' 0')字符(或可能是新行' n'字符)。

因此,现在我正在按照以下方式插入:

  • 插入之前,检查是否有任何此类特殊字符(即' 0',' n')
  • 如果是,则在字符串中,在末尾附加一个已知的代币,例如'%'
  • 列出该令牌之后由逗号分隔的位置;这些职位可以用临时场所持有人取代,例如" 0"

即。'^Z^Dfine* ^HºÉÙ<98>ö÷×^B2^@'看起来像'^Z^Dfine* ^HºÉÙ<98>ö÷×^B20#<position>'

在阅读字符串时,必须解码相同。到目前为止,这非常有帮助且运作良好!


对于那些有兴趣的人,这是替换" 0"的代码:

#define SQLa_STRING_END      '%'
#define SQLa_NUL_SEPARATOR   ','
#define SQLa_NUL_TOKEN       '0'
string
ToString (const string& s_,  // need to enclose with '' and add ' before '
          const bool isEncodingString = false)
{
  string s = s_;
  const char apostrophe = ''';
  bool isStringEndPending = isEncodingString;
  for(size_t i = 0, length = s.length(); i < length; ++i)
    switch(s[i])
    {
    case apostrophe:
      s.insert(i++, 1, apostrophe);
      ++length;
    break;
    case 0:
      if(isEncodingString)
      {
        if(isStringEndPending)
        {
          s += SQLa_STRING_END;
          isStringEndPending = false;
        }
        s[i] = SQLa_NUL_TOKEN; ;
        s += std::to_string(i) + SQLa_NUL_SEPARATOR;
      }
    default:
    break;
    }
  s.insert(0, 1, ''');
  return s += ''';
}
string
FromString (const char value[])  // enclosing '' are not present
{
  string s = value;
  if(const auto posEnd = s.rfind(SQLa_STRING_END) + 1)
  {
    std::replace(s.begin() + posEnd, s.end(), SQLa_NUL_SEPARATOR, '');
    for(auto pos = posEnd, length = s.length() - 1;
        pos < length;
        s[::atoll(&s[pos])] = 0, pos = s.find(SQLa_NUL_SEPARATOR, pos) + 1);
    s.erase(posEnd - 1);
  }
  return s;
}

具有值零的字符不是有效的UTF-8字符,因此不能直接写在SQL中。

仅用于记录:您应该使用参数。但是,如果您想在SQL中执行此操作,则必须写一个blob文字:

... VALUES('12345', x'1A0466696E652A2008BAC9D998F6F7D7023200', 'abcd', 31);