Define a mechanism for driver-specific attributes.
Use a refcount for the stmt structure.
REGISTER_LONG_CONSTANT("PDO_ATTR_SERVER_INFO", (long)PDO_ATTR_SERVER_INFO, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_CONNECTION_STATUS", (long)PDO_ATTR_CONNECTION_STATUS, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ATTR_CASE", (long)PDO_ATTR_CASE, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("PDO_ATTR_CURSOR_NAME", (long)PDO_ATTR_CURSOR_NAME, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("PDO_ATTR_CURSOR", (long)PDO_ATTR_CURSOR, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ERRMODE_SILENT", (long)PDO_ERRMODE_SILENT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("PDO_ERRMODE_WARNING", (long)PDO_ERRMODE_WARNING, CONST_CS|CONST_PERSISTENT);
dbh->username = username ? pestrdup(username, is_persistent) : NULL;
dbh->password = password ? pestrdup(password, is_persistent) : NULL;
- if (driver_options) {
- dbh->auto_commit = pdo_attr_lval(driver_options, PDO_ATTR_AUTOCOMMIT, 1 TSRMLS_CC);
- } else {
- dbh->auto_commit = 1;
- }
+ dbh->auto_commit = pdo_attr_lval(driver_options, PDO_ATTR_AUTOCOMMIT, 1 TSRMLS_CC);
if (driver->db_handle_factory(dbh, driver_options TSRMLS_CC)) {
/* all set */
/* we haven't created a lazy object yet */
ZVAL_NULL(&stmt->lazy_object_ref);
+
+ stmt->refcount = 1;
return;
}
efree(stmt);
Z_TYPE(stmt->lazy_object_ref) = IS_OBJECT;
Z_OBJ_HANDLE(stmt->lazy_object_ref) = zend_objects_store_put(stmt, NULL, pdo_row_free_storage, NULL TSRMLS_CC);
Z_OBJ_HT(stmt->lazy_object_ref) = &pdo_row_object_handlers;
+ stmt->refcount++;
}
Z_TYPE_P(return_value) = IS_OBJECT;
Z_OBJ_HANDLE_P(return_value) = Z_OBJ_HANDLE(stmt->lazy_object_ref);
NULL
};
-void pdo_dbstmt_free_storage(zend_object *object TSRMLS_DC)
+static void free_statement(pdo_stmt_t *stmt TSRMLS_DC)
{
- pdo_stmt_t *stmt = (pdo_stmt_t*)object;
-
if (stmt->methods && stmt->methods->dtor) {
stmt->methods->dtor(stmt TSRMLS_CC);
}
}
zend_objects_store_del_ref(&stmt->database_object_handle TSRMLS_CC);
-/* XXX: Does not appear to be needed and causes problems according to valgrind
- if (&stmt->lazy_object_ref) {
- zend_objects_store_del_ref(&stmt->lazy_object_ref TSRMLS_CC);
- }
-*/
efree(stmt);
}
+void pdo_dbstmt_free_storage(zend_object *object TSRMLS_DC)
+{
+ pdo_stmt_t *stmt = (pdo_stmt_t*)object;
+
+ if (--stmt->refcount == 0) {
+ free_statement(stmt TSRMLS_CC);
+ }
+}
+
zend_object_value pdo_dbstmt_new(zend_class_entry *ce TSRMLS_DC)
{
zend_object_value retval;
{
pdo_stmt_t *stmt = (pdo_stmt_t*)object;
- /* nothing to do here */
+ ZVAL_NULL(&stmt->lazy_object_ref);
+
+ if (--stmt->refcount == 0) {
+ free_statement(stmt TSRMLS_CC);
+ }
}
zend_object_value pdo_row_new(zend_class_entry *ce TSRMLS_DC)
PDO_ATTR_SERVER_INFO, /* server information */
PDO_ATTR_CONNECTION_STATUS, /* connection status */
PDO_ATTR_CASE, /* control case folding for portability */
+ PDO_ATTR_CURSOR_NAME, /* name a cursor for use in "WHERE CURRENT OF <name>" */
+ PDO_ATTR_CURSOR, /* cursor type */
+
+ /* this defines the start of the range for driver specific options.
+ * Drivers should define their own attribute constants beginning with this
+ * value. */
+ PDO_ATTR_DRIVER_SPECIFIC = 1000
+};
+
+enum pdo_cursor_type {
+ PDO_CURSOR_FWDONLY, /* forward only cursor (default) */
+ PDO_CURSOR_SCROLL, /* scrollable cursor */
};
/* generic error code values.
{
zval **v;
- if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), option_name, (void**)&v)) {
+ if (options && SUCCESS == zend_hash_index_find(Z_ARRVAL_P(options), option_name, (void**)&v)) {
convert_to_long_ex(v);
return Z_LVAL_PP(v);
}
/* for lazy fetches, we always return the same lazy object handle.
* Let's keep it here. */
zval lazy_object_ref;
+ unsigned long refcount;
};
/* call this in MINIT to register your PDO driver */