Skip to content
41 changes: 41 additions & 0 deletions orm_lib/inc/drogon/orm/Field.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,47 @@ class DROGON_EXPORT Field
return result_.getLength(row_, column_);
}

SqlType sqlType() const noexcept
{
return result_.getSqlType(column_);
}

/// Native database type name (VARCHAR, INT, DECIMAL, TINYINT, BIT, etc.)
const std::string &nativeTypeName() const noexcept
{
return result_.getNativeTypeName(column_);
}

/// Character length (VARCHAR)
int columnLength() const noexcept
{
return result_.getColumnLength(column_);
}

/// Numeric precision (DECIMAL / NUMERIC)
int precision() const noexcept
{
return result_.getPrecision(column_);
}

/// Numeric scale (DECIMAL / NUMERIC)
int scale() const noexcept
{
return result_.getScale(column_);
}

/// Is this column nullable?
bool isNullable() const noexcept
{
return result_.isNullable(column_);
}

/// Is this column unsigned?
bool isUnsigned() const noexcept
{
return result_.isUnsigned(column_);
}

/// Convert to a type T value
template <typename T>
T as() const
Expand Down
166 changes: 166 additions & 0 deletions orm_lib/inc/drogon/orm/Result.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <future>
#include <algorithm>
#include <assert.h>
#include <optional>

namespace drogon
{
Expand All @@ -34,12 +35,83 @@ class Row;
class ResultImpl;
using ResultImplPtr = std::shared_ptr<ResultImpl>;

enum class SqlType : uint8_t
{
Unknown = 0,

Bool,
Int,
Bit,
Float,
Double,
Decimal,

String,
Binary,

Json,

Date,
Time,
Year,
DateTime,
Timestamp,

Geometry
};

Comment thread
karthikeyan-netizen marked this conversation as resolved.
enum class SqlStatus
{
Ok,
End
};

/**
* @brief Column metadata from the database.
*
* Separates:
* - Logical type (type): Application-level abstraction for type handling
* - Native type (nativeType): Actual database type name (VARCHAR, DECIMAL,
* etc.)
* - Type attributes: length, precision, scale, unsigned, nullable
*
* Examples:
* DECIMAL(10,2)
* type = Decimal, nativeType = "DECIMAL", precision = 10, scale = 2
*
* VARCHAR(100)
* type = VarChar, nativeType = "VARCHAR", length = 100
*
* BIT(1)
* type = Bool, nativeType = "BIT", length = 1
*
* TINYINT(1)
* type = Bool, nativeType = "TINYINT", length = 1
*
* BIT(8)
* type = Bit, nativeType = "BIT", length = 8
*/
struct ColumnMeta
{
// Logical type.
SqlType type{SqlType::Unknown};

// Database-specific native type name.
std::string nativeType;

// Type-specific attributes.
// length is type-dependent: character and binary types use
// driver-reported byte width, while BIT uses number of bits.
// It is not decimal precision; DECIMAL uses precision and scale.
std::optional<int64_t> length;

std::optional<int> precision;
std::optional<int> scale;

bool nullable{false};
bool unsigned_{false};
};

/// Result set containing data returned by a query or command.
/** This behaves as a container (as defined by the C++ standard library) and
* provides random access const iterators to iterate over its rows. A row
Expand Down Expand Up @@ -139,6 +211,100 @@ class DROGON_EXPORT Result
*/
unsigned long long insertId() const noexcept;

/**
* @brief Get the logical SQL type of the specified column.
*
* @param column Zero-based index of the column (must be less than
* columns()).
* @return The abstracted SQL field type for the given column, or
* SqlType::Unknown if the type cannot be determined.
*
* @note Type metadata may only be fully populated for some database
* backends (for example, MySQL). For other backends, the result
* may be limited or fall back to SqlType::Unknown.
*/
SqlType getSqlType(SizeType column) const;

/**
* @brief Get the native database type name of the specified column.
*
* @param column Zero-based index of the column (must be less than
* columns()).
* @return A reference to the native type name reported by the underlying
* database driver, for example, "INT", "VARCHAR", or "DECIMAL".
*
* @note Type-name metadata may only be fully populated for some database
* backends. On other backends, the returned string may be empty or
* use a backend-specific representation.
*/
const std::string &getNativeTypeName(SizeType column) const;

/**
* @brief Get the defined maximum length of the specified column.
*
* @param column Zero-based index of the column (must be less than
* columns()).
* @return The type-specific length, or 0 if unavailable. For MySQL,
* VARCHAR, CHAR, and BLOB-family values are reported in bytes
* (not characters), while BIT is reported in bits. It is not
* populated for DECIMAL; use getPrecision() and getScale().
*
* @note Length metadata may only be populated for some database backends
* (for example, MySQL) and for certain column types (such as
* character and binary types).
*/
int getColumnLength(SizeType column) const;

/**
* @brief Get the numeric precision for the specified column.
*
* @param column Zero-based index of the column (must be less than
* columns()).
* @return The precision (total number of significant digits) for the
* column, as reported by the underlying database driver, or 0 if
* not applicable or not available.
*
* @note Precision is generally only meaningful for numeric types such as
* DECIMAL or NUMERIC. On other types, the value may be 0 or
* unspecified, and metadata may only be provided by some backends
* (for example, MySQL).
*/
int getPrecision(SizeType column) const;

/**
* @brief Get the numeric scale for the specified column.
*
* @param column Zero-based index of the column (must be less than
* columns()).
* @return The scale (number of fractional digits) for the column, as
* reported by the underlying database driver, or 0 if not
* applicable or not available.
*
* @note Scale is generally only meaningful for numeric types such as
* DECIMAL or NUMERIC. On other types, the value may be 0 or
* unspecified, and metadata may only be provided by some backends
* (for example, MySQL).
*/
int getScale(SizeType column) const;

/**
* @brief Check if the specified column is nullable.
*
* @param column Zero-based index of the column (must be less than
* columns()).
* @return True if the column is nullable, false otherwise.
*/
bool isNullable(SizeType column) const;

/**
* @brief Check if the specified column is unsigned.
*
* @param column Zero-based index of the column (must be less than
* columns()).
* @return True if the column is unsigned, false otherwise.
*/
bool isUnsigned(SizeType column) const;

#ifdef _MSC_VER
Result() noexcept = default;
#endif
Expand Down
35 changes: 35 additions & 0 deletions orm_lib/src/Result.cc
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,41 @@ unsigned long long Result::insertId() const noexcept
return resultPtr_->insertId();
}

