/** * \private * * Construct a new AnewtDatabaseResultSet instance (internal use). * * Do not call this method directly; it is for internal use only. * * (Note to backend implementors: you should override this constructor, call * into the parent, and then store the \c n_rows and \c n_rows_affected * values) * * \param $sql The SQL query for this result set * \param $connection_handle The internal connection handle * \param $result_set_handle The internal result set handle * * \see AnewtDatabaseConnection::prepare */ public function __construct($sql, $connection_handle, $result_set_handle) { $this->sql = $sql; $this->connection_handle = $connection_handle; $this->result_set_handle = $result_set_handle; /* Deduce column types for SELECT queries */ if (AnewtDatabaseSQLTemplate::query_type_for_sql($sql) == ANEWT_DATABASE_SQL_QUERY_TYPE_SELECT) { $this->obtain_field_types(); } }
/** * \private * * Construct a new AnewtDatabaseSQLTemplate instance. * * Do not create instances directly; use * AnewtDatabaseConnection::sql_template() instead. * * \param $sql * The SQL template string * * \param $connection * An AnewtDatabaseConnection instance * * \see AnewtDatabaseConnection::prepare * \see AnewtDatabaseConnection::sql_template */ function __construct($sql, $connection) { assert('is_string($sql)'); assert('$connection instanceof AnewtDatabaseConnection'); $this->connection = $connection; $this->placeholders = array(); /* Since vsprintf is used to substitute escaped values into the sql * query later on, % characters need to be escaped. */ $sql = str_replace('%', '%%', $sql); /* Find placeholders fields. All placeholders start with ? followed by * a keyword and end with ? too, e.g. ?int? for a positional * placeholder and ?string:somename? for a named placeholder. In both * cases, the parameter can end with [] to indicate an array of values. */ $placeholder_matches = array(); $placeholder_pattern_positional = '/\\?([a-z]+)(\\[\\])?\\?/i'; $placeholder_pattern_named = '/\\?([a-z]+)(\\[\\])?:([^?]+)\\?/i'; if (preg_match_all($placeholder_pattern_named, $sql, $placeholder_matches)) { $this->named_mode = true; if (preg_match($placeholder_pattern_positional, $sql)) { throw new AnewtDatabaseQueryException('Mixing positional and named placeholders is not supported.'); } } else { preg_match_all($placeholder_pattern_positional, $sql, $placeholder_matches); } if ($placeholder_matches[1]) { /* There is at least one placeholder and we know whether we are * using named mode. Extract the placeholder types and save them in * $this->placeholders, and replace all ?field? parts with %s to * allow easy vsprintf substitution when in the fill() method. */ $multiple = false; if ($this->named_mode) { /* In named mode: * - $placeholder_matches[1] contains the placeholder types * - $placeholder_matches[2] contains the placeholder names * - $this->placeholders will be a numeric array of (name, field type, multiple) tuples */ $sql = preg_replace($placeholder_pattern_named, '%s', $sql); while ($placeholder_matches[1]) { $type = AnewtDatabaseSQLTemplate::field_type_for_string(array_shift($placeholder_matches[1])); $multiple = array_shift($placeholder_matches[2]) === '[]'; $name = array_shift($placeholder_matches[3]); $this->placeholders[] = array($name, $type, $multiple); } } else { /* In positional mode: * - $placeholder_matches[1] contains the placeholder types * - $this->placeholders will be a numeric array of (NULL, field type, multiple) tuples */ $sql = preg_replace($placeholder_pattern_positional, '%s', $sql); while ($placeholder_matches[1]) { $type = AnewtDatabaseSQLTemplate::field_type_for_string(array_shift($placeholder_matches[1])); $multiple = array_shift($placeholder_matches[2]) === '[]'; $this->placeholders[] = array(null, $type, $multiple); } } } $this->sql = $sql; }
/** * Execute a query using the values passed as a single parameter, without * retrieving resulting rows. * * For some query types the number of affected rows is returned. This only * works for queries that operate on a number of rows, i.e. \c INSERT, \c * UPDATE, \c REPLACE, and \c DELETE queries. For other query types \c null * is returned. * * Note that this method is mostly useless for \c SELECT queries since it * will not return any results; use * AnewtDatabaseConnection::prepare_execute_fetch or * AnewtDatabaseConnection::prepare_execute_fetch_all if you want to * retrieve result rows. * * \param $sql The SQL query to be prepared (optionally with placeholders) * \param $values Zero or more values to be substituted for the placeholders * * \return * The number of rows affected by the query. * * \see DB::prepare_execute * \see DB::prepare_executev_fetch_one * \see DB::prepare_executev_fetch_all */ public function prepare_executev($sql, $values = null) { assert('is_string($sql);'); $pq = $this->prepare($sql); $rs = $pq->executev($values); $out = null; switch (AnewtDatabaseSQLTemplate::query_type_for_sql($sql)) { case ANEWT_DATABASE_SQL_QUERY_TYPE_INSERT: case ANEWT_DATABASE_SQL_QUERY_TYPE_UPDATE: case ANEWT_DATABASE_SQL_QUERY_TYPE_REPLACE: case ANEWT_DATABASE_SQL_QUERY_TYPE_DELETE: $out = $rs->count_affected(); break; default: /* Do nothing */ break; } $rs->free(); return $out; }
public function prepare_executev_fetch_all($sql, $values = null) { $key = null; $store_in_cache = false; if (AnewtDatabaseSQLTemplate::query_type_for_sql($sql) == ANEWT_DATABASE_SQL_QUERY_TYPE_SELECT) { $key = $this->build_key($sql, $values, true); $rows = $this->memcache->get($key); if ($rows === false) { $this->n_cache_misses++; $store_in_cache = true; } else { $this->n_cache_hits++; return $rows; } } $rows = $this->connection_handle->prepare_executev_fetch_all($sql, $values); if ($store_in_cache) { $this->memcache->set($key, $rows, $this->settings['compression'] ? MEMCACHE_COMPRESSED : 0, $this->settings['expiry']); } return $rows; }