5#if defined(_WIN32) || defined(_WIN64)
10#include "SqlConnection.hpp"
11#include "SqlQuery.hpp"
12#include "SqlServerType.hpp"
19#include <source_location>
36template <
typename QueryObject>
38 { queryObject.ToSql() } -> std::convertible_to<std::string>;
42class SqlVariantRowCursor;
75 [[nodiscard]] LIGHTWEIGHT_API
bool IsAlive() const noexcept;
78 [[nodiscard]] LIGHTWEIGHT_API
bool IsPrepared() const noexcept;
81 [[nodiscard]] LIGHTWEIGHT_API
SqlConnection& Connection() noexcept;
84 [[nodiscard]] LIGHTWEIGHT_API
SqlConnection const& Connection() const noexcept;
87 [[nodiscard]] LIGHTWEIGHT_API
SqlErrorInfo LastError() const;
94 std::string_view
const& tableAlias)
const;
97 [[nodiscard]] LIGHTWEIGHT_API SQLHSTMT NativeHandle() const noexcept;
103 LIGHTWEIGHT_API
void Prepare(std::string_view query) &;
118 [[nodiscard]] std::
string const& PreparedQuery() const noexcept;
121 template <SqlInputParameterBinder Arg>
122 void BindInputParameter(SQLSMALLINT columnIndex, Arg const& arg);
125 template <SqlInputParameterBinder Arg, typename ColumnName>
126 void BindInputParameter(SQLSMALLINT columnIndex, Arg const& arg, ColumnName&& columnNameHint);
129 template <SqlInputParameterBinder... Args>
143 template <SqlInputParameterBatchBinder FirstColumnBatch, std::ranges::contiguous_range... MoreColumnBatches>
144 [[nodiscard]]
SqlResultCursor ExecuteBatchNative(FirstColumnBatch const& firstColumnBatch,
145 MoreColumnBatches const&... moreColumnBatches);
155 template <SqlInputParameterBatchBinder FirstColumnBatch, std::ranges::range... MoreColumnBatches>
156 [[nodiscard]]
SqlResultCursor ExecuteBatchSoft(FirstColumnBatch const& firstColumnBatch,
157 MoreColumnBatches const&... moreColumnBatches);
164 template <SqlInputParameterBatchBinder FirstColumnBatch, std::ranges::range... MoreColumnBatches>
166 MoreColumnBatches const&... moreColumnBatches);
176 ExecuteDirect(std::string_view const& query, std::source_location location = std::source_location::current());
180 std::source_location location = std::source_location::current());
183 template <typename Callable>
185 void MigrateDirect(Callable const& callable, std::source_location location = std::source_location::current());
189 template <typename T>
191 [[nodiscard]] std::optional<T> ExecuteDirectScalar(std::string_view const& query,
192 std::source_location location = std::source_location::current());
195 template <typename T>
197 [[nodiscard]] T ExecuteDirectScalar(std::string_view const& query,
198 std::source_location location = std::source_location::current());
202 template <typename T>
204 [[nodiscard]] std::optional<T> ExecuteDirectScalar(
SqlQueryObject auto const& query,
205 std::source_location location = std::source_location::current());
208 template <typename T>
210 [[nodiscard]] T ExecuteDirectScalar(
SqlQueryObject auto const& query,
211 std::source_location location = std::source_location::current());
214 [[nodiscard]] LIGHTWEIGHT_API
size_t LastInsertId(std::string_view tableName);
219 [[nodiscard]] LIGHTWEIGHT_API
size_t NumRowsAffected() const;
220 [[nodiscard]] LIGHTWEIGHT_API
size_t NumColumnsAffected() const;
221 [[nodiscard]] LIGHTWEIGHT_API
bool FetchRow();
222 [[nodiscard]] LIGHTWEIGHT_API std::expected<
bool,
SqlErrorInfo> TryFetchRow(
223 std::source_location location = std::source_location::current()) noexcept;
224 void CloseCursor() noexcept;
226 template <SqlOutputColumnBinder... Args>
227 void BindOutputColumns(Args*... args);
229 template <typename... Records>
230 requires(((std::is_class_v<Records> && std::is_aggregate_v<Records>) && ...))
231 void BindOutputColumnsToRecord(Records*... records);
233 template <SqlOutputColumnBinder T>
234 void BindOutputColumn(SQLUSMALLINT columnIndex, T* arg);
236 template <SqlGetColumnNativeType T>
237 [[nodiscard]]
bool GetColumn(SQLUSMALLINT column, T* result) const;
239 template <SqlGetColumnNativeType T>
240 [[nodiscard]] T GetColumn(SQLUSMALLINT column) const;
242 template <SqlGetColumnNativeType T>
243 [[nodiscard]] std::optional<T> GetNullableColumn(SQLUSMALLINT column) const;
245 template <SqlGetColumnNativeType T>
246 [[nodiscard]] T GetColumnOr(SQLUSMALLINT column, T&& defaultValue) const;
248 LIGHTWEIGHT_API
void RequireSuccess(SQLRETURN error,
249 std::source_location sourceLocation = std::source_location::current()) const;
250 LIGHTWEIGHT_API
void PlanPostExecuteCallback(std::function<
void()>&& cb) override;
251 LIGHTWEIGHT_API
void PlanPostProcessOutputColumn(std::function<
void()>&& cb) override;
252 [[nodiscard]] LIGHTWEIGHT_API SqlServerType ServerType() const noexcept override;
253 [[nodiscard]] LIGHTWEIGHT_API std::
string const& DriverName() const noexcept override;
254 LIGHTWEIGHT_API
void ProcessPostExecuteCallbacks();
256 LIGHTWEIGHT_API SQLLEN* ProvideInputIndicator() override;
257 LIGHTWEIGHT_API SQLLEN* ProvideInputIndicators(
size_t rowCount) override;
258 LIGHTWEIGHT_API
void ClearBatchIndicators();
259 LIGHTWEIGHT_API
void RequireIndicators();
260 LIGHTWEIGHT_API SQLLEN* GetIndicatorForColumn(SQLUSMALLINT column) noexcept;
264 std::unique_ptr<Data,
void (*)(Data*)> m_data;
267 std::string m_preparedQuery;
268 std::optional<SQLSMALLINT> m_numColumns;
269 SQLSMALLINT m_expectedParameterCount {};
282 SqlResultCursor() =
delete;
283 SqlResultCursor(SqlResultCursor
const&) =
delete;
284 SqlResultCursor& operator=(SqlResultCursor
const&) =
delete;
288 m_stmt { other.m_stmt }
290 other.m_stmt =
nullptr;
298 m_stmt = other.m_stmt;
299 other.m_stmt =
nullptr;
308 m_stmt->CloseCursor();
316 return m_stmt->NumRowsAffected();
322 return m_stmt->NumColumnsAffected();
328 template <SqlOutputColumnBinder... Args>
331 m_stmt->BindOutputColumns(args...);
335 template <SqlOutputColumnBinder T>
338 m_stmt->BindOutputColumn(columnIndex, arg);
342 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
bool FetchRow()
344 return m_stmt->FetchRow();
348 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::expected<bool, SqlErrorInfo>
TryFetchRow(
349 std::source_location location = std::source_location::current()) noexcept
351 return m_stmt->TryFetchRow(location);
355 template <
typename... Records>
356 requires(((std::is_class_v<Records> && std::is_aggregate_v<Records>) && ...))
359 m_stmt->BindOutputColumnsToRecord(records...);
365 template <SqlGetColumnNativeType T>
366 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
bool GetColumn(SQLUSMALLINT column, T* result)
const
368 return m_stmt->GetColumn<T>(column, result);
372 template <SqlGetColumnNativeType T>
373 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE T
GetColumn(SQLUSMALLINT column)
const
375 return m_stmt->GetColumn<T>(column);
381 template <SqlGetColumnNativeType T>
382 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE std::optional<T>
GetNullableColumn(SQLUSMALLINT column)
const
384 return m_stmt->GetNullableColumn<T>(column);
390 template <SqlGetColumnNativeType T>
391 [[nodiscard]] T
GetColumnOr(SQLUSMALLINT column, T&& defaultValue)
const
393 return m_stmt->GetColumnOr(column, std::forward<T>(defaultValue));
400struct [[nodiscard]] SqlSentinelIterator
404class [[nodiscard]] SqlVariantRowIterator
407 explicit SqlVariantRowIterator(SqlSentinelIterator )
noexcept:
412 explicit SqlVariantRowIterator(SqlResultCursor& cursor)
noexcept:
413 _numResultColumns {
static_cast<SQLUSMALLINT
>(cursor.NumColumnsAffected()) },
416 _row.reserve(_numResultColumns);
420 SqlVariantRow& operator*() noexcept
425 SqlVariantRow
const& operator*() const noexcept
430 SqlVariantRowIterator& operator++() noexcept
432 _end = !_cursor->FetchRow();
436 for (
auto const i: std::views::iota(SQLUSMALLINT(1), SQLUSMALLINT(_numResultColumns + 1)))
437 _row.emplace_back(_cursor->GetColumn<SqlVariant>(i));
442 bool operator!=(SqlSentinelIterator )
const noexcept
447 bool operator!=(SqlVariantRowIterator
const& )
const noexcept
454 SQLUSMALLINT _numResultColumns = 0;
455 SqlResultCursor* _cursor;
459class [[nodiscard]] SqlVariantRowCursor
462 explicit SqlVariantRowCursor(SqlResultCursor&& cursor):
463 _resultCursor { std::move(cursor) }
467 SqlVariantRowIterator begin() noexcept
469 return SqlVariantRowIterator { _resultCursor };
472 static SqlSentinelIterator end() noexcept
474 return SqlSentinelIterator {};
478 SqlResultCursor _resultCursor;
506 _connection { &conn }
513 using difference_type = bool;
514 using value_type = T;
516 iterator& operator++()
520 _is_end = !_cursor->FetchRow();
527 LIGHTWEIGHT_FORCE_INLINE value_type operator*() noexcept
531 Reflection::EnumerateMembers(res, [
this]<
size_t I>(
auto&& value) {
532 auto tmp = _cursor->GetColumn<
typename Reflection::MemberTypeOf<I, value_type>::ValueType>(I + 1);
539 LIGHTWEIGHT_FORCE_INLINE
constexpr bool operator!=(iterator
const& other)
const noexcept
541 return _is_end != other._is_end;
544 constexpr iterator(std::default_sentinel_t )
noexcept:
546 _cursor { std::nullopt }
550 explicit iterator(SqlConnection& conn):
551 _stmt { std::make_unique<SqlStatement>(conn) },
552 _cursor { std::nullopt }
556 LIGHTWEIGHT_FORCE_INLINE SqlStatement& Statement() noexcept
561 void SetCursor(SqlResultCursor cursor)
noexcept
563 _cursor.emplace(std::move(cursor));
567 bool _is_end =
false;
568 std::unique_ptr<SqlStatement> _stmt;
569 std::optional<SqlResultCursor> _cursor;
575 auto it = iterator { *_connection };
576 auto& stmt = it.Statement();
577 stmt.Prepare(it.Statement().Query(RecordTableName<T>).Select().template Fields<T>().All());
578 it.SetCursor(stmt.Execute());
586 return iterator { std::default_sentinel };
596 return m_connection && m_connection->
IsAlive() && m_hStmt !=
nullptr;
601 return !m_preparedQuery.empty();
606 return *m_connection;
611 return *m_connection;
626 Prepare(queryObject.ToSql());
631 return Prepare(queryObject.ToSql());
636 return m_preparedQuery;
640template <SqlOutputColumnBinder... Args>
641inline LIGHTWEIGHT_FORCE_INLINE
void SqlStatement::BindOutputColumns(Args*... args)
646 ((++i, RequireSuccess(SqlDataBinder<Args>::OutputColumn(m_hStmt, i, args, GetIndicatorForColumn(i), *
this))), ...);
649template <
typename... Records>
650 requires(((std::is_class_v<Records> && std::is_aggregate_v<Records>) && ...))
651void SqlStatement::BindOutputColumnsToRecord(Records*... records)
656 ((Reflection::EnumerateMembers(*records,
657 [
this, &i]<
size_t I,
typename FieldType>(FieldType& value) {
659 RequireSuccess(SqlDataBinder<FieldType>::OutputColumn(
660 m_hStmt, i, &value, GetIndicatorForColumn(i), *
this));
666template <SqlOutputColumnBinder T>
667inline LIGHTWEIGHT_FORCE_INLINE
void SqlStatement::BindOutputColumn(SQLUSMALLINT columnIndex, T* arg)
671 RequireSuccess(SqlDataBinder<T>::OutputColumn(m_hStmt, columnIndex, arg, GetIndicatorForColumn(columnIndex), *
this));
675template <SqlInputParameterBinder Arg>
679 m_expectedParameterCount = (std::numeric_limits<
decltype(m_expectedParameterCount)>::max)();
680 RequireSuccess(SqlDataBinder<Arg>::InputParameter(m_hStmt,
static_cast<SQLUSMALLINT
>(columnIndex), arg, *
this));
684template <SqlInputParameterBinder Arg,
typename ColumnName>
687 ColumnName&& columnNameHint)
693template <SqlInputParameterBinder... Args>
702 if (!(m_expectedParameterCount == (std::numeric_limits<
decltype(m_expectedParameterCount)>::max)()
703 &&
sizeof...(args) == 0)
704 && !(m_expectedParameterCount ==
sizeof...(args)))
705 throw std::invalid_argument {
"Invalid argument count" };
710 RequireSuccess(SqlDataBinder<Args>::InputParameter(m_hStmt, i, args, *
this))),
713 auto const result = SQLExecute(m_hStmt);
715 if (result != SQL_NO_DATA && result != SQL_SUCCESS && result != SQL_SUCCESS_WITH_INFO)
718 ProcessPostExecuteCallbacks();
724concept SqlNativeContiguousValueConcept =
725 std::same_as<T, bool>
726 || std::same_as<T, char>
727 || std::same_as<T, unsigned char>
728 || std::same_as<T, wchar_t>
729 || std::same_as<T, std::int16_t>
730 || std::same_as<T, std::uint16_t>
731 || std::same_as<T, std::int32_t>
732 || std::same_as<T, std::uint32_t>
733 || std::same_as<T, std::int64_t>
734 || std::same_as<T, std::uint64_t>
735 || std::same_as<T, float>
736 || std::same_as<T, double>
737 || std::same_as<T, SqlDate>
738 || std::same_as<T, SqlTime>
739 || std::same_as<T, SqlDateTime>
740 || std::same_as<T, SqlFixedString<T::Capacity, typename T::value_type, T::PostRetrieveOperation>>;
742template <
typename FirstColumnBatch,
typename... MoreColumnBatches>
743concept SqlNativeBatchable =
744 std::ranges::contiguous_range<FirstColumnBatch>
745 && (std::ranges::contiguous_range<MoreColumnBatches> && ...)
746 && SqlNativeContiguousValueConcept<std::ranges::range_value_t<FirstColumnBatch>>
747 && (SqlNativeContiguousValueConcept<std::ranges::range_value_t<MoreColumnBatches>> && ...);
751template <SqlInputParameterBatchBinder FirstColumnBatch, std::ranges::contiguous_range... MoreColumnBatches>
753 MoreColumnBatches
const&... moreColumnBatches)
755 static_assert(SqlNativeBatchable<FirstColumnBatch, MoreColumnBatches...>,
756 "Must be a supported native contiguous element type.");
758 if (m_expectedParameterCount != 1 +
sizeof...(moreColumnBatches))
759 throw std::invalid_argument {
"Invalid number of columns" };
761 auto const rowCount = std::ranges::size(firstColumnBatch);
762 if (!((std::size(moreColumnBatches) == rowCount) && ...))
763 throw std::invalid_argument {
"Uneven number of rows" };
769 RequireSuccess(SQLSetStmtAttr(m_hStmt, SQL_ATTR_PARAMSET_SIZE, (SQLPOINTER) rowCount, 0));
770 RequireSuccess(SQLSetStmtAttr(m_hStmt, SQL_ATTR_PARAM_BIND_OFFSET_PTR, &rowStart, 0));
771 RequireSuccess(SQLSetStmtAttr(m_hStmt, SQL_ATTR_PARAM_BIND_TYPE, SQL_PARAM_BIND_BY_COLUMN, 0));
772 RequireSuccess(SQLSetStmtAttr(m_hStmt, SQL_ATTR_PARAM_OPERATION_PTR, SQL_PARAM_PROCEED, 0));
773 ClearBatchIndicators();
774 RequireSuccess(SqlDataBinder<std::remove_cvref_t<
decltype(*std::ranges::data(firstColumnBatch))>>::
775 BatchInputParameter(m_hStmt, 1, std::ranges::data(firstColumnBatch), rowCount, *
this));
776 SQLUSMALLINT column = 1;
777 (RequireSuccess(SqlDataBinder<std::remove_cvref_t<
decltype(*std::ranges::data(moreColumnBatches))>>::
778 BatchInputParameter(m_hStmt, ++column, std::ranges::data(moreColumnBatches), rowCount, *
this)),
780 RequireSuccess(SQLExecute(m_hStmt));
781 ProcessPostExecuteCallbacks();
787template <SqlInputParameterBatchBinder FirstColumnBatch, std::ranges::range... MoreColumnBatches>
789 MoreColumnBatches
const&... moreColumnBatches)
793 if constexpr (SqlNativeBatchable<FirstColumnBatch, MoreColumnBatches...>)
799template <SqlInputParameterBatchBinder FirstColumnBatch, std::ranges::range... MoreColumnBatches>
801 MoreColumnBatches
const&... moreColumnBatches)
803 if (m_expectedParameterCount != 1 +
sizeof...(moreColumnBatches))
804 throw std::invalid_argument {
"Invalid number of columns" };
806 auto const rowCount = std::ranges::size(firstColumnBatch);
807 if (!((std::size(moreColumnBatches) == rowCount) && ...))
808 throw std::invalid_argument {
"Uneven number of rows" };
810 for (
auto const rowIndex: std::views::iota(
size_t { 0 }, rowCount))
813 [&]<SqlInputParameterBinder... ColumnValues>(ColumnValues
const&... columnsInRow) {
814 SQLUSMALLINT column = 0;
815 ((++column, SqlDataBinder<ColumnValues>::InputParameter(m_hStmt, column, columnsInRow, *this)), ...);
816 RequireSuccess(SQLExecute(m_hStmt));
817 ProcessPostExecuteCallbacks();
820 std::ref(*std::ranges::next(std::ranges::begin(firstColumnBatch),
static_cast<std::ptrdiff_t
>(rowIndex))),
822 *std::ranges::next(std::ranges::begin(moreColumnBatches),
static_cast<std::ptrdiff_t
>(rowIndex)))...));
827template <SqlGetColumnNativeType T>
828inline bool SqlStatement::GetColumn(SQLUSMALLINT column, T* result)
const
831 RequireSuccess(SqlDataBinder<T>::GetColumn(m_hStmt, column, result, &indicator, *
this));
832 return indicator != SQL_NULL_DATA;
838 template <
typename T>
839 concept SqlNullableType = (std::same_as<T, SqlVariant> || IsSpecializationOf<std::optional, T>);
843template <SqlGetColumnNativeType T>
844inline T SqlStatement::GetColumn(SQLUSMALLINT column)
const
848 RequireSuccess(SqlDataBinder<T>::GetColumn(m_hStmt, column, &result, &indicator, *
this));
849 if constexpr (!detail::SqlNullableType<T>)
850 if (indicator == SQL_NULL_DATA)
851 throw std::runtime_error {
"Column value is NULL" };
855template <SqlGetColumnNativeType T>
856inline std::optional<T> SqlStatement::GetNullableColumn(SQLUSMALLINT column)
const
860 RequireSuccess(SqlDataBinder<T>::GetColumn(m_hStmt, column, &result, &indicator, *
this));
861 if (indicator == SQL_NULL_DATA)
863 return { std::move(result) };
866template <SqlGetColumnNativeType T>
867T SqlStatement::GetColumnOr(SQLUSMALLINT column, T&& defaultValue)
const
869 return GetNullableColumn<T>(column).value_or(std::forward<T>(defaultValue));
873 std::source_location location)
878template <
typename Callable>
879 requires std::invocable<Callable, SqlMigrationQueryBuilder&>
884 auto const queries = migration.GetPlan().ToSql();
885 for (
auto const& query: queries)
887 [[maybe_unused]]
auto cursor =
ExecuteDirect(query, location);
892 requires(!std::same_as<T, SqlVariant>)
895 auto cursor = ExecuteDirect(query, location);
896 RequireSuccess(FetchRow());
897 return GetNullableColumn<T>(1);
901 requires(std::same_as<T, SqlVariant>)
904 auto cursor = ExecuteDirect(query, location);
905 RequireSuccess(FetchRow());
906 if (
auto result = GetNullableColumn<T>(1); result.has_value())
912 requires(!std::same_as<T, SqlVariant>)
915 return ExecuteDirectScalar<T>(query.ToSql(), location);
919 requires(std::same_as<T, SqlVariant>)
922 return ExecuteDirectScalar<T>(query.ToSql(), location);
925inline LIGHTWEIGHT_FORCE_INLINE
void SqlStatement::CloseCursor() noexcept
928 SQLFreeStmt(m_hStmt, SQL_CLOSE);
Represents a connection to a SQL database.
LIGHTWEIGHT_API bool IsAlive() const noexcept
Tests if the connection is still active.
SqlQueryFormatter const & QueryFormatter() const noexcept
Retrieves a query formatter suitable for the SQL server being connected.
virtual void OnExecute(std::string_view const &query)=0
Invoked when a prepared query is executed.
static LIGHTWEIGHT_API SqlLogger & GetLogger()
Retrieves the currently configured logger.
virtual void OnFetchEnd()=0
Invoked when fetching is done.
void OnBindInputParameter(std::string_view const &name, T &&value)
Invoked when an input parameter is bound.
Query builder for building SQL migration queries.
API Entry point for building SQL queries.
API for reading an SQL query result set.
LIGHTWEIGHT_FORCE_INLINE void BindOutputColumnsToRecord(Records *... records)
Binds the given records to the prepared statement to store the fetched data to.
constexpr SqlResultCursor(SqlResultCursor &&other) noexcept
Move constructor.
LIGHTWEIGHT_FORCE_INLINE SqlResultCursor(SqlStatement &stmt) noexcept
Constructs a result cursor for the given SQL statement.
constexpr SqlResultCursor & operator=(SqlResultCursor &&other) noexcept
Move assignment operator.
LIGHTWEIGHT_FORCE_INLINE bool GetColumn(SQLUSMALLINT column, T *result) const
LIGHTWEIGHT_FORCE_INLINE void BindOutputColumns(Args *... args)
LIGHTWEIGHT_FORCE_INLINE std::optional< T > GetNullableColumn(SQLUSMALLINT column) const
LIGHTWEIGHT_FORCE_INLINE T GetColumn(SQLUSMALLINT column) const
Retrieves the value of the column at the given index for the currently selected row.
T GetColumnOr(SQLUSMALLINT column, T &&defaultValue) const
LIGHTWEIGHT_FORCE_INLINE size_t NumColumnsAffected() const
Retrieves the number of columns affected by the last query.
LIGHTWEIGHT_FORCE_INLINE size_t NumRowsAffected() const
Retrieves the number of rows affected by the last query.
LIGHTWEIGHT_FORCE_INLINE void BindOutputColumn(SQLUSMALLINT columnIndex, T *arg)
Binds a single output column at the given index to store fetched data.
LIGHTWEIGHT_FORCE_INLINE bool FetchRow()
Fetches the next row of the result set.
LIGHTWEIGHT_FORCE_INLINE std::expected< bool, SqlErrorInfo > TryFetchRow(std::source_location location=std::source_location::current()) noexcept
Attempts to fetch the next row, returning an error info on failure instead of throwing.
SQL query result row iterator.
SqlRowIterator(SqlConnection &conn)
Constructs a row iterator using the given SQL connection.
iterator end() noexcept
Returns a sentinel iterator representing the end of the result set.
iterator begin()
Returns an iterator to the first row of the result set.
High level API for (prepared) raw SQL statements.
LIGHTWEIGHT_API void Prepare(std::string_view query) &
LIGHTWEIGHT_API SQLHSTMT NativeHandle() const noexcept
Retrieves the native handle of the statement.
LIGHTWEIGHT_API SqlQueryBuilder QueryAs(std::string_view const &table, std::string_view const &tableAlias) const
Creates a new query builder for the given table with an alias, compatible with the SQL server being c...
void MigrateDirect(Callable const &callable, std::source_location location=std::source_location::current())
Executes an SQL migration query, as created b the callback.
LIGHTWEIGHT_API SqlConnection & Connection() noexcept
Retrieves the connection associated with this statement.
std::string const & PreparedQuery() const noexcept
Retrieves the last prepared query string.
SqlResultCursor Execute(Args const &... args)
Binds the given arguments to the prepared statement and executes it.
SqlResultCursor ExecuteBatch(FirstColumnBatch const &firstColumnBatch, MoreColumnBatches const &... moreColumnBatches)
LIGHTWEIGHT_API SqlErrorInfo LastError() const
Retrieves the last error information with respect to this SQL statement handle.
LIGHTWEIGHT_API SqlStatement(SqlStatement &&other) noexcept
Move constructor.
LIGHTWEIGHT_API SqlStatement()
Construct a new SqlStatement object, using a new connection, and connect to the default database.
LIGHTWEIGHT_API bool IsPrepared() const noexcept
Checks whether the statement has been prepared.
void BindInputParameter(SQLSMALLINT columnIndex, Arg const &arg)
Binds an input parameter to the prepared statement at the given column index.
LIGHTWEIGHT_API SqlStatement & operator=(SqlStatement &&other) noexcept
Move assignment operator.
LIGHTWEIGHT_API SqlStatement(std::nullopt_t)
Construct a new empty SqlStatement object. No SqlConnection is associated with this statement.
LIGHTWEIGHT_API SqlResultCursor ExecuteDirect(std::string_view const &query, std::source_location location=std::source_location::current())
Executes the given query directly.
LIGHTWEIGHT_API bool IsAlive() const noexcept
Checks whether the statement's connection is alive and the statement handle is valid.
std::optional< T > ExecuteDirectScalar(std::string_view const &query, std::source_location location=std::source_location::current())
SqlResultCursor ExecuteBatchNative(FirstColumnBatch const &firstColumnBatch, MoreColumnBatches const &... moreColumnBatches)
LIGHTWEIGHT_API SqlStatement(SqlConnection &relatedConnection)
Construct a new SqlStatement object, using the given connection.
SqlResultCursor ExecuteBatchSoft(FirstColumnBatch const &firstColumnBatch, MoreColumnBatches const &... moreColumnBatches)
Represents an SQL query object, that provides a ToSql() method.
constexpr auto SqlNullValue
Represents an ODBC SQL error.
static SqlErrorInfo FromStatementHandle(SQLHSTMT hStmt)
Constructs an ODBC error info object from the given ODBC statement handle.
A non-owning reference to a raw column data for batch processing.
Represents a value that can be any of the supported SQL data types.