HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_SQL.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_SQL.h
7  *
8  * COMMENTS:
9  * C++ Wrapper around sqlite
10  */
11 
12 #ifndef __UT_SQL_H__
13 #define __UT_SQL_H__
14 
15 #include "UT_API.h"
16 
17 #include "UT_Debug.h"
18 #include "UT_Error.h"
19 #include "UT_ErrorCode.h"
20 #include "UT_StringHolder.h"
21 #include "UT_IntrusivePtr.h"
22 #include "UT_UniquePtr.h"
23 #include "UT_SharedPtr.h"
24 
25 #include <SYS/SYS_Compiler.h>
26 #include <SYS/SYS_Inline.h>
27 
28 #include <map>
29 #include <tuple>
30 #include <optional>
31 
32 class UT_SqlDatabase;
33 class UT_SqlBaseDriver;
34 class UT_Options;
35 class UT_SqlStatement;
36 
37 class sqlite3;
38 class sqlite3_stmt;
39 
40 #define NO_DISCARD SYS_NO_DISCARD_RESULT
41 
42 // NB: An actual namespace is used here because std::error_code does an ADL
43 // lookup when creating std::error_code with just the enum class. This allows us
44 // to do `if (ec == UT::SqlError::UT_SQL_HAS_STEPPED)` instead of
45 // `if (ec == UTmakeErrorCode(UT_SqlError::UT_SQL_HAS_STEPPED))`
46 namespace UT
47 {
48 /// Error codes to describe errors as a result of UT_SQL
49 enum class SqlError
50 {
51  UT_SQL_OK = 0,
54 };
55 
58 
59 inline UT_ErrorCode
61 {
62  return UT_ErrorCode{static_cast<int>(e), GetSqlErrorCategory()};
63 }
64 } // namespace UT
65 
66 namespace std
67 {
68  template <> struct is_error_code_enum<UT::SqlError> : true_type
69  {
70  };
71 }
72 
74 {
75 public:
76  UT_SqlStatementHandleId(const char* source_file, exint source_line) :
77  mySourceFile(source_file), mySourceLine(source_line)
78  {}
79 
80  bool operator<(const UT_SqlStatementHandleId& id) const
81  {
82  if (mySourceLine != id.mySourceLine)
83  return mySourceLine < id.mySourceLine;
84  return SYSstrcmp(mySourceFile, id.mySourceFile) < 0;
85  }
86 private:
87  const char* mySourceFile;
88  exint mySourceLine;
89 };
90 
91 #define UT_SQL_ID UT_SqlStatementHandleId(__FILE__, __LINE__)
92 
94 {
95 public:
96  struct null_tag_t {};
97  struct Blob
98  {
99  const void* myPtr = nullptr;
100  std::size_t mySize = 0;
101  };
102  enum DataType
103  {
104  kUnknown = -1,
109  kNull
110  };
111 
112  virtual ~UT_SqlStatementImpl() = default;
114 
115  const UT_SqlBaseDriver& driver() const
116  {
117  return myDriver;
118  }
119 
120  virtual void reset(bool clear_bindings = false) = 0;
121 
122  virtual void prepare(const UT_StringRef &sql, UT_ErrorCode *ec = nullptr)
123  = 0;
124 
125  NO_DISCARD virtual int columnAsInt(int idx) const = 0;
126  NO_DISCARD virtual bool columnAsBool(int idx) const = 0;
127  NO_DISCARD virtual int64 columnAsInt64(int idx) const = 0;
128  NO_DISCARD virtual UT_StringHolder columnAsStr(int idx) const = 0;
129  NO_DISCARD virtual double columnAsDouble(int idx) const = 0;
130  NO_DISCARD virtual UT_IntArray columnAsIntArray(int idx) const = 0;
131  NO_DISCARD virtual UT_Int64Array columnAsInt64Array(int idx) const = 0;
132  // Stores size of blob in bytes in 'size'.
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;
136  NO_DISCARD virtual UT_StringHolder columnName(int idx) const = 0;
137  NO_DISCARD virtual int columnCount() const = 0;
138  NO_DISCARD virtual DataType columnType(int idx) const = 0;
139  NO_DISCARD virtual int columnBytes(int idx) const = 0;
140 
141  // The original text of the sql statement. Do not keep a pointer to it.
142  virtual const char* sql() const = 0;
143 
144  // Add more binds as needed
145  // This binds a NULL
146  virtual bool bind(int idx, null_tag_t) = 0;
147  virtual bool bind(int idx, const UT_StringRef &value) = 0;
148  virtual bool bind(int idx, const char *value) = 0;
149  virtual bool bind(int idx, int value) = 0;
150  virtual bool bind(int idx, int64 value) = 0;
151  virtual bool bind(int idx, bool value) = 0;
152  virtual bool bind(int idx, double value) = 0;
153  // The following methods bind arrays as strings of the form [#, #, ..., #]
154  virtual bool bind(int idx, const UT_IntArray &value) = 0;
155  virtual bool bind(int idx, const UT_Int64Array &value) = 0;
156  virtual bool bind(int idx, const UT_StringArray &value) = 0;
157  // For binding blobs. `size` is required in bytes. Note that this
158  // function does not destroy `value`.
159  virtual bool bind(int idx, const void *value, int size) = 0;
160  bool bind(int idx, Blob blob)
161  {
162  return this->bind(idx, blob.myPtr, blob.mySize);
163  }
164 
165  NO_DISCARD virtual bool isValid() const = 0;
166 
167  const UT_ErrorCode &getError() const { return myError; }
168 
169  // Called when there are rows to iterate over (i.e. SELECT).
170  virtual bool step() = 0;
171  virtual bool run() = 0;
172 
173  virtual int changes() const = 0;
174 
175  virtual bool hasRow() = 0;
176 
177  NO_DISCARD virtual bool tableExists(
178  const UT_StringRef &name,
179  UT_ErrorCode *ec = nullptr) const
180  = 0;
181 
182 protected:
184  myDriver(driver)
185  {}
186 
189 };
190 
192 {
193 public:
195  const UT_SqlBaseDriver &driver,
196  const UT_StringRef &sql);
198  ~UT_SqliteStatementImpl() override;
200 
201  void reset(bool clear_bindings = false) override final;
202 
203  NO_DISCARD int columnAsInt(int idx) const override final;
204  NO_DISCARD bool columnAsBool(int idx) const override final;
205  NO_DISCARD int64 columnAsInt64(int idx) const override final;
206  NO_DISCARD UT_StringHolder columnAsStr(int idx) const override final;
207  NO_DISCARD double columnAsDouble(int idx) const override final;
208  NO_DISCARD UT_IntArray columnAsIntArray(int idx) const override final;
209  NO_DISCARD UT_Int64Array columnAsInt64Array(int idx) const override final;
210  // Stores size of blob in bytes in 'size'.
211  NO_DISCARD const void *columnAsBlob(int idx, int &size) const override final;
212  NO_DISCARD Blob columnAsBlob(int idx) const override final;
213  NO_DISCARD null_tag_t columnAsNull(int idx) const override final;
214  NO_DISCARD UT_StringHolder columnName(int idx) const override final;
215  NO_DISCARD int columnCount() const override final;
216  NO_DISCARD DataType columnType(int idx) const override final;
217  NO_DISCARD int columnBytes(int idx) const override final;
218 
219  // The original text of the sql statement. Do not keep a pointer to it.
220  const char* sql() const override final;
221 
222  // Add more binds as needed
223  // This binds a NULL
224  bool bind(int idx, null_tag_t) override final;
225  bool bind(int idx, const UT_StringRef &value) 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;
231  // The following methods bind arrays as strings of the form [#, #, ..., #]
232  bool bind(int idx, const UT_IntArray &value) override final;
233  bool bind(int idx, const UT_Int64Array &value) override final;
234  bool bind(int idx, const UT_StringArray &value) override final;
235  // For binding blobs. `size` is required in bytes. Note that this
236  // function does not destroy `value`.
237  bool bind(int idx, const void *value, int size) override final;
238 
239  NO_DISCARD bool isValid() const override final;
240 
241  // Called when there are rows to iterate over (i.e. SELECT).
242  bool step() override final;
243  bool run() override final;
244 
245  int changes() const override final
246  {
247  return myChanges;
248  }
249  bool hasRow() override final
250  {
251  if (!myHasStepped)
252  {
253  if (!step())
254  {
255  return false;
256  }
257  }
258  return myHasRow;
259  }
260 
262  UT_ErrorCode *ec = nullptr) const override;
263 
264  void prepare(const UT_StringRef& sql, UT_ErrorCode* ec = nullptr) override;
265 
266 private:
267  void finalize_();
268  bool verifyIndex_(int idx) const;
269  bool verifyColumn_(int idx) const;
270  bool verifyHasStepped_() const;
271  int step_();
272 
273  sqlite3_stmt *myCtx = nullptr;
274  int myColumnCount;
275 
276  unsigned myHasStepped : 1, myHasRow : 1;
277  int myChanges = 0;
278 };
279 
281 {
282 public:
284  {
285  public:
287  using iterator_category = std::forward_iterator_tag;
289  using pointer = value_type*;
291 
293  {
294  if (myResult)
295  myResult->next();
296  return *this;
297  }
298 
299  bool operator==(const iterator& rhs) const
300  {
301  if (myResult != nullptr && rhs.myResult != nullptr)
302  return myResult->myStmt == rhs.myResult->myStmt;
303  else if (myResult == nullptr && rhs.myResult == nullptr)
304  return true;
305  return false;
306  }
307  bool operator!=(const iterator& rhs) const
308  {
309  return !(*this == rhs);
310  }
311  const UT_SqlResult& operator*() const{
312  return *myResult;
313  }
315  {
316  return *myResult;
317  }
318  const UT_SqlResult* operator->() const
319  {
320  return myResult;
321  }
323  {
324  return myResult;
325  }
326  bool isDone() const
327  {
328  return myResult == nullptr || !myResult->hasResults();
329  }
330 
331  private:
332  friend class UT_SqlResult;
333 
334  iterator(UT_SqlResult* result = nullptr) :
335  myResult(result)
336  {}
337 
338  UT_SqlResult* myResult = nullptr;
339  };
340 
342  {
343  return iterator(this);
344  }
346  {
347  return iterator();
348  }
349  const iterator begin() const
350  {
351  return iterator(SYSconst_cast(this));
352  }
353  const iterator end() const
354  {
355  return iterator();
356  }
357  const iterator cbegin() const
358  {
359  return begin();
360  }
361  const iterator cend() const
362  {
363  return end();
364  }
365 
366  const UT_ErrorCode& getError() const;
367  void next();
368  bool hasResults() const;
369 
370  template <typename... Args>
371  std::tuple<Args...> fetchOne(UT_ErrorCode* ec = nullptr);
372  template <typename... Args>
373  UT_Array<std::tuple<Args...>> fetchAll(UT_ErrorCode* ec = nullptr);
374  template <typename... Args>
375  std::tuple<Args...> as(UT_ErrorCode* ec = nullptr);
376 
377 private:
378  friend class UT_SqlStatement;
380  : myStmt(stmt)
381  {}
382 
383  UT_SqlStatement* myStmt;
384 };
385 
387 {
388 public:
392 
393  UT_SqlStatement(const UT_SqlDatabase& con, const UT_StringRef& sql);
394  UT_SqlStatement(const UT_SqlDatabase& con);
395  UT_SqlStatement(const UT_SqlBaseDriver &driver, const UT_StringRef &sql);
396  UT_SqlStatement(const UT_SqlBaseDriver &driver);
398  ~UT_SqlStatement();
400 
401  void reset(bool clear_bindings = false)
402  {
403  myImpl->reset(clear_bindings);
404  }
405 
406  NO_DISCARD int columnAsInt(int idx) const
407  {
408  return myImpl->columnAsInt(idx);
409  }
410  NO_DISCARD bool columnAsBool(int idx) const
411  {
412  return myImpl->columnAsBool(idx);
413  }
415  {
416  return myImpl->columnAsInt64(idx);
417  }
419  {
420  return myImpl->columnAsStr(idx);
421  }
422  NO_DISCARD double columnAsDouble(int idx) const
423  {
424  return myImpl->columnAsDouble(idx);
425  }
426  NO_DISCARD UT_IntArray columnAsIntArray(int idx) const;
427  NO_DISCARD UT_Int64Array columnAsInt64Array(int idx) const;
428  // Stores size of blob in bytes in 'size'.
429  NO_DISCARD const void *columnAsBlob(int idx, int &size) const
430  {
431  return myImpl->columnAsBlob(idx, size);
432  }
433  NO_DISCARD Blob columnAsBlob(int idx) const
434  {
435  return myImpl->columnAsBlob(idx);
436  }
438  {
439  return myImpl->columnAsNull(idx);
440  }
442  {
443  return myImpl->columnName(idx);
444  }
446  {
447  return myImpl->columnCount();
448  }
450  {
451  return myImpl->columnType(idx);
452  }
453  NO_DISCARD int columnBytes(int idx) const
454  {
455  return myImpl->columnBytes(idx);
456  }
457 
458  // The original text of the sql statement. Do not keep a pointer to it.
459  const char* sql() const
460  {
461  return myImpl->sql();
462  }
463 
464  // Add more binds as needed
465  // This binds a NULL
466  bool bind(int idx, null_tag_t)
467  {
468  return myImpl->bind(idx, null_tag_t{});
469  }
470  bool bind(int idx, const UT_StringRef &value)
471  {
472  return myImpl->bind(idx, value);
473  }
474  bool bind(int idx, const char *value)
475  {
476  return myImpl->bind(idx, value);
477  }
478  bool bind(int idx, int value)
479  {
480  return myImpl->bind(idx, value);
481  }
482  bool bind(int idx, int64 value)
483  {
484  return myImpl->bind(idx, value);
485  }
486  bool bind(int idx, bool value)
487  {
488  return myImpl->bind(idx, value);
489  }
490  bool bind(int idx, double value)
491  {
492  return myImpl->bind(idx, value);
493  }
494  // The following methods bind arrays as strings of the form [#, #, ..., #]
495  bool bind(int idx, const UT_IntArray &value)
496  {
497  return myImpl->bind(idx, value);
498  }
499  bool bind(int idx, const UT_Int64Array &value)
500  {
501  return myImpl->bind(idx, value);
502  }
503  bool bind(int idx, const UT_StringArray &value)
504  {
505  return myImpl->bind(idx, value);
506  }
507  // For binding blobs. `size` is required in bytes. Note that this
508  // function does not destroy `value`.
509  bool bind(int idx, const void *value, int size)
510  {
511  return myImpl->bind(idx, value, size);
512  }
513  bool bind(int idx, Blob blob)
514  {
515  return myImpl->bind(idx, blob);
516  }
517 
518  template <typename T>
519  T get(int idx) const
520  {
521  static_assert(
522  !std::is_same_v<T, void> && std::is_same_v<T, void>,
523  "Type not handled.");
524  return T();
525  }
526 
527  // TODO: Try redesigning this to work with the bind that accepts a blob.
528  template <typename... Args>
529  bool bindAll(Args &&... args)
530  { return bindHelper(1, std::forward<Args>(args)...); }
531 
532  bool bindNull(int idx)
533  { return bind(idx, null_tag_t()); }
534 
535  NO_DISCARD bool isValid() const
536  {
537  return myImpl && myImpl->isValid();
538  }
539 
540  bool hasRow()
541  {
542  return myImpl->hasRow();
543  }
544 
545  // Called when there is nothing to grab after (i.e. INSERT).
546  bool run()
547  {
548  return myImpl->run();
549  }
550  // Called when there are rows to iterate over (i.e. SELECT).
551  bool step()
552  {
553  return myImpl->step();
554  }
555 
556  // Methods on this class will always test myError before doing their
557  // work. If there is already an error, they will do nothing.
558  const UT_ErrorCode &getError() const
559  { return myImpl->getError(); }
560 
561  bool prepare(const UT_StringRef &sql, UT_ErrorCode &ec);
562  bool prepare(
563  const UT_SqlStatementHandleId &id,
564  const UT_StringRef &sql,
565  UT_ErrorCode &ec);
566 
567  /// Helper function to create a new statement to run a new sql statement
568  template <typename... Args>
569  UT_SqlResult execute(const UT_StringRef& sql, Args&&... args)
570  {
571  UT_ErrorCode ec;
572  if (!prepare(sql, ec))
573  {
574  return UT_SqlResult(this);
575  }
576 
577  bindAll(std::forward<Args>(args)...);
578 
579  step();
580 
581  return UT_SqlResult(this);
582  }
583  /// Helper function to create a new statement to run a new sql statement
584  template <typename... Args>
586  const UT_SqlStatementHandleId &id,
587  const UT_StringRef &sql,
588  Args &&...args)
589  {
590  UT_ErrorCode ec;
591  if (!prepare(id, sql, ec))
592  return UT_SqlResult(this);
593  bindAll(std::forward<Args>(args)...);
594 
595  step();
596 
597  return UT_SqlResult(this);
598  }
599 
600  template <typename... Args>
601  std::optional<std::tuple<Args...>> fetchOne(UT_ErrorCode* ec = nullptr)
602  {
603  constexpr int ColumnCount = sizeof...(Args);
604 
605  if (getError())
606  {
607  if (ec)
608  *ec = getError();
609  return std::nullopt;
610  }
611 
612  if (!hasRow())
613  {
614  if (ec && getError())
615  *ec = getError();
616  return std::nullopt;
617  }
618 
619  auto r = fetchRow_<Args...>(std::make_index_sequence<ColumnCount>{});
620 
621  if (getError())
622  {
623  if (ec)
624  *ec = getError();
625  return std::nullopt;
626  }
627 
628  /// Move to the next row
629  step();
630 
631  return r;
632  }
633 
634  template <typename... Args>
635  UT_Array<std::tuple<Args...>> fetchAll(UT_ErrorCode* ec = nullptr)
636  {
637  UT_Array<std::tuple<Args...>> rows;
638  if (getError())
639  {
640  if (ec)
641  *ec = getError();
642  return rows;
643  }
644 
645  if (!hasRow())
646  {
647  if (ec && getError())
648  *ec = getError();
649  return rows;
650  }
651 
652  constexpr int ColumnCount = sizeof...(Args);
653  auto idx_sequence = std::make_index_sequence<ColumnCount>{};
654  do
655  {
656  rows.emplace_back(fetchRow_<Args...>(idx_sequence));
657  } while (step());
658 
659  if (getError())
660  {
661  rows.clear();
662  if (ec)
663  *ec = getError();
664  }
665 
666  return rows;
667  }
668 
669  template <typename... Args>
670  std::optional<std::tuple<std::tuple<Args...>>> as(UT_ErrorCode* ec = nullptr)
671  {
672  if (getError())
673  {
674  if (ec)
675  *ec = getError();
676  return std::nullopt;
677  }
678 
679  if (!hasRow())
680  {
681  if (ec && getError())
682  *ec = getError();
683  return std::nullopt;
684  }
685 
686  constexpr int ColumnCount = sizeof...(Args);
687  return fetchRow_<Args...>(std::make_index_sequence<ColumnCount>{});
688  }
689 
691  UT_ErrorCode *ec = nullptr) const
692  {
693  return myImpl->tableExists(name, ec);
694  }
695 
696  int changes() const { return myImpl->changes(); }
697 
698 protected:
699  bool bindHelper(int)
700  { return true; }
701  template <typename T, typename... Args>
702  bool bindHelper(int idx, T value, Args &&... args)
703  {
704  if (!bind(idx, value))
705  return false;
706  return bindHelper(idx + 1, std::forward<Args>(args)...);
707  }
708 
709  template <class... Args, std::size_t... Idxs>
710  std::tuple<Args...>
711  fetchRow_(std::index_sequence<Idxs...>)
712  {
713  return std::make_tuple(get<Args>(Idxs)...);
714  }
715 
716 private:
718  const UT_SqlBaseDriver& myDriver;
719 };
720 
721 template <>
722 inline double
723 UT_SqlStatement::get<double>(int idx) const
724 {
725  return columnAsDouble(idx);
726 }
727 
728 template <>
730 UT_SqlStatement::get<UT_SqlStatement::null_tag_t>(int idx) const
731 {
732  return columnAsNull(idx);
733 }
734 
735 template <>
736 inline UT_StringHolder
737 UT_SqlStatement::get<UT_StringHolder>(int idx) const
738 {
739  return columnAsStr(idx);
740 }
741 
742 template <>
743 inline int
744 UT_SqlStatement::get<int>(int idx) const
745 {
746  return columnAsInt(idx);
747 }
748 
749 template <>
750 inline int64
751 UT_SqlStatement::get<int64>(int idx) const
752 {
753  return columnAsInt64(idx);
754 }
755 
756 template <>
757 inline bool
758 UT_SqlStatement::get<bool>(int idx) const
759 {
760  return columnAsBool(idx);
761 }
762 
763 template <>
764 inline const void *
765 UT_SqlStatement::get<const void *>(int idx) const
766 {
767  int size;
768  return columnAsBlob(idx, size);
769 }
770 
771 template <>
773 UT_SqlStatement::get<UT_SqlStatement::Blob>(int idx) const
774 {
775  return columnAsBlob(idx);
776 }
777 
778 inline const UT_ErrorCode &
780 {
781  return myStmt->getError();
782 }
783 
784 inline void
786 {
787  myStmt->step();
788 }
789 
790 inline bool
792 {
793  return myStmt && myStmt->hasRow();
794 }
795 
796 template <typename... Args>
797 inline std::tuple<Args...>
799 {
800  return myStmt->fetchOne<Args...>(ec);
801 }
802 
803 template <typename... Args>
804 inline UT_Array<std::tuple<Args...>>
806 {
807  return myStmt->fetchAll<Args...>(ec);
808 }
809 
810 template <typename... Args>
811 inline std::tuple<Args...>
813 {
814  return myStmt->as<Args...>(ec);
815 }
816 
818 {
819 public:
820  virtual ~UT_SqlBaseDriver() = default;
822 
823  virtual void setHostName(const UT_StringHolder& host)
824  {
825  }
826  virtual void setPort(int port)
827  {
828  }
829  virtual void setUserName(const UT_StringHolder& user)
830  {
831  }
832  virtual void setPassword(const UT_StringHolder& password)
833  {
834  }
835  virtual void setDatabaseName(const UT_StringHolder& db_name)
836  {
837  }
838  virtual void setConnectOptions(const UT_Options& options)
839  {
840  }
841 
842  virtual bool connect(UT_ErrorCode* ec = nullptr) = 0;
843  virtual bool close(UT_ErrorCode *ec = nullptr) = 0;
844  NO_DISCARD virtual bool isValid() const = 0;
845  NO_DISCARD virtual bool isReadOnly(
846  const char *db = "main",
847  UT_ErrorCode *ec = nullptr) const
848  = 0;
849 
850  NO_DISCARD virtual void* nativeAPI() = 0;
851  NO_DISCARD virtual void* nativeAPI() const = 0;
852 
853  NO_DISCARD virtual UT_SharedPtr<UT_SqlStatementImpl> createStatementImpl()
854  = 0;
855  NO_DISCARD virtual UT_SharedPtr<UT_SqlStatementImpl> createStatementImpl()
856  const
857  = 0;
858 
859  /// Check if the specified table exists.
860  NO_DISCARD virtual bool tableExists(
861  const UT_StringRef &name,
862  UT_ErrorCode *ec = nullptr) const
863  = 0;
864  NO_DISCARD virtual bool indexExists(
865  const UT_StringRef &name,
866  UT_ErrorCode *ec = nullptr) const
867  = 0;
868  NO_DISCARD virtual bool viewExists(
869  const UT_StringRef &name,
870  UT_ErrorCode *ec = nullptr) const = 0;
871  NO_DISCARD virtual bool columnExists(
872  const UT_StringRef &table_name,
873  const UT_StringRef &column_name,
874  UT_ErrorCode *ec = nullptr) const
875  = 0;
876  NO_DISCARD virtual UT_StringHolder errorMessage() const = 0;
877  NO_DISCARD virtual int errorCode() const = 0;
878  NO_DISCARD virtual int extendedErrorCode() const = 0;
879 
880  /// These are primarily used by UT_SqlTransaction (but can be used by any
881  /// client code) and provide an abstraction that resembles nested
882  /// transations. This is inspired by (and follows the same behaviour as):
883  /// https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase#beginTransaction()
884  virtual bool startTransaction(UT_ErrorCode *ec = nullptr) = 0;
885  virtual bool endTransaction(bool commit, UT_ErrorCode *ec = nullptr) = 0;
886 
887  /// Get a sql statement that is retrieved from the cache. If the statement
888  /// is not already cached then its compiled and then cached if the compiled
889  /// statement is valid.
890  virtual UT_SharedPtr<UT_SqlStatementImpl> cachedStatement(
891  const UT_SqlStatementHandleId &id,
892  const UT_StringRef &sql,
893  UT_ErrorCode *ec = nullptr) const
894  = 0;
895 
896  /// Find an sql handle based on its id. The sql statement must have already
897  /// been added from cachedStatement(). This method is typically used when
898  /// a statement has already been compiled and added to the cache but needs
899  /// to be dynamically looked up some time later.
900  virtual UT_SharedPtr<UT_SqlStatementImpl> findCachedStatement(
901  const UT_SqlStatementHandleId &id) const
902  = 0;
903 
904  NO_DISCARD virtual UT_StringHolder getSchema(
905  UT_ErrorCode *ec = nullptr) const
906  = 0;
907 
908  /// Helper function to run an sql statement with provided typed args.
909  template <typename... Args>
910  bool run(UT_ErrorCode *ec, const UT_StringRef &sql, Args &&...args)
911  {
912  UT_SqlStatement stmt(createStatementImpl());
913  if (sizeof...(Args) > 0)
914  stmt.bindAll(ec, std::forward<Args>(args)...);
915  stmt.step();
916  if (ec)
917  *ec = stmt.getError();
918  return !(bool)stmt.getError();
919  }
920  /// Returns the number of rows modified, inserted or deleted
921  virtual int exec(const UT_StringRef &sql, UT_ErrorCode *ec = nullptr) const
922  = 0;
923 
924 protected:
925  UT_SqlBaseDriver() = default;
926 };
927 
929 {
930 public:
931  static constexpr UT_StringLit theFilenameOpt = "SQLITE_FILENAME";
932  static constexpr UT_StringLit theBusyTimeoutOpt = "SQLITE_BUSY_TIMEOUT";
933 
934  UT_SqliteDriver();
935  ~UT_SqliteDriver() override;
936 
938 
939  void setDatabaseName(const UT_StringHolder& db_name) override
940  {
941  myFilename = db_name;
942  }
943  void setConnectOptions(const UT_Options& options) override;
944 
945  bool connect(UT_ErrorCode* ec = nullptr) override;
946  bool close(UT_ErrorCode *ec = nullptr) override;
947 
948  NO_DISCARD SYS_FORCE_INLINE bool isValid() const override
949  { return myCtx != nullptr && myFilename.isstring(); }
950 
951  NO_DISCARD bool isReadOnly(const char *db = "main",
952  UT_ErrorCode *ec = nullptr) const override;
953 
954  NO_DISCARD void *nativeAPI() override { return myCtx; }
955  NO_DISCARD void *nativeAPI() const override
956  {
957  return SYSconst_cast(this)->myCtx;
958  }
959 
960  /// Check the database's "data_version"
961  /// (see https://www.sqlite.org/pragma.html#pragma_data_version)
962  NO_DISCARD int dataVersion(UT_ErrorCode *ec = nullptr) const;
963 
964  /// Get/set the database's "user_version"
965  /// (see https://www.sqlite.org/pragma.html#pragma_user_version)
966  NO_DISCARD int userVersion(UT_ErrorCode *ec = nullptr) const;
967  void setUserVersion(int version, UT_ErrorCode *ec = nullptr) const;
968 
969  /// Check if the specified table exists.
971  UT_ErrorCode *ec = nullptr) const override;
973  UT_ErrorCode *ec = nullptr) const override;
975  UT_ErrorCode *ec = nullptr) const override;
977  const UT_StringRef& table_name,
978  const UT_StringRef& column_name,
979  UT_ErrorCode *ec = nullptr) const override;
980  NO_DISCARD UT_StringHolder errorMessage() const override;
981  NO_DISCARD int errorCode() const override;
982  NO_DISCARD int extendedErrorCode() const override;
983 
984  NO_DISCARD UT_StringHolder getSchema(UT_ErrorCode *ec = nullptr) const override;
985 
986  /// This sets a busy handler that sleeps for a specified amount of time
987  /// when a table is locked. The handler will sleep multiple times until at
988  /// least milliseconds of sleeping have accumulated. After the timeout the
989  /// handler returns 0 which causes the step() to return kSQLITE_BUSY.
990  void setBusyTimeout(int timeout_ms)
991  {
992  myBusyTimeout = timeout_ms;
993  }
994 
995  /// Copy the contents of this database into the provided destination
996  /// database. Return true on success and false otherwise.
997  /// On failure, the error code is set in the destination database.
998  bool copyTo(UT_SqliteDriver &destination, UT_ErrorCode *ec = nullptr)
999  const;
1000 
1003 
1004  /// Get a sql statement that is retrieved from the cache. If the statement
1005  /// is not already cached then its compiled and then cached if the compiled
1006  /// statement is valid.
1008  const UT_SqlStatementHandleId &id,
1009  const UT_StringRef& sql,
1010  UT_ErrorCode *ec = nullptr) const override;
1011 
1012  /// Find an sql handle based on its id. The sql statement must have already
1013  /// been added from cachedStatement(). This method is typically used when
1014  /// a statement has already been compiled and added to the cache but needs
1015  /// to be dynamically looked up some time later.
1017  const UT_SqlStatementHandleId& id) const override;
1018 
1019  /// These are primarily used by UT_SqlTransaction (but can be used by any
1020  /// client code) and provide an abstraction that resembles nested
1021  /// transations. This is inspired by (and follows the same behaviour as):
1022  /// https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase#beginTransaction()
1023  bool startTransaction(UT_ErrorCode *ec = nullptr) override;
1024  bool endTransaction(bool commit, UT_ErrorCode *ec = nullptr) override;
1025 
1026  int exec(const UT_StringRef &sql, UT_ErrorCode *ec = nullptr)
1027  const override;
1028 protected:
1029  bool schemaItemExists(
1030  const UT_StringRef& type,
1031  const UT_StringRef& name,
1032  UT_ErrorCode *ec) const;
1033 
1034 private:
1035  bool verifyOpen(
1036  const UT_StringHolder &filename,
1037  UT_ErrorCode *ec);
1038 
1039  mutable std::map<UT_SqlStatementHandleId,
1040  UT_SharedPtr<UT_SqlStatementImpl>> myCachedStatements;
1041  sqlite3 *myCtx = nullptr;
1042  SYS_AtomicCounter myActiveTransactionDepth;
1043  bool myShouldCommitTransaction;
1044 
1045  UT_StringHolder myFilename;
1046  int myBusyTimeout = -1;
1047 };
1048 
1050 
1052 {
1053 public:
1054  using driver_factory_t = UT_UniquePtr<UT_SqlBaseDriver>(*)();
1055 
1056  UT_SqlDatabase(driver_factory_t factory = UTsqliteFactory) :
1057  myDriver(factory())
1058  {}
1059 
1061  {
1062  return myDriver.get();
1063  }
1064  const UT_SqlBaseDriver* driver() const
1065  {
1066  return myDriver.get();
1067  }
1068 
1069  void setHostName(const UT_StringRef& host)
1070  {
1071  myDriver->setHostName(host);
1072  }
1073  void setPort(int port)
1074  {
1075  myDriver->setPort(port);
1076  }
1077  void setUserName(const UT_StringRef& user)
1078  {
1079  myDriver->setUserName(user);
1080  }
1081  void setPassword(const UT_StringRef& password)
1082  {
1083  myDriver->setPassword(password);
1084  }
1085  void setDatabaseName(const UT_StringRef& db_name)
1086  {
1087  myDriver->setDatabaseName(db_name);
1088  }
1089  void setConnectOptions(const UT_Options& options)
1090  {
1091  myDriver->setConnectOptions(options);
1092  }
1093 
1094  /// Close the sql connection to the db backend
1095  bool close(UT_ErrorCode *ec = nullptr) { return myDriver->close(ec); }
1096  /// Create a db connection with a custom db backend
1097  bool connect(UT_ErrorCode *ec = nullptr)
1098  {
1099  return myDriver && myDriver->connect(ec);
1100  }
1101  /// Check the underlying connection is valid and usable
1102  NO_DISCARD bool isValid() const
1103  {
1104  return myDriver && myDriver->isValid();
1105  }
1107  const char *db = "main",
1108  UT_ErrorCode *ec = nullptr) const
1109  {
1110  return myDriver->isReadOnly(db, ec);
1111  }
1113  {
1114  return myDriver->createStatementImpl();
1115  }
1117  {
1118  return myDriver->createStatementImpl();
1119  }
1120  /// Get a sql statement that is retrieved from the cache. If the statement
1121  /// is not already cached then its compiled and then cached if the compiled
1122  /// statement is valid.
1124  const UT_SqlStatementHandleId &id,
1125  const UT_StringRef& sql,
1126  UT_ErrorCode *ec = nullptr) const
1127  {
1128  return myDriver->cachedStatement(id, sql, ec);
1129  }
1130 
1131  /// Find an sql handle based on its id. The sql statement must have already
1132  /// been added from cachedStatement(). This method is typically used when
1133  /// a statement has already been compiled and added to the cache but needs
1134  /// to be dynamically looked up some time later.
1136  const UT_SqlStatementHandleId& id) const
1137  {
1138  return myDriver->findCachedStatement(id);
1139  }
1140  /// Helper function to run an sql statement with provided typed args.
1141  template <typename... Args>
1142  bool run(UT_ErrorCode *ec, const UT_StringRef &sql, Args &&... args)
1143  {
1144  UT_SqlStatement stmt(createStatementImpl());
1145  if (sizeof...(Args) > 0)
1146  stmt.bindAll(ec, std::forward<Args>(args)...);
1147  stmt.step();
1148  if (ec)
1149  *ec = stmt.getError();
1150  return !(bool)stmt.getError();
1151  }
1152  /// Returns the number of rows modified, inserted or deleted
1153  int exec(const UT_StringRef &sql, UT_ErrorCode *ec = nullptr) const
1154  {
1155  return myDriver->exec(sql, ec);
1156  }
1157 
1158  /// Check if the specified table exists.
1160  UT_ErrorCode *ec = nullptr) const
1161  {
1162  return myDriver->tableExists(name, ec);
1163  }
1165  UT_ErrorCode *ec = nullptr) const
1166  {
1167  return myDriver->indexExists(name, ec);
1168  }
1170  UT_ErrorCode *ec = nullptr) const
1171  {
1172  return myDriver->viewExists(name, ec);
1173  }
1175  const UT_StringRef& table_name,
1176  const UT_StringRef& column_name,
1177  UT_ErrorCode *ec = nullptr) const
1178  {
1179  return myDriver->columnExists(table_name, column_name, ec);
1180  }
1182  {
1183  return myDriver->errorMessage();
1184  }
1185  NO_DISCARD int errorCode() const
1186  {
1187  return myDriver->errorCode();
1188  }
1190  {
1191  return myDriver->extendedErrorCode();
1192  }
1193 
1194  /// These are primarily used by UT_SqlTransaction (but can be used by any
1195  /// client code) and provide an abstraction that resembles nested transations.
1196  /// This is inspired by (and follows the same behaviour as):
1197  /// https://developer.android.com/reference/android/database/sqlite/SQLiteDatabase#beginTransaction()
1198  bool startTransaction(UT_ErrorCode *ec = nullptr)
1199  {
1200  return myDriver->startTransaction(ec);
1201  }
1202  bool endTransaction(bool commit, UT_ErrorCode *ec = nullptr)
1203  {
1204  return myDriver->endTransaction(commit, ec);
1205  }
1206 
1208  {
1209  return myDriver->getSchema(ec);
1210  }
1211 
1212  NO_DISCARD void* nativeAPI() { return myDriver->nativeAPI(); }
1213  NO_DISCARD void* nativeAPI() const { return myDriver->nativeAPI(); }
1214 
1215 protected:
1217 };
1218 
1219 // Transactions are a way to group SQL statements.
1220 // This class ensures we properly setup and execute the group (or rollback if needed)
1221 //
1222 // NOTE: If commit() is not explicitly called before the object is destroyed
1223 // (e.g., goes out of scope), the transaction will be aborted (rolled back)
1224 //
1226 {
1227 public:
1228  UT_SqlTransaction(UT_SqlDatabase &connection, UT_ErrorCode *ec = nullptr);
1229  ~UT_SqlTransaction();
1231 
1232  void commit(UT_ErrorCode *ec = nullptr);
1233 
1234 private:
1235  bool myCommited;
1236  UT_SqlDatabase &myConnection;
1237 };
1238 
1239 #endif // __UT_SQL_H__
NO_DISCARD null_tag_t columnAsNull(int idx) const
Definition: UT_SQL.h:437
virtual void setPassword(const UT_StringHolder &password)
Definition: UT_SQL.h:832
UT_SqlResult & operator*()
Definition: UT_SQL.h:314
GT_API const UT_StringHolder filename
virtual NO_DISCARD int extendedErrorCode() const =0
UT_SqlStatementHandleId(const char *source_file, exint source_line)
Definition: UT_SQL.h:76
bool step()
Definition: UT_SQL.h:551
const UT_ErrorCode & getError() const
Definition: UT_SQL.h:558
UT_SharedPtr< UT_SqlStatementImpl > findCachedStatement(const UT_SqlStatementHandleId &id) const
Definition: UT_SQL.h:1135
virtual NO_DISCARD int columnCount() const =0
const UT_SqlResult & operator*() const
Definition: UT_SQL.h:311
virtual NO_DISCARD int64 columnAsInt64(int idx) const =0
#define NO_DISCARD
Definition: UT_SQL.h:40
virtual NO_DISCARD UT_IntArray columnAsIntArray(int idx) const =0
UT_SqlDatabase(driver_factory_t factory=UTsqliteFactory)
Definition: UT_SQL.h:1056
bool bind(int idx, const UT_StringArray &value)
Definition: UT_SQL.h:503
virtual bool connect(UT_ErrorCode *ec=nullptr)=0
void setDatabaseName(const UT_StringHolder &db_name) override
Definition: UT_SQL.h:939
virtual NO_DISCARD bool isReadOnly(const char *db="main", UT_ErrorCode *ec=nullptr) const =0
const void * myPtr
Definition: UT_SQL.h:99
bool bind(int idx, const char *value)
Definition: UT_SQL.h:474
std::forward_iterator_tag iterator_category
Definition: UT_SQL.h:287
UT_ErrorCode make_error_code(UT::SqlError e)
Definition: UT_SQL.h:60
NO_DISCARD bool tableExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const
Definition: UT_SQL.h:690
virtual NO_DISCARD UT_StringHolder columnName(int idx) const =0
NO_DISCARD int columnCount() const
Definition: UT_SQL.h:445
std::optional< std::tuple< std::tuple< Args...> > > as(UT_ErrorCode *ec=nullptr)
Definition: UT_SQL.h:670
virtual NO_DISCARD bool indexExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const =0
bool bind(int idx, const UT_Int64Array &value)
Definition: UT_SQL.h:499
bool bind(int idx, null_tag_t)
Definition: UT_SQL.h:466
NO_DISCARD int extendedErrorCode() const
Definition: UT_SQL.h:1189
void setBusyTimeout(int timeout_ms)
Definition: UT_SQL.h:990
NO_DISCARD bool tableExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const
Check if the specified table exists.
Definition: UT_SQL.h:1159
const char * sql() const
Definition: UT_SQL.h:459
const UT_SqlBaseDriver * driver() const
Definition: UT_SQL.h:1064
SYS_FORCE_INLINE T * SYSconst_cast(const T *foo)
Definition: SYS_Types.h:136
NO_DISCARD bool columnAsBool(int idx) const
Definition: UT_SQL.h:410
virtual const char * sql() const =0
const UT_ErrorCode & getError() const
Definition: UT_SQL.h:779
int64 exint
Definition: SYS_Types.h:125
NO_DISCARD Blob columnAsBlob(int idx) const
Definition: UT_SQL.h:433
bool bind(int idx, Blob blob)
Definition: UT_SQL.h:513
virtual void prepare(const UT_StringRef &sql, UT_ErrorCode *ec=nullptr)=0
bool hasResults() const
Definition: UT_SQL.h:791
virtual void setPort(int port)
Definition: UT_SQL.h:826
#define UT_API
Definition: UT_API.h:14
UT_SqlResult execute(const UT_StringRef &sql, Args &&...args)
Helper function to create a new statement to run a new sql statement.
Definition: UT_SQL.h:569
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
Definition: thread.h:613
void close() override
std::error_category UT_ErrorCategory
Definition: UT_ErrorCode.h:22
virtual bool step()=0
const iterator begin() const
Definition: UT_SQL.h:349
void setHostName(const UT_StringRef &host)
Definition: UT_SQL.h:1069
int changes() const overridefinal
Definition: UT_SQL.h:245
virtual bool close(UT_ErrorCode *ec=nullptr)=0
NO_DISCARD UT_StringHolder columnAsStr(int idx) const
Definition: UT_SQL.h:418
GLintptr GLsizeiptr GLboolean commit
Definition: glcorearb.h:3363
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
const iterator cend() const
Definition: UT_SQL.h:361
NO_DISCARD bool isReadOnly(const char *db="main", UT_ErrorCode *ec=nullptr) const
Definition: UT_SQL.h:1106
bool run(UT_ErrorCode *ec, const UT_StringRef &sql, Args &&...args)
Helper function to run an sql statement with provided typed args.
Definition: UT_SQL.h:1142
virtual NO_DISCARD bool viewExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const =0
NO_DISCARD UT_SharedPtr< UT_SqlStatementImpl > createStatementImpl()
Definition: UT_SQL.h:1112
std::tuple< Args...> as(UT_ErrorCode *ec=nullptr)
Definition: UT_SQL.h:812
bool operator!=(const iterator &rhs) const
Definition: UT_SQL.h:307
virtual UT_SharedPtr< UT_SqlStatementImpl > findCachedStatement(const UT_SqlStatementHandleId &id) const =0
UT_SqlStatementImpl(const UT_SqlBaseDriver &driver)
Definition: UT_SQL.h:183
UT_API const UT_ErrorCategory & GetSqlErrorCategory()
bool bindHelper(int)
Definition: UT_SQL.h:699
std::tuple< Args...> fetchOne(UT_ErrorCode *ec=nullptr)
Definition: UT_SQL.h:798
virtual void reset(bool clear_bindings=false)=0
bool hasRow()
Definition: UT_SQL.h:540
GLboolean reset
Definition: glad.h:5138
bool bind(int idx, bool value)
Definition: UT_SQL.h:486
virtual void setDatabaseName(const UT_StringHolder &db_name)
Definition: UT_SQL.h:835
bool operator<(const UT_SqlStatementHandleId &id) const
Definition: UT_SQL.h:80
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
bool startTransaction(UT_ErrorCode *ec=nullptr)
Definition: UT_SQL.h:1198
NO_DISCARD bool indexExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const
Definition: UT_SQL.h:1164
NO_DISCARD void * nativeAPI() const
Definition: UT_SQL.h:1213
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)
Definition: UT_SQL.h:490
virtual NO_DISCARD UT_StringHolder errorMessage() const =0
NO_DISCARD void * nativeAPI()
Definition: UT_SQL.h:1212
iterator & operator++()
Definition: UT_SQL.h:292
NO_DISCARD UT_StringHolder errorMessage() const
Definition: UT_SQL.h:1181
const UT_SqlBaseDriver & driver() const
Definition: UT_SQL.h:115
GLuint GLuint end
Definition: glcorearb.h:475
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
NO_DISCARD double columnAsDouble(int idx) const
Definition: UT_SQL.h:422
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.
Definition: UT_SQL.h:910
bool bindAll(Args &&...args)
Definition: UT_SQL.h:529
const UT_ErrorCode & getError() const
Definition: UT_SQL.h:167
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
NO_DISCARD UT_SharedPtr< UT_SqlStatementImpl > createStatementImpl() const
Definition: UT_SQL.h:1116
UT_API const UT_ErrorCategory & GetSqliteErrorCategory()
virtual NO_DISCARD int columnAsInt(int idx) const =0
long long int64
Definition: SYS_Types.h:116
const iterator cbegin() const
Definition: UT_SQL.h:357
UT_Array< std::tuple< Args...> > fetchAll(UT_ErrorCode *ec=nullptr)
Definition: UT_SQL.h:635
bool isDone() const
Definition: UT_SQL.h:326
virtual bool endTransaction(bool commit, UT_ErrorCode *ec=nullptr)=0
NO_DISCARD int columnBytes(int idx) const
Definition: UT_SQL.h:453
iterator begin()
Definition: UT_SQL.h:341
const UT_SqlResult * operator->() const
Definition: UT_SQL.h:318
NO_DISCARD bool isValid() const
Definition: UT_SQL.h:535
virtual NO_DISCARD bool tableExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const =0
int SYSstrcmp(const char *a, const char *b)
Definition: SYS_String.h:237
NO_DISCARD int columnAsInt(int idx) const
Definition: UT_SQL.h:406
bool bindNull(int idx)
Definition: UT_SQL.h:532
virtual NO_DISCARD UT_SharedPtr< UT_SqlStatementImpl > createStatementImpl()=0
bool bind(int idx, const UT_IntArray &value)
Definition: UT_SQL.h:495
GLuint const GLchar * name
Definition: glcorearb.h:786
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.
Definition: UT_SQL.h:585
bool bind(int idx, const void *value, int size)
Definition: UT_SQL.h:509
void setConnectOptions(const UT_Options &options)
Definition: UT_SQL.h:1089
NO_DISCARD SYS_FORCE_INLINE bool isValid() const override
Definition: UT_SQL.h:948
NO_DISCARD bool viewExists(const UT_StringRef &name, UT_ErrorCode *ec=nullptr) const
Definition: UT_SQL.h:1169
virtual NO_DISCARD bool isValid() const =0
NO_DISCARD UT_StringHolder columnName(int idx) const
Definition: UT_SQL.h:441
UT_API UT_UniquePtr< UT_SqlBaseDriver > UTsqliteFactory()
virtual NO_DISCARD int errorCode() const =0
bool bind(int idx, int64 value)
Definition: UT_SQL.h:482
virtual bool run()=0
const iterator end() const
Definition: UT_SQL.h:353
bool run()
Definition: UT_SQL.h:546
virtual NO_DISCARD DataType columnType(int idx) const =0
UT_SqlResult * operator->()
Definition: UT_SQL.h:322
GT_API const UT_StringHolder version
std::size_t mySize
Definition: UT_SQL.h:100
std::error_code UT_ErrorCode
Definition: UT_ErrorCode.h:20
NO_DISCARD bool isValid() const
Check the underlying connection is valid and usable.
Definition: UT_SQL.h:1102
Error getError()
Definition: oidn.hpp:823
bool close(UT_ErrorCode *ec=nullptr)
Close the sql connection to the db backend.
Definition: UT_SQL.h:1095
void reset(bool clear_bindings=false)
Definition: UT_SQL.h:401
GLsizeiptr size
Definition: glcorearb.h:664
bool hasRow() overridefinal
Definition: UT_SQL.h:249
virtual void setHostName(const UT_StringHolder &host)
Definition: UT_SQL.h:823
A map of string to various well defined value types.
Definition: UT_Options.h:84
bool endTransaction(bool commit, UT_ErrorCode *ec=nullptr)
Definition: UT_SQL.h:1202
void setPassword(const UT_StringRef &password)
Definition: UT_SQL.h:1081
bool bind(int idx, int value)
Definition: UT_SQL.h:478
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.
Definition: UT_SQL.h:1097
virtual NO_DISCARD const void * columnAsBlob(int idx, int &size) const =0
const UT_SqlBaseDriver & myDriver
Definition: UT_SQL.h:187
virtual void setUserName(const UT_StringHolder &user)
Definition: UT_SQL.h:829
NO_DISCARD void * nativeAPI() const override
Definition: UT_SQL.h:955
NO_DISCARD int errorCode() const
Definition: UT_SQL.h:1185
virtual NO_DISCARD int columnBytes(int idx) const =0
bool bind(int idx, Blob blob)
Definition: UT_SQL.h:160
NO_DISCARD void * nativeAPI() override
Definition: UT_SQL.h:954
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
Definition: UT_SQL.h:1123
UT_NON_COPYABLE(UT_SqlBaseDriver)
bool bind(int idx, const UT_StringRef &value)
Definition: UT_SQL.h:470
SqlError
Error codes to describe errors as a result of UT_SQL.
Definition: UT_SQL.h:49
NO_DISCARD UT_StringHolder getSchema(UT_ErrorCode *ec=nullptr) const
Definition: UT_SQL.h:1207
iterator end()
Definition: UT_SQL.h:345
**If you just want to fire and args
Definition: thread.h:609
virtual NO_DISCARD UT_StringHolder columnAsStr(int idx) const =0
std::tuple< Args...> fetchRow_(std::index_sequence< Idxs...>)
Definition: UT_SQL.h:711
virtual void setConnectOptions(const UT_Options &options)
Definition: UT_SQL.h:838
virtual bool bind(int idx, null_tag_t)=0
NO_DISCARD const void * columnAsBlob(int idx, int &size) const
Definition: UT_SQL.h:429
Definition: core.h:1131
UT_NON_COPYABLE(UT_SqlStatementImpl)
bool operator==(const iterator &rhs) const
Definition: UT_SQL.h:299
virtual NO_DISCARD null_tag_t columnAsNull(int idx) const =0
void next()
Definition: UT_SQL.h:785
NO_DISCARD bool columnExists(const UT_StringRef &table_name, const UT_StringRef &column_name, UT_ErrorCode *ec=nullptr) const
Definition: UT_SQL.h:1174
UT_Array< std::tuple< Args...> > fetchAll(UT_ErrorCode *ec=nullptr)
Definition: UT_SQL.h:805
GLboolean r
Definition: glcorearb.h:1222
UT_SqlBaseDriver * driver()
Definition: UT_SQL.h:1060
NO_DISCARD int64 columnAsInt64(int idx) const
Definition: UT_SQL.h:414
bool bindHelper(int idx, T value, Args &&...args)
Definition: UT_SQL.h:702
NO_DISCARD DataType columnType(int idx) const
Definition: UT_SQL.h:449
virtual bool startTransaction(UT_ErrorCode *ec=nullptr)=0
UT_UniquePtr< UT_SqlBaseDriver > myDriver
Definition: UT_SQL.h:1216
type
Definition: core.h:1059
UT_ErrorCode myError
Definition: UT_SQL.h:188
void setUserName(const UT_StringRef &user)
Definition: UT_SQL.h:1077
void setDatabaseName(const UT_StringRef &db_name)
Definition: UT_SQL.h:1085
void setPort(int port)
Definition: UT_SQL.h:1073
std::optional< std::tuple< Args...> > fetchOne(UT_ErrorCode *ec=nullptr)
Definition: UT_SQL.h:601
int exec(const UT_StringRef &sql, UT_ErrorCode *ec=nullptr) const
Returns the number of rows modified, inserted or deleted.
Definition: UT_SQL.h:1153
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.
int changes() const
Definition: UT_SQL.h:696
PcpNodeRef_ChildrenIterator begin(const PcpNodeRef::child_const_range &r)
Support for range-based for loops for PcpNodeRef children ranges.
Definition: node.h:558