40 #define NO_DISCARD SYS_NO_DISCARD_RESULT
68 template <>
struct is_error_code_enum<UT::
SqlError> : true_type
77 mySourceFile(source_file), mySourceLine(source_line)
82 if (mySourceLine !=
id.mySourceLine)
83 return mySourceLine <
id.mySourceLine;
84 return SYSstrcmp(mySourceFile,
id.mySourceFile) < 0;
87 const char* mySourceFile;
91 #define UT_SQL_ID UT_SqlStatementHandleId(__FILE__, __LINE__)
99 const void* myPtr =
nullptr;
100 std::size_t mySize = 0;
120 virtual void reset(
bool clear_bindings =
false) = 0;
125 NO_DISCARD virtual int columnAsInt(
int idx)
const = 0;
126 NO_DISCARD virtual bool columnAsBool(
int idx)
const = 0;
129 NO_DISCARD virtual double columnAsDouble(
int idx)
const = 0;
133 NO_DISCARD virtual const void *columnAsBlob(
int idx,
int &
size)
const = 0;
134 NO_DISCARD virtual Blob columnAsBlob(
int idx)
const = 0;
135 NO_DISCARD virtual null_tag_t columnAsNull(
int idx)
const = 0;
137 NO_DISCARD virtual int columnCount()
const = 0;
139 NO_DISCARD virtual int columnBytes(
int idx)
const = 0;
142 virtual const char* sql()
const = 0;
146 virtual bool bind(
int idx, null_tag_t) = 0;
148 virtual bool bind(
int idx,
const char *
value) = 0;
149 virtual bool bind(
int idx,
int value) = 0;
151 virtual bool bind(
int idx,
bool value) = 0;
152 virtual bool bind(
int idx,
double value) = 0;
159 virtual bool bind(
int idx,
const void *
value,
int size) = 0;
170 virtual bool step() = 0;
171 virtual bool run() = 0;
173 virtual int changes()
const = 0;
175 virtual bool hasRow() = 0;
201 void reset(
bool clear_bindings =
false)
override final;
220 const char*
sql()
const override final;
226 bool bind(
int idx,
const char *value)
override final;
227 bool bind(
int idx,
int value)
override final;
228 bool bind(
int idx,
int64 value)
override final;
229 bool bind(
int idx,
bool value)
override final;
230 bool bind(
int idx,
double value)
override final;
237 bool bind(
int idx,
const void *value,
int size)
override final;
242 bool step()
override final;
243 bool run()
override final;
268 bool verifyIndex_(
int idx)
const;
269 bool verifyColumn_(
int idx)
const;
270 bool verifyHasStepped_()
const;
273 sqlite3_stmt *myCtx =
nullptr;
276 unsigned myHasStepped : 1, myHasRow : 1;
301 if (myResult !=
nullptr && rhs.myResult !=
nullptr)
302 return myResult->myStmt == rhs.myResult->myStmt;
303 else if (myResult ==
nullptr && rhs.myResult ==
nullptr)
309 return !(*
this == rhs);
328 return myResult ==
nullptr || !myResult->hasResults();
370 template <
typename... Args>
372 template <
typename... Args>
374 template <
typename... Args>
401 void reset(
bool clear_bindings =
false)
403 myImpl->reset(clear_bindings);
408 return myImpl->columnAsInt(idx);
412 return myImpl->columnAsBool(idx);
416 return myImpl->columnAsInt64(idx);
420 return myImpl->columnAsStr(idx);
424 return myImpl->columnAsDouble(idx);
431 return myImpl->columnAsBlob(idx, size);
435 return myImpl->columnAsBlob(idx);
439 return myImpl->columnAsNull(idx);
443 return myImpl->columnName(idx);
447 return myImpl->columnCount();
451 return myImpl->columnType(idx);
455 return myImpl->columnBytes(idx);
461 return myImpl->sql();
472 return myImpl->bind(idx, value);
476 return myImpl->bind(idx, value);
480 return myImpl->bind(idx, value);
484 return myImpl->bind(idx, value);
488 return myImpl->bind(idx, value);
492 return myImpl->bind(idx, value);
497 return myImpl->bind(idx, value);
501 return myImpl->bind(idx, value);
505 return myImpl->bind(idx, value);
511 return myImpl->bind(idx, value, size);
515 return myImpl->bind(idx, blob);
518 template <
typename T>
522 !std::is_same_v<T, void> && std::is_same_v<T, void>,
523 "Type not handled.");
528 template <
typename... Args>
530 {
return bindHelper(1, std::forward<Args>(
args)...); }
537 return myImpl && myImpl->isValid();
542 return myImpl->hasRow();
548 return myImpl->run();
553 return myImpl->step();
559 {
return myImpl->getError(); }
568 template <
typename... Args>
572 if (!prepare(sql, ec))
577 bindAll(std::forward<Args>(
args)...);
584 template <
typename... Args>
591 if (!prepare(
id, sql, ec))
593 bindAll(std::forward<Args>(
args)...);
600 template <
typename... Args>
603 constexpr
int ColumnCount =
sizeof...(Args);
619 auto r = fetchRow_<Args...>(std::make_index_sequence<ColumnCount>{});
634 template <
typename... Args>
652 constexpr
int ColumnCount =
sizeof...(Args);
653 auto idx_sequence = std::make_index_sequence<ColumnCount>{};
656 rows.emplace_back(fetchRow_<Args...>(idx_sequence));
669 template <
typename... Args>
686 constexpr
int ColumnCount =
sizeof...(Args);
687 return fetchRow_<Args...>(std::make_index_sequence<ColumnCount>{});
693 return myImpl->tableExists(name, ec);
696 int changes()
const {
return myImpl->changes(); }
701 template <
typename T,
typename... Args>
704 if (!bind(idx, value))
706 return bindHelper(idx + 1, std::forward<Args>(
args)...);
709 template <
class... Args, std::size_t... Idxs>
713 return std::make_tuple(get<Args>(Idxs)...);
723 UT_SqlStatement::get<double>(
int idx)
const
725 return columnAsDouble(idx);
730 UT_SqlStatement::get<UT_SqlStatement::null_tag_t>(
int idx)
const
732 return columnAsNull(idx);
737 UT_SqlStatement::get<UT_StringHolder>(
int idx)
const
739 return columnAsStr(idx);
744 UT_SqlStatement::get<int>(
int idx)
const
746 return columnAsInt(idx);
751 UT_SqlStatement::get<int64>(
int idx)
const
753 return columnAsInt64(idx);
758 UT_SqlStatement::get<bool>(
int idx)
const
760 return columnAsBool(idx);
765 UT_SqlStatement::get<const void *>(
int idx)
const
768 return columnAsBlob(idx, size);
773 UT_SqlStatement::get<UT_SqlStatement::Blob>(
int idx)
const
775 return columnAsBlob(idx);
793 return myStmt && myStmt->
hasRow();
796 template <
typename... Args>
797 inline std::tuple<Args...>
800 return myStmt->
fetchOne<Args...>(ec);
803 template <
typename... Args>
804 inline UT_Array<std::tuple<Args...>>
807 return myStmt->
fetchAll<Args...>(ec);
810 template <
typename... Args>
811 inline std::tuple<Args...>
814 return myStmt->
as<Args...>(ec);
846 const char *db =
"main",
851 NO_DISCARD virtual void* nativeAPI()
const = 0;
878 NO_DISCARD virtual int extendedErrorCode()
const = 0;
884 virtual bool startTransaction(
UT_ErrorCode *ec =
nullptr) = 0;
909 template <
typename... Args>
913 if (
sizeof...(Args) > 0)
932 static constexpr
UT_StringLit theBusyTimeoutOpt =
"SQLITE_BUSY_TIMEOUT";
941 myFilename = db_name;
949 {
return myCtx !=
nullptr && myFilename.isstring(); }
992 myBusyTimeout = timeout_ms;
1029 bool schemaItemExists(
1041 sqlite3 *myCtx =
nullptr;
1043 bool myShouldCommitTransaction;
1046 int myBusyTimeout = -1;
1062 return myDriver.get();
1066 return myDriver.get();
1071 myDriver->setHostName(host);
1075 myDriver->setPort(port);
1079 myDriver->setUserName(user);
1083 myDriver->setPassword(password);
1087 myDriver->setDatabaseName(db_name);
1091 myDriver->setConnectOptions(options);
1099 return myDriver && myDriver->connect(ec);
1104 return myDriver && myDriver->isValid();
1107 const char *db =
"main",
1110 return myDriver->isReadOnly(db, ec);
1114 return myDriver->createStatementImpl();
1118 return myDriver->createStatementImpl();
1128 return myDriver->cachedStatement(
id, sql, ec);
1138 return myDriver->findCachedStatement(
id);
1141 template <
typename... Args>
1145 if (
sizeof...(Args) > 0)
1155 return myDriver->exec(sql, ec);
1162 return myDriver->tableExists(name, ec);
1167 return myDriver->indexExists(name, ec);
1172 return myDriver->viewExists(name, ec);
1179 return myDriver->columnExists(table_name, column_name, ec);
1183 return myDriver->errorMessage();
1187 return myDriver->errorCode();
1191 return myDriver->extendedErrorCode();
1200 return myDriver->startTransaction(ec);
1204 return myDriver->endTransaction(commit, ec);
1209 return myDriver->getSchema(ec);
1239 #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
UT_ErrorCode make_error_code(UT::SqlError e)
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)
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
virtual const char * sql() const =0
const UT_ErrorCode & getError() const
NO_DISCARD Blob columnAsBlob(int idx) 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
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.
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()
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)
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()
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
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)
void setConnectOptions(const UT_Options &options)
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
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)
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
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.
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.