SqlType Result::getSqlType(SizeType column) const
{
return resultPtr_->columnMeta(column).type;
}

const std::string &Result::getNativeTypeName(SizeType column) const
{
return resultPtr_->columnMeta(column).nativeType;
}

int Result::getColumnLength(SizeType column) const
{
return resultPtr_->columnMeta(column).length.value_or(0);
}

int Result::getPrecision(SizeType column) const
{
return resultPtr_->columnMeta(column).precision.value_or(0);
}

int Result::getScale(SizeType column) const
{
return resultPtr_->columnMeta(column).scale.value_or(0);
}

bool Result::isNullable(SizeType column) const
{
return resultPtr_->columnMeta(column).nullable;
}

bool Result::isUnsigned(SizeType column) const
{
return resultPtr_->columnMeta(column).unsigned_;
}

int Result::oid(RowSizeType column) const noexcept
{
return resultPtr_->oid(column);
Expand Down
7 changes: 7 additions & 0 deletions orm_lib/src/ResultImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ class ResultImpl : public trantor::NonCopyable
virtual bool isNull(SizeType row, RowSizeType column) const = 0;
virtual FieldSizeType getLength(SizeType row, RowSizeType column) const = 0;

virtual const ColumnMeta &columnMeta(SizeType column) const
{
(void)column;
static const ColumnMeta dummy{};
return dummy;
}

virtual unsigned long long insertId() const noexcept
{
return 0;
Expand Down
5 changes: 5 additions & 0 deletions orm_lib/src/mysql_impl/MysqlResultImpl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,8 @@ unsigned long long MysqlResultImpl::insertId() const noexcept
{
return insertId_;
}

const ColumnMeta &MysqlResultImpl::columnMeta(SizeType column) const
{
return columnMeta_.at(column);
}
Loading
Loading