41 #define NO_DISCARD SYS_NO_DISCARD_RESULT
69 template <>
struct is_error_code_enum<UT::
SqlError> : true_type
78 mySourceFile(source_file), mySourceLine(source_line)
83 if (mySourceLine !=
id.mySourceLine)
84 return mySourceLine <
id.mySourceLine;
85 return SYSstrcmp(mySourceFile,
id.mySourceFile) < 0;
88 const char* mySourceFile;
92 #define UT_SQL_ID UT_SqlStatementHandleId(__FILE__, __LINE__)
100 const void* myPtr =
nullptr;
101 std::size_t mySize = 0;
121 virtual void reset(
bool clear_bindings =
false) = 0;
126 NO_DISCARD virtual int columnAsInt(
int idx)
const = 0;
127 NO_DISCARD virtual bool columnAsBool(
int idx)
const = 0;
130 NO_DISCARD virtual double columnAsDouble(
int idx)
const = 0;
135 NO_DISCARD virtual const void *columnAsBlob(
int idx,
int &
size)
const = 0;
136 NO_DISCARD virtual Blob columnAsBlob(
int idx)
const = 0;
137 NO_DISCARD virtual null_tag_t columnAsNull(
int idx)
const = 0;
139 NO_DISCARD virtual int columnCount()
const = 0;
141 NO_DISCARD virtual int columnBytes(
int idx)
const = 0;
152 virtual const char* sql()
const = 0;
156 virtual bool bind(
int idx, null_tag_t) = 0;
158 virtual bool bind(
int idx,
const char *
value) = 0;
159 virtual bool bind(
int idx,
int value) = 0;
161 virtual bool bind(
int idx,
bool value) = 0;
162 virtual bool bind(
int idx,
double value) = 0;
170 virtual bool bind(
int idx,
const void *
value,
int size) = 0;
181 virtual bool step() = 0;
182 virtual bool run() = 0;
184 virtual int changes()
const = 0;
186 virtual bool hasRow() = 0;
212 void reset(
bool clear_bindings =
false)
override final;
232 const char*
sql()
const override final;
238 bool bind(
int idx,
const char *value)
override final;
239 bool bind(
int idx,
int value)
override final;
240 bool bind(
int idx,
int64 value)
override final;
241 bool bind(
int idx,
bool value)
override final;
242 bool bind(
int idx,
double value)
override final;
249 bool bind(
int idx,
const void *value,
int size)
override final;
263 bool step()
override final;
264 bool run()
override final;
288 bool verifyIndex_(
int idx)
const;
289 bool verifyColumn_(
int idx)
const;
290 bool verifyHasStepped_()
const;
293 sqlite3_stmt *myCtx =
nullptr;
296 unsigned myHasStepped : 1, myHasRow : 1;
321 if (myResult !=
nullptr && rhs.myResult !=
nullptr)
322 return myResult->myStmt == rhs.myResult->myStmt;
323 else if (myResult ==
nullptr && rhs.myResult ==
nullptr)
329 return !(*
this == rhs);
348 return myResult ==
nullptr || !myResult->hasResults();
390 template <
typename... Args>
392 template <
typename... Args>
394 template <
typename... Args>
421 void reset(
bool clear_bindings =
false)
423 myImpl->reset(clear_bindings);
428 return myImpl->columnAsInt(idx);
432 return myImpl->columnAsBool(idx);
436 return myImpl->columnAsInt64(idx);
440 return myImpl->columnAsStr(idx);
444 return myImpl->columnAsDouble(idx);
450 return myImpl->columnAsDate(idx);
455 return myImpl->columnAsBlob(idx, size);
459 return myImpl->columnAsBlob(idx);
463 return myImpl->columnAsNull(idx);
467 return myImpl->columnName(idx);
471 return myImpl->columnCount();
475 return myImpl->columnType(idx);
479 return myImpl->columnBytes(idx);
485 return myImpl->sql();
496 return myImpl->bind(idx, value);
500 return myImpl->bind(idx, value);
504 return myImpl->bind(idx, value);
508 return myImpl->bind(idx, value);
512 return myImpl->bind(idx, value);
516 return myImpl->bind(idx, value);
521 return myImpl->bind(idx, value);
525 return myImpl->bind(idx, value);
529 return myImpl->bind(idx, value);
535 return myImpl->bind(idx, value, size);
539 return myImpl->bind(idx, blob);
543 return myImpl->bind(idx, dt);
548 return myImpl->intTypeString();
552 return myImpl->stringTypeString();
556 return myImpl->nullTypeString();
560 return myImpl->realTypeString();
564 return myImpl->blobTypeString();
568 return myImpl->dateTimeTypeString();
572 return myImpl->boolTypeString();
575 template <
typename T>
579 !std::is_same_v<T, void> && std::is_same_v<T, void>,
580 "Type not handled.");
585 template <
typename... Args>
587 {
return bindHelper(1, std::forward<Args>(
args)...); }
594 return myImpl && myImpl->isValid();
599 return myImpl->hasRow();
605 return myImpl->run();
610 return myImpl->step();
616 {
return myImpl->getError(); }
625 template <
typename... Args>
629 if (!prepare(sql, ec))
634 bindAll(std::forward<Args>(
args)...);
641 template <
typename... Args>
648 if (!prepare(
id, sql, ec))
652 bindAll(std::forward<Args>(
args)...);
659 template <
typename... Args>
662 constexpr
int ColumnCount =
sizeof...(Args);
678 auto r = fetchRow_<Args...>(std::make_index_sequence<ColumnCount>{});
693 template <
typename... Args>
711 constexpr
int ColumnCount =
sizeof...(Args);
712 auto idx_sequence = std::make_index_sequence<ColumnCount>{};
715 rows.emplace_back(fetchRow_<Args...>(idx_sequence));
728 template <
typename... Args>
745 constexpr
int ColumnCount =
sizeof...(Args);
746 return fetchRow_<Args...>(std::make_index_sequence<ColumnCount>{});
752 return myImpl->tableExists(name, ec);
755 int changes()
const {
return myImpl->changes(); }
760 template <
typename T,
typename... Args>
763 if (!bind(idx, value))
765 return bindHelper(idx + 1, std::forward<Args>(
args)...);
768 template <
class... Args, std::size_t... Idxs>
772 return std::make_tuple(get<Args>(Idxs)...);
782 UT_SqlStatement::get<double>(
int idx)
const
784 return columnAsDouble(idx);
789 UT_SqlStatement::get<UT_SqlStatement::null_tag_t>(
int idx)
const
791 return columnAsNull(idx);
796 UT_SqlStatement::get<UT_StringHolder>(
int idx)
const
798 return columnAsStr(idx);
803 UT_SqlStatement::get<int>(
int idx)
const
805 return columnAsInt(idx);
810 UT_SqlStatement::get<int64>(
int idx)
const
812 return columnAsInt64(idx);
817 UT_SqlStatement::get<bool>(
int idx)
const
819 return columnAsBool(idx);
824 UT_SqlStatement::get<UT_DateTimeField>(
int idx)
const
826 return columnAsDate(idx);
831 UT_SqlStatement::get<const void *>(
int idx)
const
834 return columnAsBlob(idx, size);
839 UT_SqlStatement::get<UT_SqlStatement::Blob>(
int idx)
const
841 return columnAsBlob(idx);
859 return myStmt && myStmt->
hasRow();
862 template <
typename... Args>
863 inline std::tuple<Args...>
866 return myStmt->
fetchOne<Args...>(ec);
869 template <
typename... Args>
870 inline UT_Array<std::tuple<Args...>>
873 return myStmt->
fetchAll<Args...>(ec);
876 template <
typename... Args>
877 inline std::tuple<Args...>
880 return myStmt->
as<Args...>(ec);
912 const char *db =
"main",
917 NO_DISCARD virtual void* nativeAPI()
const = 0;
944 NO_DISCARD virtual int extendedErrorCode()
const = 0;
950 virtual bool startTransaction(
UT_ErrorCode *ec =
nullptr) = 0;
975 template <
typename... Args>
979 if (
sizeof...(Args) > 0)
998 static constexpr
UT_StringLit theBusyTimeoutOpt =
"SQLITE_BUSY_TIMEOUT";
1007 myFilename = db_name;
1015 {
return myCtx !=
nullptr && myFilename.isstring(); }
1058 myBusyTimeout = timeout_ms;
1095 bool schemaItemExists(
1107 sqlite3 *myCtx =
nullptr;
1109 bool myShouldCommitTransaction;
1112 int myBusyTimeout = -1;
1128 return myDriver.get();
1132 return myDriver.get();
1137 myDriver->setHostName(host);
1141 myDriver->setPort(port);
1145 myDriver->setUserName(user);
1149 myDriver->setPassword(password);
1153 myDriver->setDatabaseName(db_name);
1157 myDriver->setConnectOptions(options);
1165 return myDriver && myDriver->connect(ec);
1170 return myDriver && myDriver->isValid();
1173 const char *db =
"main",
1176 return myDriver->isReadOnly(db, ec);
1180 return myDriver->createStatementImpl();
1184 return myDriver->createStatementImpl();
1194 return myDriver->cachedStatement(
id, sql, ec);
1204 return myDriver->findCachedStatement(
id);
1207 template <
typename... Args>
1211 if (
sizeof...(Args) > 0)
1221 return myDriver->exec(sql, ec);
1228 return myDriver->tableExists(name, ec);
1233 return myDriver->indexExists(name, ec);
1238 return myDriver->viewExists(name, ec);
1245 return myDriver->columnExists(table_name, column_name, ec);
1249 return myDriver->errorMessage();
1253 return myDriver->errorCode();
1257 return myDriver->extendedErrorCode();
1266 return myDriver->startTransaction(ec);
1270 return myDriver->endTransaction(commit, ec);
1275 return myDriver->getSchema(ec);
1305 #endif // __UT_SQL_H__
NO_DISCARD null_tag_t columnAsNull(int idx) const
virtual void setPassword(const UT_StringHolder &password)
UT_SqlResult & operator*()
GT_API const UT_StringHolder filename
virtual NO_DISCARD int extendedErrorCode() const =0
UT_SqlStatementHandleId(const char *source_file, exint source_line)
const UT_ErrorCode & getError() const
UT_SharedPtr< UT_SqlStatementImpl > findCachedStatement(const UT_SqlStatementHandleId &id) const
virtual NO_DISCARD int columnCount() const =0
const UT_SqlResult & operator*() const
virtual NO_DISCARD int64 columnAsInt64(int idx) const =0
virtual NO_DISCARD UT_IntArray columnAsIntArray(int idx) const =0
UT_SqlDatabase(driver_factory_t factory=UTsqliteFactory)
bool bind(int idx, const UT_StringArray &value)
virtual bool connect(UT_ErrorCode *ec=nullptr)=0
void setDatabaseName(const UT_StringHolder &db_name) override
virtual NO_DISCARD bool isReadOnly(const char *db="main", UT_ErrorCode *ec=nullptr) const =0
bool bind(int idx, const char *value)
std::forward_iterator_tag iterator_category
NO_DISCARD bool tableExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const
virtual NO_DISCARD UT_StringHolder columnName(int idx) const =0
NO_DISCARD int columnCount() const
std::optional< std::tuple< std::tuple< Args...> > > as(UT_ErrorCode *ec=nullptr)
virtual NO_DISCARD bool indexExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const =0
bool bind(int idx, const UT_Int64Array &value)
bool bind(int idx, null_tag_t)
NO_DISCARD int extendedErrorCode() const
void setBusyTimeout(int timeout_ms)
const UT_StringHolder & blobTypeString() const
NO_DISCARD bool tableExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const
Check if the specified table exists.
const UT_SqlBaseDriver * driver() const
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
NO_DISCARD bool columnAsBool(int idx) const
const UT_StringHolder & boolTypeString() const
virtual const char * sql() const =0
const UT_ErrorCode & getError() const
NO_DISCARD Blob columnAsBlob(int idx) const
const UT_StringHolder & nullTypeString() const
bool bind(int idx, Blob blob)
virtual void prepare(const UT_StringRef &sql, UT_ErrorCode *ec=nullptr)=0
virtual void setPort(int port)
UT_SqlResult execute(const UT_StringRef &sql, Args &&...args)
Helper function to create a new statement to run a new sql statement.
virtual NO_DISCARD bool columnExists(const UT_StringRef &table_name, const UT_StringRef &column_name, UT_ErrorCode *ec=nullptr) const =0
**But if you need a result
std::error_category UT_ErrorCategory
const iterator begin() const
void setHostName(const UT_StringRef &host)
int changes() const overridefinal
virtual bool close(UT_ErrorCode *ec=nullptr)=0
NO_DISCARD UT_StringHolder columnAsStr(int idx) const
GLintptr GLsizeiptr GLboolean commit
virtual NO_DISCARD UT_DateTimeField columnAsDate(int idx) const =0
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
const iterator cend() const
NO_DISCARD bool isReadOnly(const char *db="main", UT_ErrorCode *ec=nullptr) const
bool run(UT_ErrorCode *ec, const UT_StringRef &sql, Args &&...args)
Helper function to run an sql statement with provided typed args.
const UT_StringHolder & stringTypeString() const
virtual NO_DISCARD bool viewExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const =0
NO_DISCARD UT_SharedPtr< UT_SqlStatementImpl > createStatementImpl()
std::tuple< Args...> as(UT_ErrorCode *ec=nullptr)
bool operator!=(const iterator &rhs) const
virtual UT_SharedPtr< UT_SqlStatementImpl > findCachedStatement(const UT_SqlStatementHandleId &id) const =0
UT_SqlStatementImpl(const UT_SqlBaseDriver &driver)
UT_API const UT_ErrorCategory & GetSqlErrorCategory()
virtual const UT_StringHolder & blobTypeString() const =0
std::tuple< Args...> fetchOne(UT_ErrorCode *ec=nullptr)
virtual void reset(bool clear_bindings=false)=0
bool bind(int idx, bool value)
virtual void setDatabaseName(const UT_StringHolder &db_name)
virtual const UT_StringHolder & boolTypeString() const =0
bool operator<(const UT_SqlStatementHandleId &id) const
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
bool startTransaction(UT_ErrorCode *ec=nullptr)
NO_DISCARD bool indexExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const
NO_DISCARD void * nativeAPI() const
virtual NO_DISCARD bool tableExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const =0
Check if the specified table exists.
bool bind(int idx, double value)
virtual NO_DISCARD UT_StringHolder errorMessage() const =0
NO_DISCARD void * nativeAPI()
virtual const UT_StringHolder & nullTypeString() const =0
NO_DISCARD UT_StringHolder errorMessage() const
const UT_SqlBaseDriver & driver() const
NO_DISCARD double columnAsDouble(int idx) const
virtual NO_DISCARD double columnAsDouble(int idx) const =0
virtual NO_DISCARD UT_StringHolder getSchema(UT_ErrorCode *ec=nullptr) const =0
bool run(UT_ErrorCode *ec, const UT_StringRef &sql, Args &&...args)
Helper function to run an sql statement with provided typed args.
bool bindAll(Args &&...args)
const UT_ErrorCode & getError() const
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
NO_DISCARD UT_SharedPtr< UT_SqlStatementImpl > createStatementImpl() const
UT_API const UT_ErrorCategory & GetSqliteErrorCategory()
virtual NO_DISCARD int columnAsInt(int idx) const =0
const iterator cbegin() const
UT_Array< std::tuple< Args...> > fetchAll(UT_ErrorCode *ec=nullptr)
virtual bool endTransaction(bool commit, UT_ErrorCode *ec=nullptr)=0
NO_DISCARD int columnBytes(int idx) const
const UT_SqlResult * operator->() const
NO_DISCARD bool isValid() const
virtual NO_DISCARD bool tableExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const =0
int SYSstrcmp(const char *a, const char *b)
NO_DISCARD int columnAsInt(int idx) const
virtual NO_DISCARD UT_SharedPtr< UT_SqlStatementImpl > createStatementImpl()=0
bool bind(int idx, const UT_IntArray &value)
GLuint const GLchar * name
NO_DISCARD UT_DateTimeField columnAsDate(int idx) const
UT_SqlResult execute(const UT_SqlStatementHandleId &id, const UT_StringRef &sql, Args &&...args)
Helper function to create a new statement to run a new sql statement.
bool bind(int idx, const void *value, int size)
const UT_StringHolder & intTypeString() const
void setConnectOptions(const UT_Options &options)
UT_ErrorCode make_error_code(UT::OrmMigError e)
virtual const UT_StringHolder & intTypeString() const =0
virtual const UT_StringHolder & realTypeString() const =0
NO_DISCARD SYS_FORCE_INLINE bool isValid() const override
NO_DISCARD bool viewExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const
virtual NO_DISCARD bool isValid() const =0
virtual const UT_StringHolder & dateTimeTypeString() const =0
NO_DISCARD UT_StringHolder columnName(int idx) const
UT_API UT_UniquePtr< UT_SqlBaseDriver > UTsqliteFactory()
virtual NO_DISCARD int errorCode() const =0
bool bind(int idx, int64 value)
const iterator end() const
virtual NO_DISCARD DataType columnType(int idx) const =0
UT_SqlResult * operator->()
GT_API const UT_StringHolder version
std::error_code UT_ErrorCode
NO_DISCARD bool isValid() const
Check the underlying connection is valid and usable.
bool close(UT_ErrorCode *ec=nullptr)
Close the sql connection to the db backend.
void reset(bool clear_bindings=false)
bool hasRow() overridefinal
virtual void setHostName(const UT_StringHolder &host)
A map of string to various well defined value types.
bool endTransaction(bool commit, UT_ErrorCode *ec=nullptr)
const UT_StringHolder & realTypeString() const
void setPassword(const UT_StringRef &password)
bool bind(int idx, int value)
virtual NO_DISCARD UT_Int64Array columnAsInt64Array(int idx) const =0
bool connect(UT_ErrorCode *ec=nullptr)
Create a db connection with a custom db backend.
virtual NO_DISCARD const void * columnAsBlob(int idx, int &size) const =0
const UT_SqlBaseDriver & myDriver
virtual void setUserName(const UT_StringHolder &user)
NO_DISCARD void * nativeAPI() const override
NO_DISCARD int errorCode() const
virtual NO_DISCARD int columnBytes(int idx) const =0
bool bind(int idx, Blob blob)
NO_DISCARD void * nativeAPI() override
virtual UT_SharedPtr< UT_SqlStatementImpl > cachedStatement(const UT_SqlStatementHandleId &id, const UT_StringRef &sql, UT_ErrorCode *ec=nullptr) const =0
UT_SharedPtr< UT_SqlStatementImpl > cachedStatement(const UT_SqlStatementHandleId &id, const UT_StringRef &sql, UT_ErrorCode *ec=nullptr) const
UT_NON_COPYABLE(UT_SqlBaseDriver)
bool bind(int idx, const UT_StringRef &value)
SqlError
Error codes to describe errors as a result of UT_SQL.
NO_DISCARD UT_StringHolder getSchema(UT_ErrorCode *ec=nullptr) const
**If you just want to fire and args
virtual NO_DISCARD UT_StringHolder columnAsStr(int idx) const =0
std::tuple< Args...> fetchRow_(std::index_sequence< Idxs...>)
virtual void setConnectOptions(const UT_Options &options)
virtual bool bind(int idx, null_tag_t)=0
NO_DISCARD const void * columnAsBlob(int idx, int &size) const
UT_NON_COPYABLE(UT_SqlStatementImpl)
bool operator==(const iterator &rhs) const
virtual NO_DISCARD null_tag_t columnAsNull(int idx) const =0
NO_DISCARD bool columnExists(const UT_StringRef &table_name, const UT_StringRef &column_name, UT_ErrorCode *ec=nullptr) const
UT_Array< std::tuple< Args...> > fetchAll(UT_ErrorCode *ec=nullptr)
UT_SqlBaseDriver * driver()
NO_DISCARD int64 columnAsInt64(int idx) const
bool bindHelper(int idx, T value, Args &&...args)
NO_DISCARD DataType columnType(int idx) const
virtual bool startTransaction(UT_ErrorCode *ec=nullptr)=0
virtual const UT_StringHolder & stringTypeString() const =0
const UT_StringHolder & dateTimeTypeString() const
UT_UniquePtr< UT_SqlBaseDriver > myDriver
void setUserName(const UT_StringRef &user)
void setDatabaseName(const UT_StringRef &db_name)
std::optional< std::tuple< Args...> > fetchOne(UT_ErrorCode *ec=nullptr)
int exec(const UT_StringRef &sql, UT_ErrorCode *ec=nullptr) const
Returns the number of rows modified, inserted or deleted.
virtual NO_DISCARD bool columnAsBool(int idx) const =0
virtual int exec(const UT_StringRef &sql, UT_ErrorCode *ec=nullptr) const =0
Returns the number of rows modified, inserted or deleted.
bool bind(int idx, const UT_DateTimeField &dt)
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.