+/**
+ * Wrapper to address lack of certain operations in the DB2 driver
+ * ( seek, num_rows )
+ * @ingroup Database
+ * @since 1.19
+ */
+class IBM_DB2Result{
+ private $db;
+ private $result;
+ private $num_rows;
+ private $current_pos;
+ private $columns = array();
+ private $sql;
+
+ private $resultSet = array();
+ private $loadedLines = 0;
+
+ /**
+ * Construct and initialize a wrapper for DB2 query results
+ * @param $db Database
+ * @param $result Object
+ * @param $num_rows Integer
+ * @param $sql String
+ * @param $columns Array
+ */
+ public function __construct( $db, $result, $num_rows, $sql, $columns ){
+ $this->db = $db;
+
+ if( $result instanceof ResultWrapper ){
+ $this->result = $result->result;
+ }
+ else{
+ $this->result = $result;
+ }
+
+ $this->num_rows = $num_rows;
+ $this->current_pos = 0;
+ if ( $this->num_rows > 0 ) {
+ // Make a lower-case list of the column names
+ // By default, DB2 column names are capitalized
+ // while MySQL column names are lowercase
+
+ // Is there a reasonable maximum value for $i?
+ // Setting to 2048 to prevent an infinite loop
+ for( $i = 0; $i < 2048; $i++ ) {
+ $name = db2_field_name( $this->result, $i );
+ if ( $name != false ) {
+ continue;
+ }
+ else {
+ return false;
+ }
+
+ $this->columns[$i] = strtolower( $name );
+ }
+ }
+
+ $this->sql = $sql;
+ }
+
+ /**
+ * Unwrap the DB2 query results
+ * @return mixed Object on success, false on failure
+ */
+ public function getResult() {
+ if ( $this->result ) {
+ return $this->result;
+ }
+ else return false;
+ }
+
+ /**
+ * Get the number of rows in the result set
+ * @return integer
+ */
+ public function getNum_rows() {
+ return $this->num_rows;
+ }
+
+ /**
+ * Return a row from the result set in object format
+ * @return mixed Object on success, false on failure.
+ */
+ public function fetchObject() {
+ if ( $this->result
+ && $this->num_rows > 0
+ && $this->current_pos >= 0
+ && $this->current_pos < $this->num_rows )
+ {
+ $row = $this->fetchRow();
+ $ret = new stdClass();
+
+ foreach ( $row as $k => $v ) {
+ $lc = $this->columns[$k];
+ $ret->$lc = $v;
+ }
+ return $ret;
+ }
+ return false;
+ }
+
+ /**
+ * Return a row form the result set in array format
+ * @return mixed Array on success, false on failure
+ * @throws DBUnexpectedError
+ */
+ public function fetchRow(){
+ if ( $this->result
+ && $this->num_rows > 0
+ && $this->current_pos >= 0
+ && $this->current_pos < $this->num_rows )
+ {
+ if ( $this->loadedLines <= $this->current_pos ) {
+ $row = db2_fetch_array( $this->result );
+ $this->resultSet[$this->loadedLines++] = $row;
+ if ( $this->db->lastErrno() ) {
+ throw new DBUnexpectedError( $this->db, 'Error in fetchRow(): '
+ . htmlspecialchars( $this->db->lastError() ) );
+ }
+ }
+
+ if ( $this->loadedLines > $this->current_pos ){
+ return $this->resultSet[$this->current_pos++];
+ }
+
+ }
+ return false;
+ }
+
+ /**
+ * Free a DB2 result object
+ * @throws DBUnexpectedError
+ */
+ public function freeResult(){
+ unset( $this->resultSet );
+ if ( !@db2_free_result( $this->result ) ) {
+ throw new DBUnexpectedError( $this, "Unable to free DB2 result\n" );
+ }
+ }
+}
+