Differences between sqlpp11 and sqlpp23

August 3, 2025 ยท View on GitHub

< Index

Differences between sqlpp11 and sqlpp23

Below is a (probably incomplete) list of differences as of June 2025. For additional changes, see change log.

If seems a bit dry, follow the links to examples.

%sqlpp11sqlpp23
IDE code completion
statement data membersall publicfewer and private (less noisy)
prepared statement data membersall publiconly API public (less noisy)
connection functionsall publiconly API public (less noisy)
Data types
nullable valuessqlpp::value_or_nullstd::optional
NULLsqlpp::nullstd::nullopt
date and timeday_point, time_point, and time_of_day are represented as sqlpp::chrono::day_point, sqlpp::chrono::microsecond_point, and std::chrono::microsecondsdate, timestamp, time are represented as std::chrono::sys_days, std::chrono::sys_time<std::chrono::microseconds>, and std::chrono::microseconds
Result row
result fieldsspecializations of the result_field_t templatestandard types, like int64_t, std::optional<int64_t>, or std::string_view
TEXT result fieldsconvertible to std::stringstd::string_view
BLOB result fieldsconvertible to std::vector<uint8_t>std::span<uint8_t>
programmatic accessfor_each_fieldresult_row_t::as_tuple()
Names
creating namesSQLPP_ALIAS_PROVIDERSQLPP_CREATE_NAME_TAG
creating quoted namesSQLPP_QUOTED_ALIAS_PROVIDERSQLPP_CREATE_QUOTED_NAME_TAG
Dynamic queries
clausesseparate calls to add dynamic parts with very few compile time checksdirectly embedded in statement using dynamic() with many compile time checks
where conditionsdynamic and supported without nestingdynamic and and or supported at any nesting level
result fieldsdynamic result fields in std::map<std::string, std::string>correctly typed and named data members of result rows
Database connection
connectconnectUsingconnect_using
operator()executes statements, but not stringsexecutes statements and strings
executeexecutes strings and non-select statementsdropped
queryexecutes select statementsdropped
exceptionsmany individual exception classes for PostgreSQL, but not for other connectorsexception classes for each connector to transport native error codes
Constraints
read-only columnse.g. for auto-incrementfor generated columns (GENERATED)
required wherein select, update, removedropped
unconditionally()to explicitly omit where or on condition in joinsdropped
Clauses
SELECTselect flags like DISTINCT require calling separate function flags()flags can be passed as parameters to the select function
DELETE FROMremove_fromdelete_from
LIMIT & OFFSETrequire unsigned argumentany integer argument
TRUNCATEN/Atruncate
WITHconnect with with statement using operator()connect with with statement using operator<<
custom queriessqlpp::custom_queryclauses can be concatenated using operator<<
Functions
COALESCEN/Acoalesce(<one or more arguments>)
COUNT(*)N/Acount(sqlpp::star)
SOMEsomedropped (use any)
Operators
CASEcase_when.then().else_() supports a single when/then pair. Data types of then and else_ must be comparable. then does not support sqlpp::nullSupport for multiple when/then pairs. Data types of thens and else must be same (plus/minus optional). then supports std::nullopt if at least one then argument or the else_ argument has a data type.
INin requires sqlpp::value_list to pass std::vectorsomething.in(my_vector)
NOT INnot_in requires sqlpp::value_list to pass std::vectorsomething.not_in(my_vector)
Unary operator+()presentdropped
comparison with value or NULLis_equal_to_or_null (does not work with parameters)is_distinct_from and is_not_distinct_from
Sub queries
select(...).as(...)Could be table or value (depending on the context)Always a table unless wrapped by value()
Logging
config.debugCould control logging to std::cerr via a bool value in the connection's configCan control which message categories are logged and control how hey are logged (you can provide a std::function). And you can turn off debug logging completely at compile time by defining SQLPP23_DISABLE_DEBUG.
Magic
INx.in(sqlpp::value_list(vector{})) interpreted as falseno magic: x IN ()
NOT INx.not_in(sqlpp::value_list(vector{})) interpreted as trueno magic: x NOT IN ()
operator+= etcx += y was translated into x = x + yno magic
aggregate functionsauto-named in select but not otherwiserequire explicit names, e.g. max(id).as(sqlpp::alias::max_)
Misc
prepared statement parameters.params.parameters
eval(db, expr)Convenience wrapper around db(select(expr.as(a))).front().adropped (could lead to dangling references, see TEXT and BLOB)
ppgenPre-processor code generation for tablesdropped
sqlite2cpp.pysqlpp23-ddl2cpp variant for sqlite3dropped
dynamic loadingAbility to load connector library dynamicallydropped (was unmaintained)
memory allocationMultiple cases of double pointer indirections (wrapping a smart pointer with yet another smart pointer)Removed all known double pointer indirections

< Index