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