2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010- 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 "ext_async_mysql.h"
23 #include <squangle/mysql_client/AsyncHelpers.h>
25 #include "hphp/runtime/base/array-init.h"
26 #include "hphp/runtime/ext/ext_collections.h"
27 #include "hphp/runtime/ext/mysql/ext_mysql.h"
28 #include "hphp/runtime/ext/mysql/mysql_common.h"
29 #include "hphp/runtime/vm/native-data.h"
30 #include "hphp/system/systemlib.h"
31 #include "hphp/util/logger.h"
34 ///////////////////////////////////////////////////////////////////////////////
36 #define DEFINE_CONSTANT(name) \
37 const int64_t k_##name = name; \
38 const StaticString s_##name(#name); \
40 #define IMPLEMENT_GET_CLASS(cls) \
41 Class* cls::getClass() { \
42 if (s_class == nullptr) { \
43 s_class = Unit::lookupClass(s_className.get()); \
49 // expose the mysql flags
50 DEFINE_CONSTANT(NOT_NULL_FLAG
);
51 DEFINE_CONSTANT(PRI_KEY_FLAG
);
52 DEFINE_CONSTANT(UNIQUE_KEY_FLAG
);
53 DEFINE_CONSTANT(MULTIPLE_KEY_FLAG
);
54 DEFINE_CONSTANT(UNSIGNED_FLAG
);
55 DEFINE_CONSTANT(ZEROFILL_FLAG
);
56 DEFINE_CONSTANT(BINARY_FLAG
);
57 DEFINE_CONSTANT(AUTO_INCREMENT_FLAG
);
58 DEFINE_CONSTANT(ENUM_FLAG
);
59 DEFINE_CONSTANT(SET_FLAG
);
60 DEFINE_CONSTANT(BLOB_FLAG
);
61 DEFINE_CONSTANT(TIMESTAMP_FLAG
);
62 DEFINE_CONSTANT(NUM_FLAG
);
63 DEFINE_CONSTANT(NO_DEFAULT_VALUE_FLAG
);
65 // expose the mysql field types
66 DEFINE_CONSTANT(MYSQL_TYPE_TINY
);
67 DEFINE_CONSTANT(MYSQL_TYPE_SHORT
);
68 DEFINE_CONSTANT(MYSQL_TYPE_LONG
);
69 DEFINE_CONSTANT(MYSQL_TYPE_INT24
);
70 DEFINE_CONSTANT(MYSQL_TYPE_LONGLONG
);
71 DEFINE_CONSTANT(MYSQL_TYPE_DECIMAL
);
72 DEFINE_CONSTANT(MYSQL_TYPE_NEWDECIMAL
);
73 DEFINE_CONSTANT(MYSQL_TYPE_FLOAT
);
74 DEFINE_CONSTANT(MYSQL_TYPE_DOUBLE
);
75 DEFINE_CONSTANT(MYSQL_TYPE_BIT
);
76 DEFINE_CONSTANT(MYSQL_TYPE_TIMESTAMP
);
77 DEFINE_CONSTANT(MYSQL_TYPE_DATE
);
78 DEFINE_CONSTANT(MYSQL_TYPE_TIME
);
79 DEFINE_CONSTANT(MYSQL_TYPE_DATETIME
);
80 DEFINE_CONSTANT(MYSQL_TYPE_YEAR
);
81 DEFINE_CONSTANT(MYSQL_TYPE_STRING
);
82 DEFINE_CONSTANT(MYSQL_TYPE_VAR_STRING
);
83 DEFINE_CONSTANT(MYSQL_TYPE_BLOB
);
84 DEFINE_CONSTANT(MYSQL_TYPE_SET
);
85 DEFINE_CONSTANT(MYSQL_TYPE_ENUM
);
86 DEFINE_CONSTANT(MYSQL_TYPE_GEOMETRY
);
87 DEFINE_CONSTANT(MYSQL_TYPE_NULL
);
89 static am::AsyncMysqlClient
* getDefaultClient() {
90 return am::AsyncMysqlClient::defaultClient();
93 void HHVM_STATIC_METHOD(AsyncMysqlClient
, setPoolsConnectionLimit
,
95 getDefaultClient()->setPoolsConnectionLimit(limit
);
98 Object
HHVM_STATIC_METHOD(AsyncMysqlClient
, connect
,
101 const String
& dbname
,
103 const String
& password
,
104 int64_t timeout_micros
/* = -1 */) {
105 auto op
= getDefaultClient()->beginConnection(static_cast<std::string
>(host
),
107 static_cast<std::string
>(dbname
),
108 static_cast<std::string
>(user
),
109 static_cast<std::string
>(password
));
110 if (timeout_micros
< 0) {
111 timeout_micros
= mysqlExtension::ConnectTimeout
* 1000;
113 if (timeout_micros
> 0) {
114 op
->setTimeout(am::Duration(timeout_micros
));
117 auto event
= new AsyncMysqlConnectEvent(op
);
119 op
->setCallback([event
](am::ConnectOperation
& op
) { event
->opFinished(); });
122 return event
->getWaitHandle();
131 Object
HHVM_STATIC_METHOD(AsyncMysqlClient
, adoptConnection
,
132 const Variant
& connection
) {
133 auto conn
= connection
.toResource().getTyped
<MySQLResource
>()->mysql();
134 // mysql connection from ext/mysql/mysql_common.h
135 auto raw_conn
= conn
->eject_mysql();
136 auto adopted
= getDefaultClient()->adoptConnection(raw_conn
,
143 ObjectData
* ret
= AsyncMysqlConnection::newInstance(std::move(adopted
));
147 ///////////////////////////////////////////////////////////////////////////////
148 // class AsyncMysqlConnectionPool
150 const StaticString
AsyncMysqlConnectionPool::s_className(
151 "AsyncMysqlConnectionPool");
153 // `connection_limit` - Defines the limit of opened connections for each set of
154 // User, Database, Host, etc
155 // `total_connection_limit` - Defines the total limit of opened connection as a
157 // `idle_timeout_micros` - Sets the maximum idle time in microseconds a
158 // connection can be left in the pool without being killed by the pool
159 // `age_timeout_micros` - Sets the maximum age (means the time since started) of
160 // a connection, the pool will then kill this connection when reaches that limit
161 // `expiration_policy` - We offer 2 policies for the expiration of a
162 // connection: `IdleTime` and `Age`, in the Idle policy a connection will only
163 // die after some time being idle; in Age policy we extend the idle one to kill
166 const StaticString
s_per_key_connection_limit("per_key_connection_limit"),
167 s_pool_connection_limit("pool_connection_limit"),
168 s_idle_timeout_micros("idle_timeout_micros"),
169 s_age_timeout_micros("age_timeout_micros"),
170 s_expiration_policy("expiration_policy");
172 void HHVM_METHOD(AsyncMysqlConnectionPool
, __construct
,
173 const Array
& options
) {
175 auto* data
= Native::data
<AsyncMysqlConnectionPool
>(this_
);
176 am::PoolOptions pool_options
;
177 if (options
.exists(s_per_key_connection_limit
)) {
178 pool_options
.setPerKeyLimit(options
[s_per_key_connection_limit
].toInt32());
180 if (options
.exists(s_pool_connection_limit
)) {
181 pool_options
.setPoolLimit(options
[s_pool_connection_limit
].toInt32());
183 if (options
.exists(s_idle_timeout_micros
)) {
184 pool_options
.setIdleTimeout(
185 am::Duration(options
[s_idle_timeout_micros
].toInt64()));
187 if (options
.exists(s_age_timeout_micros
)) {
188 pool_options
.setAgeTimeout(
189 am::Duration(options
[s_age_timeout_micros
].toInt64()));
191 if (options
.exists(s_expiration_policy
)) {
192 pool_options
.setExpPolicy(options
[s_expiration_policy
].toString() ==
193 String::FromCStr("IdleTime")
194 ? am::ExpirationPolicy::IdleTime
195 : am::ExpirationPolicy::Age
);
197 data
->m_async_pool
= am::AsyncConnectionPool::makePool(
198 getDefaultClient(), pool_options
);
201 // `created_pool_connections` - Number of connections created by the pool
202 // `destroyed_pool_connections` - Number of connections destroyed by the pool,
203 // be careful with this number, it will only be equal to the above when all
204 // created connections have been close. This may not be true by the end of
206 // `connections_requested` - This number helps with comparing how many
207 // connection would have been made if the there were no pooling.
208 // `pool_hits` - Counts the number of times a request for connection went to
209 // the pool and it had a connection ready in cache
210 // `pool_misses` - Counts the number of times a we needed a connection and
211 // none was ready to return
212 const StaticString
s_created_pool_connections("created_pool_connections"),
213 s_destroyed_pool_connections("destroyed_pool_connections"),
214 s_connections_requested("connections_requested"), s_pool_hits("pool_hits"),
215 s_pool_misses("pool_misses");
217 Array
HHVM_METHOD(AsyncMysqlConnectionPool
, getPoolStats
) {
218 auto* data
= Native::data
<AsyncMysqlConnectionPool
>(this_
);
219 auto* pool_stats
= data
->m_async_pool
->stats();
220 Array ret
= make_map_array(s_created_pool_connections
,
221 pool_stats
->numCreatedPoolConnections(),
222 s_destroyed_pool_connections
,
223 pool_stats
->numDestroyedPoolConnections(),
224 s_connections_requested
,
225 pool_stats
->numConnectionsRequested(),
227 pool_stats
->numPoolHits(),
229 pool_stats
->numPoolMisses());
233 Object
HHVM_METHOD(AsyncMysqlConnectionPool
, connect
,
236 const String
& dbname
,
238 const String
& password
,
239 int64_t timeout_micros
,
240 const String
& extra_key
) {
242 auto* data
= Native::data
<AsyncMysqlConnectionPool
>(this_
);
243 auto op
= data
->m_async_pool
->beginConnection(static_cast<std::string
>(host
),
245 static_cast<std::string
>(dbname
),
246 static_cast<std::string
>(user
),
247 static_cast<std::string
>(password
),
248 static_cast<std::string
>(extra_key
));
249 if (timeout_micros
< 0) {
250 timeout_micros
= mysqlExtension::ConnectTimeout
* 1000;
252 if (timeout_micros
> 0) {
253 op
->setTimeout(am::Duration(timeout_micros
));
256 auto event
= new AsyncMysqlConnectEvent(op
);
258 op
->setCallback([event
](am::ConnectOperation
& op
) { event
->opFinished(); });
261 return event
->getWaitHandle();
264 LOG(ERROR
) << "Unexpected exception while beginning ConnectPoolOperation";
271 ///////////////////////////////////////////////////////////////////////////////
272 // class AsyncMysqlConnection
274 Class
* AsyncMysqlConnection::s_class
= nullptr;
275 const StaticString
AsyncMysqlConnection::s_className("AsyncMysqlConnection");
277 IMPLEMENT_GET_CLASS(AsyncMysqlConnection
)
279 ObjectData
* AsyncMysqlConnection::newInstance(
280 std::unique_ptr
<am::Connection
> conn
) {
281 ObjectData
* ret
= ObjectData::newInstance(getClass());
282 Native::data
<AsyncMysqlConnection
>(ret
)->setConnection(std::move(conn
));
286 AsyncMysqlConnection::AsyncMysqlConnection() : m_port(0), m_closed(false) {}
288 void AsyncMysqlConnection::sweep() {
292 void AsyncMysqlConnection::setConnection(std::unique_ptr
<am::Connection
> conn
) {
293 m_conn
= std::move(conn
);
294 m_host
= String(m_conn
->host(), CopyString
);
295 m_port
= m_conn
->port();
298 void AsyncMysqlConnection::verifyValidConnection() {
299 if (UNLIKELY(!m_conn
|| !m_conn
->ok())) {
301 throw Object(SystemLib::AllocInvalidArgumentExceptionObject(
302 "attempt to invoke method on a closed connection"));
303 } else if (m_conn
&& !m_conn
->ok()) {
304 throw Object(SystemLib::AllocInvalidArgumentExceptionObject(
305 "attempt to invoke method on an invalid connection"));
307 throw Object(SystemLib::AllocInvalidArgumentExceptionObject(
308 "attempt to invoke method on a busy connection"));
313 Object
AsyncMysqlConnection::query(
316 int64_t timeout_micros
/* = -1 */) {
318 verifyValidConnection();
319 auto op
= am::Connection::beginQuery(std::move(m_conn
), query
);
320 if (timeout_micros
< 0) {
321 timeout_micros
= mysqlExtension::ReadTimeout
* 1000;
323 if (timeout_micros
> 0) {
324 op
->setTimeout(am::Duration(timeout_micros
));
327 auto event
= new AsyncMysqlQueryEvent(this_
, op
);
329 am::QueryAppenderCallback appender_callback
= [event
](
330 am::QueryOperation
& op
,
331 am::QueryResult query_result
,
332 am::QueryCallbackReason reason
) {
333 DCHECK(reason
!= am::QueryCallbackReason::RowsFetched
);
335 LOG(ERROR
) << "Invalid state! Callback called as finished "
336 << "but operation didn't finish";
338 op
.setQueryResult(std::move(query_result
));
341 op
->setCallback(am::resultAppender(appender_callback
));
344 return event
->getWaitHandle();
347 LOG(ERROR
) << "Unexpected exception while beginning ConnectOperation";
354 Object
HHVM_METHOD(AsyncMysqlConnection
, query
,
356 int64_t timeout_micros
/* = -1 */) {
357 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
361 am::Query::unsafe(static_cast<std::string
>(query
)),
365 Object
HHVM_METHOD(AsyncMysqlConnection
, queryf
,
366 const String
& pattern
,
368 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
370 // Not directly calling argsv.toFollyDynamic() as that creates a folly
371 // dynamic object, not list
372 std::vector
<am::QueryArgument
> query_args
;
373 for (ArrayIter
iter(args
); iter
; ++iter
) {
374 const Variant
& arg
= iter
.second();
375 // not using switch (arg.getType()) because null and strings are special
376 if (arg
.isInteger()) {
377 query_args
.push_back(arg
.toInt64());
378 } else if (arg
.isDouble()) {
379 query_args
.push_back(arg
.toDouble());
380 } else if (arg
.isString()) {
381 query_args
.push_back(static_cast<std::string
>(arg
.toString()));
382 } else if (arg
.isNull()) {
383 query_args
.push_back(am::QueryArgument());
385 throw_invalid_argument(
386 "queryf parameters must be scalars - parameter %ld is a %s",
388 getDataTypeString(arg
.getType()).c_str()
395 am::Query(static_cast<std::string
>(pattern
), query_args
));
398 Object
HHVM_METHOD(AsyncMysqlConnection
, multiQuery
,
399 const Array
& queries
,
400 int64_t timeout_micros
/* = -1 */) {
401 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
403 data
->verifyValidConnection();
404 std::vector
<am::Query
> queries_vec
;
405 queries_vec
.reserve(queries
.size());
406 for (ArrayIter
iter(queries
); iter
; ++iter
) {
407 queries_vec
.emplace_back(am::Query::unsafe(
408 static_cast<std::string
>(iter
.second().toString().data())));
410 auto op
= am::Connection::beginMultiQuery(std::move(data
->m_conn
),
411 std::move(queries_vec
));
412 if (timeout_micros
< 0) {
413 timeout_micros
= mysqlExtension::ReadTimeout
* 1000;
415 if (timeout_micros
> 0) {
416 op
->setTimeout(am::Duration(timeout_micros
));
419 auto event
= new AsyncMysqlMultiQueryEvent(this_
, op
);
421 am::MultiQueryAppenderCallback appender_callback
= [event
](
422 am::MultiQueryOperation
& op
,
423 std::vector
<am::QueryResult
> query_results
,
424 am::QueryCallbackReason reason
) {
425 DCHECK(reason
!= am::QueryCallbackReason::RowsFetched
);
426 DCHECK(reason
!= am::QueryCallbackReason::QueryBoundary
);
428 LOG(ERROR
) << "Invalid state! Callback called as finished "
429 << "but operation didn't finish";
431 op
.setQueryResults(std::move(query_results
));
434 op
->setCallback(am::resultAppender(appender_callback
));
437 return event
->getWaitHandle();
446 String
HHVM_METHOD(AsyncMysqlConnection
, escapeString
, const String
& input
) {
447 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
449 String ret
= data
->m_conn
->escapeString(input
.data());
453 String
HHVM_METHOD(AsyncMysqlConnection
, serverInfo
) {
454 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
457 if (data
->m_conn
&& !data
->m_closed
) {
458 ret
= data
->m_conn
->serverInfo();
463 int HHVM_METHOD(AsyncMysqlConnection
, warningCount
) {
464 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
467 if (data
->m_conn
&& !data
->m_closed
) {
468 count
= data
->m_conn
->warningCount();
473 String
HHVM_METHOD(AsyncMysqlConnection
, host
) {
474 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
478 int HHVM_METHOD(AsyncMysqlConnection
, port
) {
479 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
483 void HHVM_METHOD(AsyncMysqlConnection
, setReusable
,
485 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
488 data
->m_conn
->setReusable(reusable
);
490 LOG(ERROR
) << "Accessing closed connection";
494 bool HHVM_METHOD(AsyncMysqlConnection
, isReusable
) {
495 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
498 return data
->m_conn
->isReusable();
500 LOG(ERROR
) << "Accessing closed connection";
505 void HHVM_METHOD(AsyncMysqlConnection
, close
) {
506 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
508 data
->m_conn
.reset();
509 data
->m_closed
= true;
512 Variant
HHVM_METHOD(AsyncMysqlConnection
, releaseConnection
) {
513 auto* data
= Native::data
<AsyncMysqlConnection
>(this_
);
514 data
->verifyValidConnection();
516 auto raw_connection
= data
->m_conn
->stealMysql();
517 auto host
= data
->m_conn
->host();
518 auto port
= data
->m_conn
->port();
519 auto username
= data
->m_conn
->user();
520 auto database
= data
->m_conn
->database();
521 data
->m_conn
.reset();
522 data
->m_closed
= true;
523 return new MySQL(host
.c_str(),
531 ///////////////////////////////////////////////////////////////////////////////
532 // class AsyncMysqlResult
534 int64_t AsyncMysqlResult::elapsedMicros() {
535 return op()->elapsed().count();
538 double AsyncMysqlResult::startTime() {
539 am::Duration d
= std::chrono::duration_cast
<std::chrono::microseconds
>(
540 op()->startTime() - std::chrono::system_clock::from_time_t(0));
541 return d
.count() / 1000.0 / 1000.0;
544 double AsyncMysqlResult::endTime() {
545 am::Duration d
= std::chrono::duration_cast
<std::chrono::microseconds
>(
546 op()->endTime() - std::chrono::system_clock::from_time_t(0));
547 return d
.count() / 1000.0 / 1000.0;
550 #define DEFINE_PROXY_METHOD(cls, method, type) \
551 type HHVM_METHOD(cls, method) { return Native::data<cls>(this_)->method(); } \
553 #define EXTENDS_ASYNC_MYSQL_RESULT(cls) \
554 DEFINE_PROXY_METHOD(cls, elapsedMicros, int64_t) \
555 DEFINE_PROXY_METHOD(cls, startTime, double) \
556 DEFINE_PROXY_METHOD(cls, endTime, double) \
558 ///////////////////////////////////////////////////////////////////////////////
559 // class AsyncMysqlErrorResult
561 Class
* AsyncMysqlErrorResult::s_class
= nullptr;
562 const StaticString
AsyncMysqlErrorResult::s_className("AsyncMysqlErrorResult");
564 IMPLEMENT_GET_CLASS(AsyncMysqlErrorResult
)
566 ObjectData
* AsyncMysqlErrorResult::newInstance(
567 std::shared_ptr
<am::Operation
> op
) {
568 ObjectData
* ret
= ObjectData::newInstance(getClass());
569 Native::data
<AsyncMysqlErrorResult
>(ret
)->create(op
);
573 void AsyncMysqlErrorResult::create(std::shared_ptr
<am::Operation
> op
) {
577 void AsyncMysqlErrorResult::sweep() {
581 am::Operation
* AsyncMysqlErrorResult::op() {
582 if (m_op
.get() == nullptr) {
583 // m_op is null if this object is directly created. It is possible if
584 // a derived class is defined that does not call this class' constructor.
585 Object
e(SystemLib::AllocInvalidOperationExceptionObject(
586 "AsyncMysqlErrorResult object is not properly initialized."));
592 EXTENDS_ASYNC_MYSQL_RESULT(AsyncMysqlErrorResult
)
594 int HHVM_METHOD(AsyncMysqlErrorResult
, mysql_errno
) {
595 auto* data
= Native::data
<AsyncMysqlErrorResult
>(this_
);
596 return data
->m_op
->mysql_errno();
599 String
HHVM_METHOD(AsyncMysqlErrorResult
, mysql_error
) {
600 auto* data
= Native::data
<AsyncMysqlErrorResult
>(this_
);
601 return data
->m_op
->mysql_error();
604 String
HHVM_METHOD(AsyncMysqlErrorResult
, failureType
) {
605 auto* data
= Native::data
<AsyncMysqlErrorResult
>(this_
);
606 return data
->m_op
->resultString().toString();
609 ///////////////////////////////////////////////////////////////////////////////
610 // class AsyncMysqlQueryErrorResult
612 Class
* AsyncMysqlQueryErrorResult::s_class
= nullptr;
613 const StaticString
AsyncMysqlQueryErrorResult::s_className(
614 "AsyncMysqlQueryErrorResult");
616 IMPLEMENT_GET_CLASS(AsyncMysqlQueryErrorResult
)
618 ObjectData
* AsyncMysqlQueryErrorResult::newInstance(
619 std::shared_ptr
<am::Operation
> op
, SmartPtr
<c_Vector
> results
) {
620 ObjectData
* ret
= ObjectData::newInstance(getClass());
621 Native::data
<AsyncMysqlQueryErrorResult
>(ret
)->create(op
, results
);
625 AsyncMysqlQueryErrorResult::AsyncMysqlQueryErrorResult() {
626 static_assert(offsetof(AsyncMysqlQueryErrorResult
, m_parent
) +
627 sizeof(AsyncMysqlErrorResult
) == sizeof(AsyncMysqlQueryErrorResult
),
628 "m_parent must be the last member of AsyncMysqlQueryErrorResult");
631 void AsyncMysqlQueryErrorResult::sweep() {
635 void AsyncMysqlQueryErrorResult::create(std::shared_ptr
<am::Operation
> op
,
636 SmartPtr
<c_Vector
> results
) {
638 m_query_results
= results
;
641 int HHVM_METHOD(AsyncMysqlQueryErrorResult
, numSuccessfulQueries
) {
642 auto* data
= Native::data
<AsyncMysqlQueryErrorResult
>(this_
);
643 return std::dynamic_pointer_cast
<am::FetchOperation
>(data
->m_parent
.m_op
)
644 ->numQueriesExecuted();
647 Object
HHVM_METHOD(AsyncMysqlQueryErrorResult
, getSuccessfulResults
) {
648 auto* data
= Native::data
<AsyncMysqlQueryErrorResult
>(this_
);
649 return Object(data
->m_query_results
);
652 ///////////////////////////////////////////////////////////////////////////////
653 // class AsyncMysqlQueryResult
655 Class
* AsyncMysqlQueryResult::s_class
= nullptr;
656 const StaticString
AsyncMysqlQueryResult::s_className("AsyncMysqlQueryResult");
658 IMPLEMENT_GET_CLASS(AsyncMysqlQueryResult
)
660 void AsyncMysqlQueryResult::sweep() {
662 m_query_result
.reset();
665 ObjectData
* AsyncMysqlQueryResult::newInstance(
666 std::shared_ptr
<am::Operation
> op
, am::QueryResult query_result
) {
667 ObjectData
* ret
= ObjectData::newInstance(getClass());
668 Native::data
<AsyncMysqlQueryResult
>(ret
)->create(op
, std::move(query_result
));
672 void AsyncMysqlQueryResult::create(std::shared_ptr
<am::Operation
> op
,
673 am::QueryResult query_result
) {
676 folly::make_unique
<am::QueryResult
>(std::move(query_result
));
678 std::make_shared
<FieldIndex
>(m_query_result
->getRowFields());
681 am::Operation
* AsyncMysqlQueryResult::op() {
685 EXTENDS_ASYNC_MYSQL_RESULT(AsyncMysqlQueryResult
)
687 int64_t HHVM_METHOD(AsyncMysqlQueryResult
, lastInsertId
) {
688 auto* data
= Native::data
<AsyncMysqlQueryResult
>(this_
);
689 return data
->m_query_result
->lastInsertId();
692 int64_t HHVM_METHOD(AsyncMysqlQueryResult
, numRowsAffected
) {
693 auto* data
= Native::data
<AsyncMysqlQueryResult
>(this_
);
694 return data
->m_query_result
->numRowsAffected();
697 int64_t HHVM_METHOD(AsyncMysqlQueryResult
, numRows
) {
698 auto* data
= Native::data
<AsyncMysqlQueryResult
>(this_
);
699 return data
->m_query_result
->numRows();
701 Object
HHVM_METHOD(AsyncMysqlQueryResult
, vectorRows
) {
702 auto* data
= Native::data
<AsyncMysqlQueryResult
>(this_
);
703 return data
->buildRows(false /* as_maps */, false /* typed */);
706 Object
HHVM_METHOD(AsyncMysqlQueryResult
, mapRows
) {
707 auto* data
= Native::data
<AsyncMysqlQueryResult
>(this_
);
708 return data
->buildRows(true /* as_maps */, false /* typed */);
711 Object
HHVM_METHOD(AsyncMysqlQueryResult
, vectorRowsTyped
) {
712 auto* data
= Native::data
<AsyncMysqlQueryResult
>(this_
);
713 return data
->buildRows(false /* as_maps */, true /* typed */);
716 Object
HHVM_METHOD(AsyncMysqlQueryResult
, mapRowsTyped
) {
717 auto* data
= Native::data
<AsyncMysqlQueryResult
>(this_
);
718 return data
->buildRows(true /* as_maps */, true /* typed */);
721 Object
HHVM_METHOD(AsyncMysqlQueryResult
, rowBlocks
) {
722 auto* data
= Native::data
<AsyncMysqlQueryResult
>(this_
);
723 auto ret
= makeSmartPtr
<c_Vector
>();
724 auto row_blocks
= data
->m_query_result
->stealRows();
725 ret
->reserve(row_blocks
.size());
727 for (auto& row_block
: row_blocks
) {
728 ObjectData
* row
= AsyncMysqlRowBlock::newInstance(&row_block
,
729 data
->m_field_index
);
730 ret
->t_add(Object(row
));
732 return Object(std::move(ret
));
736 Variant
buildTypedValue(const am::RowFields
* row_fields
,
740 if (row
.isNull(field_num
)) {
744 // The underlying library may return zero length null ptr's to
745 // indicate an empty string (since the isNull check above would tell
746 // if it were actually NULL).
747 String string_value
=
748 (row
[field_num
].data() == nullptr && row
[field_num
].size() == 0)
750 : String(row
[field_num
].data(), row
[field_num
].size(), CopyString
);
756 return mysql_makevalue(string_value
, row_fields
->getFieldType(field_num
));
760 Object
AsyncMysqlQueryResult::buildRows(bool as_maps
, bool typed_values
) {
761 auto ret
= makeSmartPtr
<c_Vector
>();
762 ret
->reserve(m_query_result
->numRows());
763 for (const auto& row
: *m_query_result
) {
765 auto row_map
= makeSmartPtr
<c_Map
>();
766 for (int i
= 0; i
< row
.size(); ++i
) {
768 m_field_index
->getFieldString(i
),
770 m_query_result
->getRowFields(), row
, i
, typed_values
));
772 ret
->t_add(Variant(std::move(row_map
)));
774 auto row_vector
= makeSmartPtr
<c_Vector
>();
775 row_vector
->reserve(row
.size());
776 for (int i
= 0; i
< row
.size(); ++i
) {
777 row_vector
->t_add(buildTypedValue(
778 m_query_result
->getRowFields(), row
, i
, typed_values
));
780 ret
->t_add(Variant(std::move(row_vector
)));
783 return Object(std::move(ret
));
786 FieldIndex::FieldIndex(const am::RowFields
* row_fields
) {
787 if (row_fields
== nullptr)
789 field_names_
.reserve(row_fields
->numFields());
790 for (int i
= 0; i
< row_fields
->numFields(); ++i
) {
791 auto name
= String(row_fields
->fieldName(i
).str());
792 field_names_
.push_back(name
);
793 field_name_map_
[name
] = i
;
797 size_t FieldIndex::getFieldIndex(String field_name
) const {
798 auto it
= field_name_map_
.find(field_name
);
799 if (it
== field_name_map_
.end()) {
800 Object
e(SystemLib::AllocInvalidArgumentExceptionObject(
801 "Given field name doesn't exist"));
807 String
FieldIndex::getFieldString(size_t field_index
) const {
808 // Leaving out of bounds to be thrown by the vector in case needed
809 return field_names_
.at(field_index
);
813 void throwAsyncMysqlException(const char* exception_type
,
814 std::shared_ptr
<am::Operation
> op
) {
815 ObjectData
* error
= AsyncMysqlErrorResult::newInstance(op
);
817 assert(op
->result() == am::OperationResult::Failed
||
818 op
->result() == am::OperationResult::TimedOut
||
819 op
->result() == am::OperationResult::Cancelled
);
822 params
.append(error
);
823 throw create_object(exception_type
, params
, true /* init */);
826 void throwAsyncMysqlQueryException(const char* exception_type
,
827 std::shared_ptr
<am::Operation
> op
,
828 SmartPtr
<c_Vector
> res
) {
829 ObjectData
* error
= AsyncMysqlQueryErrorResult::newInstance(op
, res
);
831 assert(op
->result() == am::OperationResult::Failed
||
832 op
->result() == am::OperationResult::TimedOut
||
833 op
->result() == am::OperationResult::Cancelled
);
836 params
.append(error
);
837 throw create_object(exception_type
, params
, true /* init */);
841 void AsyncMysqlConnectEvent::unserialize(Cell
& result
) {
843 ObjectData
* ret
= AsyncMysqlConnection::newInstance(
844 m_op
->releaseConnection());
845 cellDup(make_tv
<KindOfObject
>(ret
), result
);
847 throwAsyncMysqlException("AsyncMysqlConnectException", m_op
);
851 void AsyncMysqlQueryEvent::unserialize(Cell
& result
) {
852 // Retrieve the original conn and return the underlying connection
854 assert(getPrivData()->instanceof(AsyncMysqlConnection::getClass()));
855 auto* conn
= Native::data
<AsyncMysqlConnection
>(getPrivData());
856 conn
->setConnection(m_query_op
->releaseConnection());
858 if (m_query_op
->ok()) {
859 auto query_result
= m_query_op
->stealQueryResult();
860 ObjectData
* ret
= AsyncMysqlQueryResult::newInstance(m_query_op
,
861 std::move(query_result
));
862 cellDup(make_tv
<KindOfObject
>(ret
), result
);
864 throwAsyncMysqlQueryException(
865 "AsyncMysqlQueryException",
867 makeSmartPtr
<c_Vector
>());
871 void AsyncMysqlMultiQueryEvent::unserialize(Cell
& result
) {
872 // Same as unserialize from AsyncMysqlQueryEvent but the result is a
873 // vector of query results
874 assert(getPrivData()->instanceof(AsyncMysqlConnection::getClass()));
875 auto* conn
= Native::data
<AsyncMysqlConnection
>(getPrivData());
876 conn
->setConnection(m_multi_op
->releaseConnection());
878 // Retrieving the results for all executed queries
879 auto results
= makeSmartPtr
<c_Vector
>();
880 std::vector
<am::QueryResult
> query_results
= m_multi_op
->stealQueryResults();
881 results
->reserve(query_results
.size());
882 for (int i
= 0; i
< query_results
.size(); ++i
) {
883 ObjectData
* ret
= AsyncMysqlQueryResult::newInstance(m_multi_op
,
884 std::move(query_results
[i
]));
887 query_results
.clear();
889 if (m_multi_op
->ok()) {
890 cellDup(make_tv
<KindOfObject
>(results
.get()), result
);
892 throwAsyncMysqlQueryException(
893 "AsyncMysqlQueryException", m_multi_op
, results
);
897 ///////////////////////////////////////////////////////////////////////////////
898 // class AsyncMysqlRowBlock
900 Class
* AsyncMysqlRowBlock::s_class
= nullptr;
901 const StaticString
AsyncMysqlRowBlock::s_className("AsyncMysqlRowBlock");
903 IMPLEMENT_GET_CLASS(AsyncMysqlRowBlock
)
905 ObjectData
* AsyncMysqlRowBlock::newInstance(am::RowBlock
* row_block
,
906 std::shared_ptr
<FieldIndex
> indexer
) {
907 ObjectData
* ret
= ObjectData::newInstance(AsyncMysqlRowBlock::getClass());
908 auto* data
= Native::data
<AsyncMysqlRowBlock
>(ret
);
909 data
->m_row_block
.reset(new am::RowBlock(std::move(*row_block
)));
910 data
->m_field_index
= indexer
;
914 void AsyncMysqlRowBlock::sweep() {
918 size_t AsyncMysqlRowBlock::getIndexFromVariant(const Variant
& field
) {
919 if (field
.isInteger()) {
920 return field
.toInt64();
921 } else if (field
.isString()) {
922 return m_field_index
->getFieldIndex(field
.toString());
924 Object
e(SystemLib::AllocInvalidArgumentExceptionObject(
925 "Only integer or string field names may be used with RowBlock"));
929 // The String conversion allows `NULL` to ""
931 folly::StringPiece
AsyncMysqlRowBlock::getFieldAs(int64_t row
,
932 const Variant
& field
) {
933 auto index
= getIndexFromVariant(field
);
935 // Note that for String before you return to PHP you need to copy it into
937 return m_row_block
->getField
<folly::StringPiece
>(row
, index
);
939 catch (std::range_error
& excep
) {
940 Object
e(SystemLib::AllocBadMethodCallExceptionObject(
941 std::string("Error during conversion: ") + excep
.what()));
946 template <typename FieldType
>
947 FieldType
AsyncMysqlRowBlock::getFieldAs(int64_t row
, const Variant
& field
) {
948 auto index
= getIndexFromVariant(field
);
950 if (m_row_block
->isNull(row
, index
)) {
951 Object
e(SystemLib::AllocBadMethodCallExceptionObject(
952 "Field value needs to be non-null."));
956 return m_row_block
->getField
<FieldType
>(row
, index
);
958 catch (std::range_error
& excep
) {
959 Object
e(SystemLib::AllocBadMethodCallExceptionObject(
960 std::string("Error during conversion: ") + excep
.what()));
965 Variant
HHVM_METHOD(AsyncMysqlRowBlock
, at
, int64_t row
, const Variant
& field
) {
966 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
967 auto col_index
= data
->getIndexFromVariant(field
);
968 return buildTypedValue(data
->m_row_block
->getRowFields(),
969 data
->m_row_block
->getRow(row
),
974 int64_t HHVM_METHOD(AsyncMysqlRowBlock
,
977 const Variant
& field
) {
978 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
979 return data
->getFieldAs
<int64_t>(row
, field
);
982 double HHVM_METHOD(AsyncMysqlRowBlock
,
985 const Variant
& field
) {
986 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
987 return data
->getFieldAs
<double>(row
, field
);
990 String
HHVM_METHOD(AsyncMysqlRowBlock
,
993 const Variant
& field
) {
994 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
995 auto val
= data
->getFieldAs
<StringPiece
>(row
, field
);
996 return StringData::Make(val
.data(), val
.size(), CopyString
);
999 bool HHVM_METHOD(AsyncMysqlRowBlock
, isNull
,
1001 const Variant
& field
) {
1002 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
1003 return data
->m_row_block
->isNull(row
, data
->getIndexFromVariant(field
));
1006 int64_t HHVM_METHOD(AsyncMysqlRowBlock
, fieldType
,
1007 const Variant
& field
) {
1008 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
1009 return data
->m_row_block
->getFieldType(data
->getIndexFromVariant(field
));
1012 int64_t HHVM_METHOD(AsyncMysqlRowBlock
, fieldFlags
,
1013 const Variant
& field
) {
1014 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
1015 return data
->m_row_block
->getFieldFlags(data
->getIndexFromVariant(field
));
1018 String
HHVM_METHOD(AsyncMysqlRowBlock
, fieldName
,
1020 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
1021 return data
->m_field_index
->getFieldString(field_id
);
1024 bool HHVM_METHOD(AsyncMysqlRowBlock
, isEmpty
) {
1025 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
1026 return data
->m_row_block
->empty();
1029 int64_t HHVM_METHOD(AsyncMysqlRowBlock
, fieldsCount
) {
1030 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
1031 return data
->m_row_block
->numFields();
1034 int64_t HHVM_METHOD(AsyncMysqlRowBlock
, count
) {
1035 auto* data
= Native::data
<AsyncMysqlRowBlock
>(this_
);
1036 return data
->m_row_block
->numRows();
1039 Object
HHVM_METHOD(AsyncMysqlRowBlock
, getRow
,
1041 ObjectData
* row
= AsyncMysqlRow::newInstance(this_
, row_no
);
1045 Object
HHVM_METHOD(AsyncMysqlRowBlock
, getIterator
) {
1046 ObjectData
* it
= AsyncMysqlRowBlockIterator::newInstance(this_
, 0);
1050 ///////////////////////////////////////////////////////////////////////////////
1051 // class AsyncMysqlRowBlockIterator
1053 Class
* AsyncMysqlRowBlockIterator::s_class
= nullptr;
1054 const StaticString
AsyncMysqlRowBlockIterator::s_className(
1055 "AsyncMysqlRowBlockIterator");
1057 IMPLEMENT_GET_CLASS(AsyncMysqlRowBlockIterator
)
1059 ObjectData
* AsyncMysqlRowBlockIterator::newInstance(Object row_block
,
1060 size_t row_number
) {
1061 ObjectData
* ret
= ObjectData::newInstance(getClass());
1062 auto* data
= Native::data
<AsyncMysqlRowBlockIterator
>(ret
);
1063 data
->m_row_block
= row_block
;
1064 data
->m_row_number
= row_number
;
1068 void HHVM_METHOD(AsyncMysqlRowBlockIterator
, next
) {
1069 auto* data
= Native::data
<AsyncMysqlRowBlockIterator
>(this_
);
1070 data
->m_row_number
++;
1073 bool HHVM_METHOD(AsyncMysqlRowBlockIterator
, valid
) {
1074 auto* data
= Native::data
<AsyncMysqlRowBlockIterator
>(this_
);
1076 static_assert(std::is_unsigned
<typeof(data
->m_row_number
)>::value
,
1077 "m_row_number should be unsigned");
1078 int64_t count
= HHVM_MN(AsyncMysqlRowBlock
, count
)(
1079 data
->m_row_block
.get());
1080 return data
->m_row_number
< count
;
1083 Object
HHVM_METHOD(AsyncMysqlRowBlockIterator
, current
) {
1084 auto* data
= Native::data
<AsyncMysqlRowBlockIterator
>(this_
);
1086 if (!HHVM_MN(AsyncMysqlRowBlockIterator
, valid
)(this_
)) {
1087 throw_iterator_not_valid();
1089 return HHVM_MN(AsyncMysqlRowBlock
, getRow
)(data
->m_row_block
.get(),
1090 data
->m_row_number
);
1093 int64_t HHVM_METHOD(AsyncMysqlRowBlockIterator
, key
) {
1094 auto* data
= Native::data
<AsyncMysqlRowBlockIterator
>(this_
);
1095 return data
->m_row_number
;
1098 void HHVM_METHOD(AsyncMysqlRowBlockIterator
, rewind
) {
1099 auto* data
= Native::data
<AsyncMysqlRowBlockIterator
>(this_
);
1100 data
->m_row_number
= 0;
1103 ///////////////////////////////////////////////////////////////////////////////
1104 // class AsyncMysqlRow
1106 Class
* AsyncMysqlRow::s_class
= nullptr;
1107 const StaticString
AsyncMysqlRow::s_className("AsyncMysqlRow");
1109 IMPLEMENT_GET_CLASS(AsyncMysqlRow
)
1111 ObjectData
* AsyncMysqlRow::newInstance(Object row_block
, size_t row_number
) {
1112 ObjectData
* ret
= ObjectData::newInstance(getClass());
1113 auto* data
= Native::data
<AsyncMysqlRow
>(ret
);
1114 data
->m_row_block
= row_block
;
1115 data
->m_row_number
= row_number
;
1119 #define ROW_BLOCK(method, ...) HHVM_MN(AsyncMysqlRowBlock, method)( \
1120 data->m_row_block.get(), __VA_ARGS__) \
1122 Variant HHVM_METHOD(AsyncMysqlRow, at,
1123 const Variant
& field
) {
1124 auto* data
= Native::data
<AsyncMysqlRow
>(this_
);
1125 return ROW_BLOCK(at
, data
->m_row_number
, field
);
1128 int64_t HHVM_METHOD(AsyncMysqlRow
, getFieldAsInt
,
1129 const Variant
& field
) {
1130 auto* data
= Native::data
<AsyncMysqlRow
>(this_
);
1131 return ROW_BLOCK(getFieldAsInt
, data
->m_row_number
, field
);
1134 double HHVM_METHOD(AsyncMysqlRow
, getFieldAsDouble
,
1135 const Variant
& field
) {
1136 auto* data
= Native::data
<AsyncMysqlRow
>(this_
);
1137 return ROW_BLOCK(getFieldAsDouble
, data
->m_row_number
, field
);
1140 String
HHVM_METHOD(AsyncMysqlRow
, getFieldAsString
,
1141 const Variant
& field
) {
1142 auto* data
= Native::data
<AsyncMysqlRow
>(this_
);
1143 return ROW_BLOCK(getFieldAsString
, data
->m_row_number
, field
);
1146 bool HHVM_METHOD(AsyncMysqlRow
, isNull
,
1147 const Variant
& field
) {
1148 auto* data
= Native::data
<AsyncMysqlRow
>(this_
);
1149 return ROW_BLOCK(isNull
, data
->m_row_number
, field
);
1152 int64_t HHVM_METHOD(AsyncMysqlRow
, fieldType
,
1153 const Variant
& field
) {
1154 auto* data
= Native::data
<AsyncMysqlRow
>(this_
);
1155 return ROW_BLOCK(fieldType
, field
);
1158 int64_t HHVM_METHOD(AsyncMysqlRow
, count
) {
1159 auto* data
= Native::data
<AsyncMysqlRow
>(this_
);
1160 return HHVM_MN(AsyncMysqlRowBlock
, fieldsCount
)(data
->m_row_block
.get());
1163 Object
HHVM_METHOD(AsyncMysqlRow
, getIterator
) {
1164 ObjectData
* it
= AsyncMysqlRowIterator::newInstance(this_
, 0);
1170 ///////////////////////////////////////////////////////////////////////////////
1171 // class AsyncMysqlRowIterator
1173 Class
* AsyncMysqlRowIterator::s_class
= nullptr;
1174 const StaticString
AsyncMysqlRowIterator::s_className("AsyncMysqlRowIterator");
1176 IMPLEMENT_GET_CLASS(AsyncMysqlRowIterator
)
1178 ObjectData
* AsyncMysqlRowIterator::newInstance(Object row
,
1179 size_t field_number
) {
1180 ObjectData
* ret
= ObjectData::newInstance(getClass());
1181 auto* data
= Native::data
<AsyncMysqlRowIterator
>(ret
);
1183 data
->m_field_number
= field_number
;
1187 void HHVM_METHOD(AsyncMysqlRowIterator
, next
) {
1188 auto* data
= Native::data
<AsyncMysqlRowIterator
>(this_
);
1189 data
->m_field_number
++;
1192 bool HHVM_METHOD(AsyncMysqlRowIterator
, valid
) {
1193 auto* data
= Native::data
<AsyncMysqlRowIterator
>(this_
);
1195 static_assert(std::is_unsigned
<typeof(data
->m_field_number
)>::value
,
1196 "m_field_number should be unsigned");
1197 int64_t count
= HHVM_MN(AsyncMysqlRow
, count
)(data
->m_row
.get());
1198 return data
->m_field_number
< count
;
1201 /*?? return as string? */
1202 String
HHVM_METHOD(AsyncMysqlRowIterator
, current
) {
1203 auto* data
= Native::data
<AsyncMysqlRowIterator
>(this_
);
1204 return HHVM_MN(AsyncMysqlRow
, getFieldAsString
)(data
->m_row
.get(),
1205 data
->m_field_number
);
1208 int64_t HHVM_METHOD(AsyncMysqlRowIterator
, key
) {
1209 auto* data
= Native::data
<AsyncMysqlRowIterator
>(this_
);
1210 return data
->m_field_number
;
1213 void HHVM_METHOD(AsyncMysqlRowIterator
, rewind
) {
1214 auto* data
= Native::data
<AsyncMysqlRowIterator
>(this_
);
1215 data
->m_field_number
= 0;
1218 ///////////////////////////////////////////////////////////////////////////////
1220 #define REGISTER_CONSTANT(name) \
1221 Native::registerConstant<KindOfInt64>(s_##name.get(), k_##name) \
1223 static const int64_t DISABLE_COPY_AND_SWEEP = Native::NDIFlags::NO_COPY |
1224 Native::NDIFlags::NO_SWEEP
;
1226 static class AsyncMysqlExtension final
: public Extension
{
1228 AsyncMysqlExtension() : Extension("async_mysql") {}
1229 void moduleInit() override
{
1230 REGISTER_CONSTANT(NOT_NULL_FLAG
);
1231 REGISTER_CONSTANT(PRI_KEY_FLAG
);
1232 REGISTER_CONSTANT(UNIQUE_KEY_FLAG
);
1233 REGISTER_CONSTANT(MULTIPLE_KEY_FLAG
);
1234 REGISTER_CONSTANT(UNSIGNED_FLAG
);
1235 REGISTER_CONSTANT(ZEROFILL_FLAG
);
1236 REGISTER_CONSTANT(BINARY_FLAG
);
1237 REGISTER_CONSTANT(AUTO_INCREMENT_FLAG
);
1238 REGISTER_CONSTANT(ENUM_FLAG
);
1239 REGISTER_CONSTANT(SET_FLAG
);
1240 REGISTER_CONSTANT(BLOB_FLAG
);
1241 REGISTER_CONSTANT(TIMESTAMP_FLAG
);
1242 REGISTER_CONSTANT(NUM_FLAG
);
1243 REGISTER_CONSTANT(NO_DEFAULT_VALUE_FLAG
);
1245 REGISTER_CONSTANT(MYSQL_TYPE_TINY
);
1246 REGISTER_CONSTANT(MYSQL_TYPE_SHORT
);
1247 REGISTER_CONSTANT(MYSQL_TYPE_LONG
);
1248 REGISTER_CONSTANT(MYSQL_TYPE_INT24
);
1249 REGISTER_CONSTANT(MYSQL_TYPE_LONGLONG
);
1250 REGISTER_CONSTANT(MYSQL_TYPE_DECIMAL
);
1251 REGISTER_CONSTANT(MYSQL_TYPE_NEWDECIMAL
);
1252 REGISTER_CONSTANT(MYSQL_TYPE_FLOAT
);
1253 REGISTER_CONSTANT(MYSQL_TYPE_DOUBLE
);
1254 REGISTER_CONSTANT(MYSQL_TYPE_BIT
);
1255 REGISTER_CONSTANT(MYSQL_TYPE_TIMESTAMP
);
1256 REGISTER_CONSTANT(MYSQL_TYPE_DATE
);
1257 REGISTER_CONSTANT(MYSQL_TYPE_TIME
);
1258 REGISTER_CONSTANT(MYSQL_TYPE_DATETIME
);
1259 REGISTER_CONSTANT(MYSQL_TYPE_YEAR
);
1260 REGISTER_CONSTANT(MYSQL_TYPE_STRING
);
1261 REGISTER_CONSTANT(MYSQL_TYPE_VAR_STRING
);
1262 REGISTER_CONSTANT(MYSQL_TYPE_BLOB
);
1263 REGISTER_CONSTANT(MYSQL_TYPE_SET
);
1264 REGISTER_CONSTANT(MYSQL_TYPE_ENUM
);
1265 REGISTER_CONSTANT(MYSQL_TYPE_GEOMETRY
);
1266 REGISTER_CONSTANT(MYSQL_TYPE_NULL
);
1268 HHVM_STATIC_ME(AsyncMysqlClient
, setPoolsConnectionLimit
);
1269 HHVM_STATIC_ME(AsyncMysqlClient
, connect
);
1270 HHVM_STATIC_ME(AsyncMysqlClient
, adoptConnection
);
1272 HHVM_ME(AsyncMysqlConnectionPool
, __construct
);
1273 HHVM_ME(AsyncMysqlConnectionPool
, getPoolStats
);
1274 HHVM_ME(AsyncMysqlConnectionPool
, connect
);
1275 Native::registerNativeDataInfo
<AsyncMysqlConnectionPool
>(
1276 AsyncMysqlConnectionPool::s_className
.get(), DISABLE_COPY_AND_SWEEP
);
1278 HHVM_ME(AsyncMysqlConnection
, query
);
1279 HHVM_ME(AsyncMysqlConnection
, queryf
);
1280 HHVM_ME(AsyncMysqlConnection
, multiQuery
);
1281 HHVM_ME(AsyncMysqlConnection
, escapeString
);
1282 HHVM_ME(AsyncMysqlConnection
, close
);
1283 HHVM_ME(AsyncMysqlConnection
, releaseConnection
);
1284 HHVM_ME(AsyncMysqlConnection
, serverInfo
);
1285 HHVM_ME(AsyncMysqlConnection
, warningCount
);
1286 HHVM_ME(AsyncMysqlConnection
, host
);
1287 HHVM_ME(AsyncMysqlConnection
, port
);
1288 HHVM_ME(AsyncMysqlConnection
, setReusable
);
1289 HHVM_ME(AsyncMysqlConnection
, isReusable
);
1290 Native::registerNativeDataInfo
<AsyncMysqlConnection
>(
1291 AsyncMysqlConnection::s_className
.get(), Native::NDIFlags::NO_COPY
);
1293 HHVM_ME(AsyncMysqlErrorResult
, elapsedMicros
);
1294 HHVM_ME(AsyncMysqlErrorResult
, startTime
);
1295 HHVM_ME(AsyncMysqlErrorResult
, endTime
);
1296 HHVM_ME(AsyncMysqlErrorResult
, mysql_errno
);
1297 HHVM_ME(AsyncMysqlErrorResult
, mysql_error
);
1298 HHVM_ME(AsyncMysqlErrorResult
, failureType
);
1299 Native::registerNativeDataInfo
<AsyncMysqlErrorResult
>(
1300 AsyncMysqlErrorResult::s_className
.get(), Native::NDIFlags::NO_COPY
);
1302 HHVM_ME(AsyncMysqlQueryErrorResult
, numSuccessfulQueries
);
1303 HHVM_ME(AsyncMysqlQueryErrorResult
, getSuccessfulResults
);
1304 Native::registerNativeDataInfo
<AsyncMysqlQueryErrorResult
>(
1305 AsyncMysqlQueryErrorResult::s_className
.get(),
1306 Native::NDIFlags::NO_COPY
);
1308 HHVM_ME(AsyncMysqlQueryResult
, elapsedMicros
);
1309 HHVM_ME(AsyncMysqlQueryResult
, startTime
);
1310 HHVM_ME(AsyncMysqlQueryResult
, endTime
);
1311 HHVM_ME(AsyncMysqlQueryResult
, numRowsAffected
);
1312 HHVM_ME(AsyncMysqlQueryResult
, lastInsertId
);
1313 HHVM_ME(AsyncMysqlQueryResult
, numRows
);
1314 HHVM_ME(AsyncMysqlQueryResult
, mapRows
);
1315 HHVM_ME(AsyncMysqlQueryResult
, vectorRows
);
1316 HHVM_ME(AsyncMysqlQueryResult
, mapRowsTyped
);
1317 HHVM_ME(AsyncMysqlQueryResult
, vectorRowsTyped
);
1318 HHVM_ME(AsyncMysqlQueryResult
, rowBlocks
);
1319 Native::registerNativeDataInfo
<AsyncMysqlQueryResult
>(
1320 AsyncMysqlQueryResult::s_className
.get(), Native::NDIFlags::NO_COPY
);
1322 HHVM_ME(AsyncMysqlRowBlock
, at
);
1323 HHVM_ME(AsyncMysqlRowBlock
, getFieldAsInt
);
1324 HHVM_ME(AsyncMysqlRowBlock
, getFieldAsDouble
);
1325 HHVM_ME(AsyncMysqlRowBlock
, getFieldAsString
);
1326 HHVM_ME(AsyncMysqlRowBlock
, isNull
);
1327 HHVM_ME(AsyncMysqlRowBlock
, fieldType
);
1328 HHVM_ME(AsyncMysqlRowBlock
, fieldFlags
);
1329 HHVM_ME(AsyncMysqlRowBlock
, fieldName
);
1330 HHVM_ME(AsyncMysqlRowBlock
, isEmpty
);
1331 HHVM_ME(AsyncMysqlRowBlock
, fieldsCount
);
1332 HHVM_ME(AsyncMysqlRowBlock
, count
);
1333 HHVM_ME(AsyncMysqlRowBlock
, getIterator
);
1334 HHVM_ME(AsyncMysqlRowBlock
, getRow
);
1335 Native::registerNativeDataInfo
<AsyncMysqlRowBlock
>(
1336 AsyncMysqlRowBlock::s_className
.get(), Native::NDIFlags::NO_COPY
);
1338 HHVM_ME(AsyncMysqlRowBlockIterator
, valid
);
1339 HHVM_ME(AsyncMysqlRowBlockIterator
, next
);
1340 HHVM_ME(AsyncMysqlRowBlockIterator
, current
);
1341 HHVM_ME(AsyncMysqlRowBlockIterator
, key
);
1342 HHVM_ME(AsyncMysqlRowBlockIterator
, rewind
);
1343 Native::registerNativeDataInfo
<AsyncMysqlRowBlockIterator
>(
1344 AsyncMysqlRowBlockIterator::s_className
.get(),
1345 DISABLE_COPY_AND_SWEEP
);
1347 HHVM_ME(AsyncMysqlRow
, at
);
1348 HHVM_ME(AsyncMysqlRow
, getFieldAsInt
);
1349 HHVM_ME(AsyncMysqlRow
, getFieldAsDouble
);
1350 HHVM_ME(AsyncMysqlRow
, getFieldAsString
);
1351 HHVM_ME(AsyncMysqlRow
, isNull
);
1352 HHVM_ME(AsyncMysqlRow
, fieldType
);
1353 HHVM_ME(AsyncMysqlRow
, count
);
1354 HHVM_ME(AsyncMysqlRow
, getIterator
);
1355 Native::registerNativeDataInfo
<AsyncMysqlRow
>(
1356 AsyncMysqlRow::s_className
.get(), DISABLE_COPY_AND_SWEEP
);
1358 HHVM_ME(AsyncMysqlRowIterator
, valid
);
1359 HHVM_ME(AsyncMysqlRowIterator
, next
);
1360 HHVM_ME(AsyncMysqlRowIterator
, current
);
1361 HHVM_ME(AsyncMysqlRowIterator
, key
);
1362 HHVM_ME(AsyncMysqlRowIterator
, rewind
);
1363 Native::registerNativeDataInfo
<AsyncMysqlRowIterator
>(
1364 AsyncMysqlRowIterator::s_className
.get(), DISABLE_COPY_AND_SWEEP
);
1366 loadSystemlib("mysqlrow");
1367 loadSystemlib("async_mysql_exceptions");
1370 } s_async_mysql_extension
;
1372 ///////////////////////////////////////////////////////////////////////////////