2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_VM_REPO_HELPERS_H_
18 #define incl_HPHP_VM_REPO_HELPERS_H_
20 #include "hphp/runtime/base/attr.h"
21 #include "hphp/runtime/base/types.h"
23 #include "hphp/util/md5.h"
24 #include "hphp/util/portability.h"
28 #include <folly/portability/Stdio.h>
32 // Forward declaration.
44 RepoIdCount
= 2 // Number of database IDs.
47 struct RepoExc
: std::exception
{
48 RepoExc(ATTRIBUTE_PRINTF_STRING
const char* fmt
, ...)
49 ATTRIBUTE_PRINTF(2, 3) {
53 if (vasprintf(&msg
, fmt
, ap
) == -1) {
61 const std::string
& msg() const { return m_msg
; }
62 const char* what() const noexcept override
{ return m_msg
.c_str(); }
69 explicit RepoStmt(Repo
& repo
);
74 bool prepared() const { return (m_stmt
!= nullptr); }
75 void prepare(const std::string
& sql
); // throws(RepoExc)
77 Repo
& repo() const { return m_repo
; }
78 sqlite3_stmt
*& get() { return m_stmt
; }
79 const std::string
& sql() const { return m_sql
; }
87 // Under most circumstances RepoTxnQuery should be used instead of RepoQuery;
88 // queries outside of transactions are fraught with peril.
90 explicit RepoQuery(RepoStmt
& stmt
)
91 : m_stmt(stmt
), m_row(false), m_done(false) {
92 assertx(m_stmt
.prepared());
94 ~RepoQuery() { m_stmt
.reset(); }
96 void bindBlob(const char* paramName
, const void* blob
, size_t size
,
98 void bindBlob(const char* paramName
, const BlobEncoder
& blob
,
100 void bindMd5(const char* paramName
, const MD5
& md5
);
101 void bindTypedValue(const char* paramName
, const TypedValue
& tv
);
102 void bindText(const char* paramName
, const char* text
, size_t size
,
103 bool isStatic
=false);
104 void bindStaticString(const char* paramName
, const StringData
* sd
);
105 void bindStdString(const char* paramName
, const std::string
& s
);
106 void bindStringPiece(const char* paramName
, const folly::StringPiece s
);
107 void bindDouble(const char* paramName
, double val
);
108 void bindInt(const char* paramName
, int val
);
109 void bindId(const char* paramName
, Id id
);
110 void bindOffset(const char* paramName
, Offset offset
);
111 void bindAttr(const char* paramName
, Attr attrs
);
112 void bindBool(const char* paramName
, bool b
);
113 void bindInt64(const char* paramName
, int64_t val
);
114 void bindNull(const char* paramName
);
116 void step(); // throws(RepoExc)
117 bool row() const { return m_row
; }
118 bool done() const { return m_done
; }
120 void exec(); // throws(RepoExc)
122 // rowid() returns the row id associated with the most recent successful
123 // insert. Thus the rowid is irrelevant for non-insert queries.
124 int64_t getInsertedRowid();
125 bool isBlob(int iCol
);
126 bool isText(int iCol
);
127 bool isDouble(int iCol
);
128 bool isInt(int iCol
);
129 bool isNull(int iCol
);
131 // Get the column value as the named type. If the value cannot be converted
132 // into the named type then an error is thrown.
133 void getBlob(int iCol
, const void*& blob
, size_t& size
); // throws(RepoExc)
134 BlobDecoder
getBlob(int iCol
); // throws(RepoExc)
135 void getMd5(int iCol
, MD5
& md5
); // throws(RepoExc)
136 void getTypedValue(int iCol
, TypedValue
& tv
); // throws(RepoExc)
137 void getText(int iCol
, const char*& text
); // throws(RepoExc)
138 void getText(int iCol
, const char*& text
, size_t& size
); // throws(RepoExc)
139 void getStaticString(int iCol
, StringData
*& s
); // throws(RepoExc)
140 void getStdString(int iCol
, std::string
& s
); // throws(RepoExc)
141 void getDouble(int iCol
, double& val
); // throws(RepoExc)
142 void getInt(int iCol
, int& val
); // throws(RepoExc)
143 void getId(int iCol
, Id
& id
); // throws(RepoExc)
144 void getOffset(int iCol
, Offset
& offset
); // throws(RepoExc)
145 void getAttr(int iCol
, Attr
& attrs
); // throws(RepoExc)
146 void getBool(int iCol
, bool& b
); // throws(RepoExc)
147 void getInt64(int iCol
, int64_t& val
); // throws(RepoExc)
156 * Transaction guard object.
158 * Semantics: the guard object will rollback the transaction unless
159 * you tell it not to. Call .commit() when you want things to stay.
162 explicit RepoTxn(Repo
& repo
); // throws(RepoExc)
165 RepoTxn(const RepoTxn
&) = delete;
166 RepoTxn
& operator=(const RepoTxn
&) = delete;
169 * All these routines may throw if there is an error accessing the
170 * repo. The RepoTxn object will rollback the entire transaction in
171 * any of these cases (which technically means they only provide the
172 * basic exception safety guarantee, even though the whole point is
173 * to behave transactionally. ;)
175 void prepare(RepoStmt
& stmt
, const std::string
& sql
); // throws(RepoExc)
176 void exec(const std::string
& sQuery
); // throws(RepoExc)
177 void commit(); // throws(RepoExc)
179 bool error() const { return m_error
; }
182 friend struct RepoTxnQuery
;
183 void step(RepoQuery
& query
); // throws(RepoExc)
184 void exec(RepoQuery
& query
); // throws(RepoExc)
185 void rollback(); // nothrow
191 template<class F
> void rollback_guard(const char* func
, F f
);
194 struct RepoTxnQuery
: RepoQuery
{
195 RepoTxnQuery(RepoTxn
& txn
, RepoStmt
& stmt
)
196 : RepoQuery(stmt
), m_txn(txn
) {
199 void step(); // throws(RepoExc)
200 void exec(); // throws(RepoExc)
207 explicit RepoProxy(Repo
& repo
) : m_repo(repo
) {}
211 struct Stmt
: RepoStmt
{
212 Stmt(Repo
& repo
, int repoId
) : RepoStmt(repo
), m_repoId(repoId
) {}