<commit_before>#pragma once

#include "debug.h"
#include "string.h"
#include "utilities.h"

#include <atomic>
#include <cstddef>
#include <fcntl.h>
#include <functional>
#include <mutex>
#include <optional>

#if __has_include(<mysql.h>) && __has_include(<errmsg.h>)
#define SIMLIB_MYSQL_ENABLED 1
#include <errmsg.h>
#include <mysql.h>

#if 0
#warning "Before committing disable this debug"
#define DEBUG_MYSQL(...) __VA_ARGS__
#define NO_DEBUG_MYSQL(...)
#else
#define DEBUG_MYSQL(...)
#define NO_DEBUG_MYSQL(...) __VA_ARGS__
#endif

template <class...>
constexpr bool is_enum_val = false;

template <class T>
constexpr bool is_enum_val<EnumVal<T>> = true;

template <class T>
struct EnumValTypeHelper {
	using type = void;
};

template <class T>
struct EnumValTypeHelper<EnumVal<T>> {
	using type = T;
};

template <class T>
using EnumValType = typename EnumValTypeHelper<T>::type;

namespace MySQL {

// Optional type used to access data retrieved from MySQL
template <class T>
class Optional {
	using StoredType = std::remove_const_t<T>;
	StoredType value_; // This optional always need to contain value
	my_bool has_no_value_;

	friend class Statement;

public:
	Optional() : has_no_value_(true) {}

	Optional(const Optional&) = default;
	Optional(Optional&&) = default;

	// As optional may hold InplaceBuff<>, changing its value when it is
	// bounded is dangerous (may result in buffer overflow, as we store in
	// MYSQL_BIND its max_size() along with data pointer which may become
	// invalid after the assignment)
	Optional& operator=(const Optional&) = delete;
	Optional& operator=(Optional&&) = delete;

	Optional(const T& value) : value_(value), has_no_value_(false) {}

	Optional(T&& value) : value_(std::move(value)), has_no_value_(false) {}

	operator std::optional<T>() const { return opt(); }

	template <class U = T>
	operator std::enable_if_t<is_enum_val<U>, std::optional<EnumValType<T>>>()
	   const {
		return has_no_value_ ? std::optional<T>() : value_;
	}

	std::optional<T> opt() const {
		return has_no_value_ ? std::optional<T>() : value_;
	}

	constexpr explicit operator bool() const noexcept {
		return not has_no_value_;
	}

	constexpr const T& operator*() const { return value_; }

	constexpr const T* operator->() const { return std::addressof(value_); }

	constexpr bool has_value() const noexcept { return not has_no_value_; }

	constexpr const T& value() const {
		if (has_no_value_)
			THROW("bad optional access");

		return value_;
	}

	template <class U>
	constexpr T value_or(U&& default_value) const {
		return (has_no_value_ ? std::forward<U>(default_value) : value_);
	}
};

template <class...>
constexpr bool is_optional = false;

template <class T>
constexpr bool is_optional<Optional<T>> = true;

class Connection;

class Result {
private:
	friend Connection;

	size_t* connection_referencing_objects_no_;
	MYSQL_RES* res_;
	MYSQL_ROW row_ {};
	unsigned long* lengths_ {};

	Result(MYSQL_RES* res, size_t& conn_ref_objs_no)
	   : connection_referencing_objects_no_(&conn_ref_objs_no), res_(res) {
		++conn_ref_objs_no;
	}

	Result(const Result&) = delete;
	Result& operator=(const Result&) = delete;

public:
	Result(Result&& r) noexcept
	   : connection_referencing_objects_no_(
	        std::exchange(r.connection_referencing_objects_no_, nullptr)),
	     res_(std::exchange(r.res_, nullptr)), row_(std::move(r.row_)),
	     lengths_(r.lengths_) {
		// r.row_ = {};
		// r.lengths_ does not have to be changed
	}

