| 614 | } |
| 615 | |
| 616 | std::unique_ptr<DatabaseCursor> SQLiteBatch::GetNewPrefixCursor(std::span<const std::byte> prefix) |
| 617 | { |
| 618 | if (!m_database.m_db) return nullptr; |
| 619 | |
| 620 | // To get just the records we want, the SQL statement does a comparison of the binary data |
| 621 | // where the data must be greater than or equal to the prefix, and less than |
| 622 | // the prefix incremented by one (when interpreted as an integer) |
| 623 | std::vector<std::byte> start_range(prefix.begin(), prefix.end()); |
| 624 | std::vector<std::byte> end_range(prefix.begin(), prefix.end()); |
| 625 | auto it = end_range.rbegin(); |
| 626 | for (; it != end_range.rend(); ++it) { |
| 627 | if (*it == std::byte(std::numeric_limits<unsigned char>::max())) { |
| 628 | *it = std::byte(0); |
| 629 | continue; |
| 630 | } |
| 631 | *it = std::byte(std::to_integer<unsigned char>(*it) + 1); |
| 632 | break; |
| 633 | } |
| 634 | if (it == end_range.rend()) { |
| 635 | // If the prefix is all 0xff bytes, clear end_range as we won't need it |
| 636 | end_range.clear(); |
| 637 | } |
| 638 | |
| 639 | auto cursor = std::make_unique<SQLiteCursor>(start_range, end_range); |
| 640 | if (!cursor) return nullptr; |
| 641 | |
| 642 | const char* stmt_text = end_range.empty() ? "SELECT key, value FROM main WHERE key >= ?" : |
| 643 | "SELECT key, value FROM main WHERE key >= ? AND key < ?"; |
| 644 | int res = sqlite3_prepare_v2(m_database.m_db, stmt_text, -1, &cursor->m_cursor_stmt, nullptr); |
| 645 | if (res != SQLITE_OK) { |
| 646 | throw std::runtime_error(strprintf( |
| 647 | "SQLiteDatabase: Failed to setup cursor SQL statement: %s\n", sqlite3_errstr(res))); |
| 648 | } |
| 649 | |
| 650 | if (!BindBlobToStatement(cursor->m_cursor_stmt, 1, cursor->m_prefix_range_start, "prefix_start")) return nullptr; |
| 651 | if (!end_range.empty()) { |
| 652 | if (!BindBlobToStatement(cursor->m_cursor_stmt, 2, cursor->m_prefix_range_end, "prefix_end")) return nullptr; |
| 653 | } |
| 654 | |
| 655 | return cursor; |
| 656 | } |
| 657 | |
| 658 | bool SQLiteBatch::TxnBegin() |
| 659 | { |