2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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 #include "hphp/util/db-query.h"
18 #include "hphp/util/db-conn.h"
19 #include "hphp/util/db-dataset.h"
23 ///////////////////////////////////////////////////////////////////////////////
25 DBQuery::DBQuery(DBConn
*conn
, const char *sql
, ...)
26 : m_conn(conn
), m_insert(false) {
30 Util::string_vsnprintf(m_base
, sql
, ap
);
34 ///////////////////////////////////////////////////////////////////////////////
36 void DBQuery::filterBy(const char *fmt
, Op op
/* = And */) {
39 if (m_where
.empty()) {
43 case And
: m_where
+= " and "; break;
44 case Or
: m_where
+= " or "; break;
51 void DBQuery::filterBy(const char *fmt
, const char *value
, Op op
/* = And */) {
55 m_conn
->escapeString(value
, escaped
);
56 char *where
= (char*)malloc(strlen(fmt
) + escaped
.size() - 1);
57 sprintf(where
, fmt
, escaped
.c_str());
63 void DBQuery::filterBy(const char *fmt
, const std::string
&value
,
65 filterBy(fmt
, value
.c_str(), op
);
68 void DBQuery::filterBy(const char *fmt
, int value
, Op op
/* = And */) {
69 char *where
= (char*)malloc(strlen(fmt
) + 16);
70 sprintf(where
, fmt
, value
);
76 void DBQuery::filterBy(const char *fmt
, unsigned int value
,
78 filterBy(fmt
, (int)value
, op
);
81 void DBQuery::filterBy(const char *fmt
, DBQueryFilterPtr filter
,
83 assert(!filter
->isEmpty());
90 void DBQuery::orderBy(const char *field
, bool ascending
/* = true */) {
91 m_order
+= m_order
.empty() ? " ORDER BY " : ",";
98 void DBQuery::limit(int count
, int offset
/* = 0 */) {
101 m_limit
+= boost::lexical_cast
<string
>(offset
) + ", ";
103 m_limit
+= boost::lexical_cast
<string
>(count
);
106 void DBQuery::insert(const char *fmt
, ...) {
112 m_values
.push_back(m_format
);
115 void DBQuery::append(const char *extra
) {
116 m_extra
+= (extra
? extra
: "");
119 void DBQuery::setField(const char *fmt
) {
120 m_values
.push_back(fmt
);
123 void DBQuery::setField(const char *fmt
, const char *value
) {
124 setField(fmt
, value
, strlen(value
));
127 void DBQuery::setField(const char *fmt
, const std::string
&value
) {
128 setField(fmt
, value
.data(), value
.length());
131 void DBQuery::setField(const char *fmt
, const char *binary
, int len
) {
135 m_conn
->escapeString(binary
, len
, escaped
);
137 char *buffer
= (char*)malloc(strlen(fmt
) + escaped
.size());
139 throw std::bad_alloc();
141 sprintf(buffer
, fmt
, escaped
.c_str());
146 void DBQuery::setField(const char *fmt
, int value
) {
147 setField(fmt
, boost::lexical_cast
<string
>(value
).c_str());
150 void DBQuery::setField(const char *fmt
, unsigned int value
) {
151 setField(fmt
, (int)value
);
154 ///////////////////////////////////////////////////////////////////////////////
156 int DBQuery::execute() {
157 return execute(nullptr);
160 int DBQuery::execute(DBDataSet
&ds
) {
164 int DBQuery::execute(DBDataSet
*ds
) {
166 assert(m_conn
->isOpened());
169 for (const char *sql
= getFirstSql(); sql
; sql
= getNextSql()) {
170 affected
+= m_conn
->execute(sql
, ds
);
175 int DBQuery::execute(int &result
) {
177 int affected
= execute(ds
);
179 for (ds
.moveFirst(); ds
.getRow(); ds
.moveNext()) {
180 result
+= ds
.getIntField(0);
185 int DBQuery::execute(unsigned int &result
) {
187 int affected
= execute(ds
);
189 for (ds
.moveFirst(); ds
.getRow(); ds
.moveNext()) {
190 result
+= ds
.getUIntField(0);
195 ///////////////////////////////////////////////////////////////////////////////
197 const char *DBQuery::getFirstSql() {
199 const char *where
= m_filter
->getFirst(m_where
);
201 return getSql(where
);
203 return getSql(m_where
.c_str());
206 const char *DBQuery::getNextSql() {
208 const char *where
= m_filter
->getNext(m_where
);
209 if (where
) return getSql(where
);
214 const char *DBQuery::getSql(const char *where
) {
215 if (m_values
.empty()) {
216 m_sql
= m_base
+ where
+ m_order
+ m_limit
+ m_extra
;
217 } else if (m_insert
) {
219 int total
= m_base
.size() + 8 + m_extra
.size();
220 for (unsigned int i
= 0; i
< m_values
.size(); i
++) {
221 total
+= m_values
[i
].size() + 4;
223 m_sql
.reserve(total
);
227 for (unsigned int i
= 0; i
< m_values
.size(); i
++) {
228 if (i
> 0) m_sql
+= ", ";
230 m_sql
+= m_values
[i
];
237 for (unsigned int i
= 0; i
< m_values
.size(); i
++) {
238 if (i
> 0) m_sql
+= ",";
239 m_sql
+= m_values
[i
];
245 return m_sql
.c_str();
248 ///////////////////////////////////////////////////////////////////////////////
250 const char *DBQuery::format(const char *fmt
, ...) {
255 return m_format
.c_str();
258 const char *DBQuery::format(const char *fmt
, va_list ap
) {
261 for (string::size_type pos
= m_format
.find('%');
262 pos
!= string::npos
&& pos
< m_format
.length() - 1;
263 pos
= m_format
.find('%', pos
+ 1)) {
264 switch (m_format
[pos
+1]) {
268 const char *value
= va_arg(ap
, const char *);
270 m_conn
->escapeString(value
, escaped
);
271 m_format
.replace(pos
, 2, escaped
);
272 pos
+= escaped
.size();
277 int value
= va_arg(ap
, int);
280 sprintf(buf
, "%d", value
);
281 m_format
.replace(pos
, 2, buf
);
287 long value
= va_arg(ap
, long);
290 sprintf(buf
, "%ld", value
);
291 m_format
.replace(pos
, 2, buf
);
296 m_format
.erase(pos
, 1);
303 return m_format
.c_str();
306 std::string
DBQuery::escapeFieldName(const char *fieldNameList
) {
307 assert(fieldNameList
);
309 ret
+= fieldNameList
;
311 Util::replaceAll(ret
, ",", "`,`");
315 std::string
DBQuery::escapeFieldName(const std::string
&fieldNameList
) {
316 return escapeFieldName(fieldNameList
.c_str());
319 ///////////////////////////////////////////////////////////////////////////////