	Result& operator=(Result&& r) {
		if (res_)
			mysql_free_result(res_);
		if (connection_referencing_objects_no_)
			--*connection_referencing_objects_no_;

		connection_referencing_objects_no_ =
		   std::exchange(r.connection_referencing_objects_no_, nullptr);
		res_ = std::exchange(r.res_, nullptr);
		row_ = std::move(r.row_);
		lengths_ = r.lengths_;

		// r.row_ = {};
		// r.lengths_ does not have to be changed
		return *this;
	}

	~Result() {
		if (res_)
			mysql_free_result(res_);
		if (connection_referencing_objects_no_)
			--*connection_referencing_objects_no_;
	}

	MYSQL_RES* impl() noexcept { return res_; }

	operator MYSQL_RES*() noexcept { return impl(); }

	bool next() noexcept {
		if ((row_ = mysql_fetch_row(res_)) and
		    (lengths_ = mysql_fetch_lengths(res_))) {
			return true;
		}

		return false;
	}

	unsigned fields_num() noexcept { return mysql_num_fields(res_); }

	my_ulonglong rows_num() noexcept { return mysql_num_rows(res_); }

	bool is_null(unsigned idx) NO_DEBUG_MYSQL(noexcept) {
		DEBUG_MYSQL(throw_assert(idx < fields_num());)
		return (row_[idx] == nullptr);
	}

	StringView operator[](unsigned idx) {
		STACK_UNWINDING_MARK;
		DEBUG_MYSQL(throw_assert(idx < fields_num());)
		if (is_null(idx))
			THROW("Encountered NULL at column ", idx, " that did not expect nullable data");

		return {row_[idx], lengths_[idx]};
	}

