differences
parent
4d5587565f
commit
120a9ba63f
|
@ -0,0 +1,120 @@
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DATA_LOADER_H
|
||||||
|
#define DATA_LOADER_H
|
||||||
|
|
||||||
|
#include <sql.h>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <blt/math/vectors.h>
|
||||||
|
#include <blt/std/hashmap.h>
|
||||||
|
|
||||||
|
database_t load_database(const std::filesystem::path& path);
|
||||||
|
|
||||||
|
struct image_t;
|
||||||
|
|
||||||
|
struct sampler_interface_t
|
||||||
|
{
|
||||||
|
virtual void clear()
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual std::optional<blt::vec3> get_sample() = 0;
|
||||||
|
|
||||||
|
virtual ~sampler_interface_t() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sampler_single_value_t final : sampler_interface_t
|
||||||
|
{
|
||||||
|
explicit sampler_single_value_t(const blt::vec3 value): value{value}
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::optional<blt::vec3> get_sample() override
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
blt::vec3 value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sampler_one_point_t final : sampler_interface_t
|
||||||
|
{
|
||||||
|
explicit sampler_one_point_t(const image_t& image);
|
||||||
|
|
||||||
|
void clear() override
|
||||||
|
{
|
||||||
|
found = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<blt::vec3> get_sample() override
|
||||||
|
{
|
||||||
|
if (found)
|
||||||
|
return {};
|
||||||
|
found = true;
|
||||||
|
return average;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
blt::vec3 average;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct comparator_interface_t
|
||||||
|
{
|
||||||
|
virtual ~comparator_interface_t() = default;
|
||||||
|
virtual blt::vec3 compare(sampler_interface_t& s1, sampler_interface_t& s2) = 0;
|
||||||
|
|
||||||
|
blt::vec3 compare(sampler_interface_t& s1, const blt::vec3 point)
|
||||||
|
{
|
||||||
|
sampler_single_value_t value{point};
|
||||||
|
return compare(s1, value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct comparator_euclidean_t final : comparator_interface_t
|
||||||
|
{
|
||||||
|
blt::vec3 compare(sampler_interface_t& s1, sampler_interface_t& s2) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct image_t
|
||||||
|
{
|
||||||
|
blt::i32 width, height;
|
||||||
|
std::vector<float> data;
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_default_sampler() const
|
||||||
|
{
|
||||||
|
return sampler_one_point_t{*this};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct assets_t
|
||||||
|
{
|
||||||
|
blt::hashmap_t<std::string, blt::hashmap_t<std::string, image_t>> images;
|
||||||
|
};
|
||||||
|
|
||||||
|
class data_loader_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit data_loader_t(database_t& data): db{&data}
|
||||||
|
{}
|
||||||
|
|
||||||
|
[[nodiscard]] assets_t load() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
database_t* db;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //DATA_LOADER_H
|
|
@ -82,10 +82,10 @@ public:
|
||||||
return static_cast<float>(sqlite3_column_double(statement, col));
|
return static_cast<float>(sqlite3_column_double(statement, col));
|
||||||
} else if constexpr (std::is_same_v<Decay, std::string> || std::is_same_v<Decay, std::string_view> || std::is_same_v<Decay, char*>)
|
} else if constexpr (std::is_same_v<Decay, std::string> || std::is_same_v<Decay, std::string_view> || std::is_same_v<Decay, char*>)
|
||||||
{
|
{
|
||||||
return T(sqlite3_column_text(statement, col));
|
return T{reinterpret_cast<const char*>(sqlite3_column_text(statement, col))};
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
return static_cast<T>(sqlite3_column_blob(statement, col));
|
return static_cast<const std::remove_pointer_t<T>*>(sqlite3_column_blob(statement, col));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,6 +191,35 @@ private:
|
||||||
sqlite3_stmt* statement;
|
sqlite3_stmt* statement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct statement_result_t
|
||||||
|
{
|
||||||
|
explicit statement_result_t(const int error_code): error_code{error_code}
|
||||||
|
{}
|
||||||
|
|
||||||
|
[[nodiscard]] bool has_error() const
|
||||||
|
{
|
||||||
|
return !(error_code == SQLITE_ROW || error_code == SQLITE_DONE || error_code == SQLITE_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool has_row() const
|
||||||
|
{
|
||||||
|
return error_code == SQLITE_ROW;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const
|
||||||
|
{
|
||||||
|
return !has_error();
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int get_error() const
|
||||||
|
{
|
||||||
|
return error_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int error_code = 0;
|
||||||
|
};
|
||||||
|
|
||||||
class statement_t
|
class statement_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -217,7 +246,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the statement has a row. false otherwise. optional is empty if there is an error
|
// returns true if the statement has a row. false otherwise. optional is empty if there is an error
|
||||||
[[jetbrains::has_side_effects]] std::optional<bool> execute() const; // NOLINT
|
[[jetbrains::has_side_effects]] statement_result_t execute() const; // NOLINT
|
||||||
|
|
||||||
[[nodiscard]] column_t fetch() const
|
[[nodiscard]] column_t fetch() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -359,12 +359,13 @@ std::optional<load_failure_t> asset_loader_t::load_assets(const std::string& ass
|
||||||
|
|
||||||
database_t& asset_loader_t::load_textures()
|
database_t& asset_loader_t::load_textures()
|
||||||
{
|
{
|
||||||
|
BLT_INFO("[Phase 2] Loading Textures");
|
||||||
auto texture_table = db.builder().create_table("solid_textures");
|
auto texture_table = db.builder().create_table("solid_textures");
|
||||||
texture_table.with_column<std::string>("namespace").primary_key();
|
texture_table.with_column<std::string>("namespace").primary_key();
|
||||||
texture_table.with_column<std::string>("name").primary_key();
|
texture_table.with_column<std::string>("name").primary_key();
|
||||||
texture_table.with_column<blt::i32>("width").not_null();
|
texture_table.with_column<blt::i32>("width").not_null();
|
||||||
texture_table.with_column<blt::i32>("height").not_null();
|
texture_table.with_column<blt::i32>("height").not_null();
|
||||||
texture_table.with_column<std::byte*>("data").not_null();
|
texture_table.with_column<const std::byte*>("data").not_null();
|
||||||
texture_table.build().execute();
|
texture_table.build().execute();
|
||||||
|
|
||||||
auto non_texture_table = db.builder().create_table("non_solid_textures");
|
auto non_texture_table = db.builder().create_table("non_solid_textures");
|
||||||
|
@ -372,7 +373,7 @@ database_t& asset_loader_t::load_textures()
|
||||||
non_texture_table.with_column<std::string>("name").primary_key();
|
non_texture_table.with_column<std::string>("name").primary_key();
|
||||||
non_texture_table.with_column<blt::i32>("width").not_null();
|
non_texture_table.with_column<blt::i32>("width").not_null();
|
||||||
non_texture_table.with_column<blt::i32>("height").not_null();
|
non_texture_table.with_column<blt::i32>("height").not_null();
|
||||||
non_texture_table.with_column<std::byte*>("data").not_null();
|
non_texture_table.with_column<const std::byte*>("data").not_null();
|
||||||
non_texture_table.build().execute();
|
non_texture_table.build().execute();
|
||||||
|
|
||||||
const static auto insert_solid_sql = "INSERT INTO solid_textures VALUES (?, ?, ?, ?, ?)";
|
const static auto insert_solid_sql = "INSERT INTO solid_textures VALUES (?, ?, ?, ?, ?)";
|
||||||
|
@ -384,12 +385,14 @@ database_t& asset_loader_t::load_textures()
|
||||||
{
|
{
|
||||||
for (const auto& texture : textures)
|
for (const auto& texture : textures)
|
||||||
process_texture(insert_solid_stmt, namespace_str, texture);
|
process_texture(insert_solid_stmt, namespace_str, texture);
|
||||||
|
BLT_INFO("[Phase 2] Loaded {} solid textures for namespace {}", textures.size(), namespace_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [namespace_str, textures] : data.non_solid_textures_to_load)
|
for (const auto& [namespace_str, textures] : data.non_solid_textures_to_load)
|
||||||
{
|
{
|
||||||
for (const auto& texture : textures)
|
for (const auto& texture : textures)
|
||||||
process_texture(insert_non_solid_stmt, namespace_str, texture);
|
process_texture(insert_non_solid_stmt, namespace_str, texture);
|
||||||
|
BLT_INFO("[Phase 2] Loaded {} non-solid textures for namespace {}", textures.size(), namespace_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tag_table = db.builder().create_table("tags");
|
auto tag_table = db.builder().create_table("tags");
|
||||||
|
@ -409,26 +412,38 @@ database_t& asset_loader_t::load_textures()
|
||||||
const static auto insert_tag_model_sql = "INSERT INTO tag_models VALUES (?, ?, ?, ?)";
|
const static auto insert_tag_model_sql = "INSERT INTO tag_models VALUES (?, ?, ?, ?)";
|
||||||
const auto insert_tag_stmt = db.prepare(insert_tag_sql);
|
const auto insert_tag_stmt = db.prepare(insert_tag_sql);
|
||||||
const auto insert_tag_model_stmt = db.prepare(insert_tag_model_sql);
|
const auto insert_tag_model_stmt = db.prepare(insert_tag_model_sql);
|
||||||
|
|
||||||
|
BLT_DEBUG("[Phase 2] Begin tag storage");
|
||||||
|
size_t tag_list_count = 0;
|
||||||
|
size_t tag_model_count = 0;
|
||||||
for (const auto& [namespace_str, jdata] : data.json_data)
|
for (const auto& [namespace_str, jdata] : data.json_data)
|
||||||
{
|
{
|
||||||
for (const auto& [tag_name, tag_data] : jdata.tags)
|
for (const auto& [tag_name, tag_data] : jdata.tags)
|
||||||
{
|
{
|
||||||
|
if (tag_data.list.empty() && tag_data.models.empty())
|
||||||
|
continue;
|
||||||
for (const auto& block_tag : tag_data.list)
|
for (const auto& block_tag : tag_data.list)
|
||||||
{
|
{
|
||||||
|
++tag_list_count;
|
||||||
insert_tag_stmt.bind().bind_all(namespace_str, tag_name, block_tag);
|
insert_tag_stmt.bind().bind_all(namespace_str, tag_name, block_tag);
|
||||||
if (!insert_tag_stmt.execute())
|
if (!insert_tag_stmt.execute())
|
||||||
BLT_WARN("[Tag List] Unable to insert {} into {}:{} reason '{}'", block_tag, namespace_str, tag_name, db.get_error());
|
BLT_WARN("[Tag List] Unable to insert {} into {}:{} reason '{}'", block_tag, namespace_str, tag_name, db.get_error());
|
||||||
}
|
}
|
||||||
|
BLT_DEBUG("[Phase 2] Loaded {} blocks to tag {}:{}", tag_data.list.size(), namespace_str, tag_name);
|
||||||
for (const auto& [model_namespace, model_list] : tag_data.models)
|
for (const auto& [model_namespace, model_list] : tag_data.models)
|
||||||
{
|
{
|
||||||
for (const auto& model : model_list)
|
for (const auto& model : model_list)
|
||||||
{
|
{
|
||||||
|
++tag_model_count;
|
||||||
insert_tag_model_stmt.bind().bind_all(namespace_str, tag_name, model_namespace, model);
|
insert_tag_model_stmt.bind().bind_all(namespace_str, tag_name, model_namespace, model);
|
||||||
if (!insert_tag_model_stmt.execute())
|
if (!insert_tag_model_stmt.execute())
|
||||||
BLT_WARN("[Model List] Unable to insert {}:{} into {}:{} reason '{}'", namespace_str, tag_name, model_namespace, model, db.get_error());
|
BLT_WARN("[Model List] Unable to insert {}:{} into {}:{} reason '{}'", namespace_str, tag_name, model_namespace, model,
|
||||||
|
db.get_error());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BLT_INFO("[Phase 2] Loaded {} blocks to tags.", tag_list_count);
|
||||||
|
BLT_INFO("[Phase 2] Loaded {} models to tags.", tag_model_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return db;
|
return db;
|
||||||
|
@ -440,10 +455,12 @@ void asset_loader_t::process_texture(const statement_t& stmt, const std::string&
|
||||||
if (!std::filesystem::exists(texture_path))
|
if (!std::filesystem::exists(texture_path))
|
||||||
return;
|
return;
|
||||||
int width, height, channels;
|
int width, height, channels;
|
||||||
const auto data = stbi_load(texture_path.c_str(), &width, &height, &channels, 4);
|
const auto data = stbi_loadf(texture_path.c_str(), &width, &height, &channels, 4);
|
||||||
if (data == nullptr)
|
if (data == nullptr)
|
||||||
return;
|
return;
|
||||||
stmt.bind().bind_all(namespace_str, texture, width, height, blt::span{data, static_cast<blt::size_t>(width * height * 4)});
|
stmt.bind().bind_all(namespace_str, texture, width, height, blt::span{
|
||||||
|
reinterpret_cast<char*>(data), static_cast<blt::size_t>(width * height * 4) * sizeof(float)
|
||||||
|
});
|
||||||
if (!stmt.execute())
|
if (!stmt.execute())
|
||||||
{
|
{
|
||||||
BLT_WARN("Failed to insert texture '{}:{}' into database. Error: '{}'", namespace_str, texture, db.get_error());
|
BLT_WARN("Failed to insert texture '{}:{}' into database. Error: '{}'", namespace_str, texture, db.get_error());
|
||||||
|
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* <Short Description>
|
||||||
|
* Copyright (C) 2025 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <blt/math/log_util.h>
|
||||||
|
#include <data_loader.h>
|
||||||
|
#include <blt/logging/logging.h>
|
||||||
|
|
||||||
|
database_t load_database(const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
database_t db{path.string()};
|
||||||
|
return db;
|
||||||
|
}
|
||||||
|
|
||||||
|
assets_t data_loader_t::load() const
|
||||||
|
{
|
||||||
|
constexpr auto SQL = "SELECT * FROM solid_textures";
|
||||||
|
const auto stmt = db->prepare(SQL);
|
||||||
|
|
||||||
|
assets_t assets;
|
||||||
|
|
||||||
|
while (stmt.execute().has_row())
|
||||||
|
{
|
||||||
|
auto column = stmt.fetch();
|
||||||
|
|
||||||
|
const auto [namespace_str, name, width, height, ptr] = column.get<std::string, std::string, blt::i32, blt::i32, const std::byte*>();
|
||||||
|
|
||||||
|
const auto size_floats = width * height * 4;
|
||||||
|
|
||||||
|
auto& namespace_hash = assets.images[namespace_str];
|
||||||
|
auto& image = namespace_hash[name];
|
||||||
|
image.width = width;
|
||||||
|
image.height = height;
|
||||||
|
image.data.resize(size_floats);
|
||||||
|
std::memcpy(image.data.data(), ptr, size_floats * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
return assets;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sample_pair
|
||||||
|
{
|
||||||
|
sample_pair(sampler_interface_t& s1, sampler_interface_t& s2): sample1{s1.get_sample()}, sample2{s2.get_sample()}
|
||||||
|
{}
|
||||||
|
|
||||||
|
[[nodiscard]] bool has_value() const
|
||||||
|
{
|
||||||
|
return sample1.has_value() && sample2.has_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const
|
||||||
|
{
|
||||||
|
return has_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<blt::vec3> sample1;
|
||||||
|
std::optional<blt::vec3> sample2;
|
||||||
|
};
|
||||||
|
|
||||||
|
sampler_one_point_t::sampler_one_point_t(const image_t& image)
|
||||||
|
{
|
||||||
|
float alpha = 0;
|
||||||
|
for (blt::i32 y = 0; y < image.height; y++)
|
||||||
|
{
|
||||||
|
for (blt::i32 x = 0; x < image.width; x++)
|
||||||
|
{
|
||||||
|
const auto a = image.data[y * image.width + x + 3];
|
||||||
|
average += blt::vec3{
|
||||||
|
image.data[y * image.width + x + 0], image.data[y * image.width + x + 1], image.data[y * image.width + x + 2]
|
||||||
|
} * a;
|
||||||
|
alpha += a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (alpha != 0)
|
||||||
|
average = average / (alpha / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
blt::vec3 comparator_euclidean_t::compare(sampler_interface_t& s1, sampler_interface_t& s2)
|
||||||
|
{
|
||||||
|
s1.clear();
|
||||||
|
s2.clear();
|
||||||
|
blt::vec3 total{};
|
||||||
|
while (auto sampler = sample_pair{s1, s2})
|
||||||
|
{
|
||||||
|
auto [sample1, sample2] = sampler;
|
||||||
|
const auto dif = *sample1 - *sample2;
|
||||||
|
total += dif * dif;
|
||||||
|
}
|
||||||
|
return {std::sqrt(total[0]), std::sqrt(total[1]), std::sqrt(total[2])};
|
||||||
|
}
|
33
src/main.cpp
33
src/main.cpp
|
@ -22,6 +22,8 @@
|
||||||
#include "blt/gfx/renderer/camera.h"
|
#include "blt/gfx/renderer/camera.h"
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <sql.h>
|
#include <sql.h>
|
||||||
|
#include <data_loader.h>
|
||||||
|
#include <blt/math/log_util.h>
|
||||||
|
|
||||||
blt::gfx::matrix_state_manager global_matrices;
|
blt::gfx::matrix_state_manager global_matrices;
|
||||||
blt::gfx::resource_manager resources;
|
blt::gfx::resource_manager resources;
|
||||||
|
@ -57,11 +59,31 @@ void destroy(const blt::gfx::window_data&)
|
||||||
blt::gfx::cleanup();
|
blt::gfx::cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void use_database(database_t& db)
|
||||||
|
{
|
||||||
|
const data_loader_t data{db};
|
||||||
|
auto assets = data.load();
|
||||||
|
|
||||||
|
const auto i1 = assets.images["minecraft"]["block/redstone_block"];
|
||||||
|
const auto i2 = assets.images["minecraft"]["block/red_wool"];
|
||||||
|
|
||||||
|
auto s1 = i1.get_default_sampler();
|
||||||
|
auto s2 = i2.get_default_sampler();
|
||||||
|
|
||||||
|
comparator_euclidean_t compare{};
|
||||||
|
|
||||||
|
const auto difference = compare.compare(s1, s2);
|
||||||
|
|
||||||
|
BLT_TRACE("{}", difference);
|
||||||
|
}
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::filesystem::remove("1.21.5.assets");
|
// std::filesystem::remove("1.21.5.assets");
|
||||||
// blt::gfx::init(blt::gfx::window_data{"Minecraft Color Picker", init, update, destroy}.setSyncInterval(1));
|
// blt::gfx::init(blt::gfx::window_data{"Minecraft Color Picker", init, update, destroy}.setSyncInterval(1));
|
||||||
|
|
||||||
|
if (!std::filesystem::exists("1.21.5.assets"))
|
||||||
|
{
|
||||||
asset_loader_t loader{"1.21.5"};
|
asset_loader_t loader{"1.21.5"};
|
||||||
|
|
||||||
if (const auto result = loader.load_assets("../res/assets", "../res/data"))
|
if (const auto result = loader.load_assets("../res/assets", "../res/data"))
|
||||||
|
@ -70,7 +92,14 @@ int main()
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& asset_data = loader.load_textures();
|
auto& db = loader.load_textures();
|
||||||
|
use_database(db);
|
||||||
|
} else {
|
||||||
|
auto db = load_database("1.21.5.assets");
|
||||||
|
use_database(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
|
@ -24,14 +24,10 @@ statement_t::statement_t(sqlite3* db, const std::string& stmt): db{db}
|
||||||
BLT_ERROR("Failed to create statement object '{}' cause '{}'", stmt, sqlite3_errmsg(db));
|
BLT_ERROR("Failed to create statement object '{}' cause '{}'", stmt, sqlite3_errmsg(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<bool> statement_t::execute() const
|
statement_result_t statement_t::execute() const
|
||||||
{
|
{
|
||||||
const auto v = sqlite3_step(statement);
|
const auto v = sqlite3_step(statement);
|
||||||
if (v == SQLITE_ROW)
|
return statement_result_t{v};
|
||||||
return true;
|
|
||||||
if (v == SQLITE_OK || v == SQLITE_DONE)
|
|
||||||
return false;
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
statement_t::~statement_t()
|
statement_t::~statement_t()
|
||||||
|
|
Loading…
Reference in New Issue