	Optional<StringView> opt(unsigned idx) NO_DEBUG_MYSQL(noexcept) {
		if (is_null(idx))
			return {};

		return {(*this)[idx]};<commit_msg>Ran clang-format<commit_after>#pragma once

#include "debug.h"
#include "string.h"
#include "utilities.h"

#include <atomic>
#include <cstddef>
#include <fcntl.h>
#include <functional>
#include <mutex>
#include <optional>

#if __has_include(<mysql.h>) && __has_include(<errmsg.h>)
#define SIMLIB_MYSQL_ENABLED 1
#include <errmsg.h>
#include <mysql.h>

#if 0
#warning "Before committing disable this debug"
#define DEBUG_MYSQL(...) __VA_ARGS__
#define NO_DEBUG_MYSQL(...)
#else
#define DEBUG_MYSQL(...)
#define NO_DEBUG_MYSQL(...) __VA_ARGS__
#endif

template <class...>
constexpr bool is_enum_val = false;

template <class T>
constexpr bool is_enum_val<EnumVal<T>> = true;

template <class T>
struct EnumValTypeHelper {
	using type = void;
};

template <class T>
struct EnumValTypeHelper<EnumVal<T>> {
	using type = T;
};

template <class T>
using EnumValType = typename EnumValTypeHelper<T>::type;

namespace MySQL {

// Optional type used to access data retrieved from MySQL
template <class T>
class Optional {
	using StoredType = std::remove_const_t<T>;
	StoredType value_; // This optional always need to contain value
	my_bool has_no_value_;

	friend class Statement;

public:
	Optional() : has_no_value_(true) {}

	Optional(const Optional&) = default;
	Optional(Optional&&) = default;

	// As optional may hold InplaceBuff<>, changing its value when it is
	// bounded is dangerous (may result in buffer overflow, as we store in
	// MYSQL_BIND its max_size() along with data pointer which may become
	// invalid after the assignment)
	Optional& operator=(const Optional&) = delete;
	Optional& operator=(Optional&&) = delete;

	Optional(const T& value) : value_(value), has_no_value_(false) {}

	Optional(T&& value) : value_(std::move(value)), has_no_value_(false) {}

	operator std::optional<T>() const { return opt(); }

	template <class U = T>
	operator std::enable_if_t<is_enum_val<U>, std::optional<EnumValType<T>>>()
	   const {
		return has_no_value_ ? std::optional<T>() : value_;
	}

	std::optional<T> opt() const {
		return has_no_value_ ? std::optional<T>() : value_;
	}

	constexpr explicit operator bool() const noexcept {
		return not has_no_value_;
	}

	constexpr const T& operator*() const { return value_; }

	constexpr const T* operator->() const { return std::addressof(value_); }

	constexpr bool has_value() const noexcept { return not has_no_value_; }

	constexpr const T& value() const {
		if (has_no_value_)
			THROW("bad optional access");

		return value_;
	}

	template <class U>
	constexpr T value_or(U&& default_value) const {
		return (has_no_value_ ? std::forward<U>(default_value) : value_);
	}
};

template <class...>
constexpr bool is_optional = false;

template <class T>
constexpr bool is_optional<Optional<T>> = true;

class Connection;

class Result {
private:
	friend Connection;

	size_t* connection_referencing_objects_no_;
	MYSQL_RES* res_;
	MYSQL_ROW row_ {};
	unsigned long* lengths_ {};

	Result(MYSQL_RES* res, size_t& conn_ref_objs_no)
	   : connection_referencing_objects_no_(&conn_ref_objs_no), res_(res) {
		++conn_ref_objs_no;
	}

	Result(const Result&) = delete;
	Result& operator=(const Result&) = delete;

public:
	Result(Result&& r) noexcept
	   : connection_referencing_objects_no_(
	        std::exchange(r.connection_referencing_objects_no_, nullptr)),
	     res_(std::exchange(r.res_, nullptr)), row_(std::move(r.row_)),
	     lengths_(r.lengths_) {
		// r.row_ = {};
		// r.lengths_ does not have to be changed
	}

	Result& operator=(Result&& r) {
		if (res_)
			mysql_free_result(res_);
		if (connection_referencing_objects_no_)
			--*connection_referencing_objects_no_;

		connection_referencing_objects_no_ =
		   std::exchange(r.connection_referencing_objects_no_, nullptr);
		res_ = std::exchange(r.res_, nullptr);
		row_ = std::move(r.row_);
		lengths_ = r.lengths_;

		// r.row_ = {};
		// r.lengths_ does not have to be changed
		return *this;
	}

	~Result() {
		if (res_)
			mysql_free_result(res_);
		if (connection_referencing_objects_no_)
			--*connection_referencing_objects_no_;
	}

	MYSQL_RES* impl() noexcept { return res_; }

	operator MYSQL_RES*() noexcept { return impl(); }

	bool next() noexcept {
		if ((row_ = mysql_fetch_row(res_)) and
		    (lengths_ = mysql_fetch_lengths(res_))) {
			return true;
		}

		return false;
	}

	unsigned fields_num() noexcept { return mysql_num_fields(res_); }

	my_ulonglong rows_num() noexcept { return mysql_num_rows(res_); }

	bool is_null(unsigned idx) NO_DEBUG_MYSQL(noexcept) {
		DEBUG_MYSQL(throw_assert(idx < fields_num());)
		return (row_[idx] == nullptr);
	}

	StringView operator[](unsigned idx) {
		STACK_UNWINDING_MARK;
		DEBUG_MYSQL(throw_assert(idx < fields_num());)
		if (is_null(idx)) {
			THROW("Encountered NULL at column ", idx,
			      " that did not expect nullable data");
		}

		return {row_[idx], lengths_[idx]};
	}

	Optional<StringView> opt(unsigned idx) NO_DEBUG_MYSQL(noexcept) {
		if (is_null(idx))
			return {};

		return {(*this)[idx]};
{'fraction_non_alphanumeric': 0.13042168674698795, 'fraction_numerical': 0.00040160642570281126, 'mean_word_length': 4.873231132075472, 'pattern_counts': {'":': 0, '<': 85, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5167487', 'n_tokens_mistral': 3602, 'n_tokens_neox': 3421, 'n_words': 860}