public function __construct($args = null)
 {
     $args_default = array('max_offset' => 2147483646, 'server' => array('ip' => '127.0.0.1', 'port' => 6379, 'database' => 15, 'alias' => 'first'));
     $args = FOX_sUtil::parseArgs($args, $args_default);
     foreach ($args as $key => $var) {
         $this->{$key} = $var;
     }
     unset($key, $var);
     // Handle process-id binding
     // ===========================================================
     if (FOX_sUtil::keyExists('process_id', $args)) {
         // Binding to a reference is important. It makes the cache engine $process_id
         // update if the FOX_mCache is changed, which we do during unit testing.
         $this->process_id =& $args['process_id'];
     } else {
         global $fox;
         $this->process_id = $fox->process_id;
     }
     $this->has_libs = true;
     if ($this->enable == true) {
         require_once FOX_PATH_BASE . '/lib/predis/autoload.php';
         $this->engine = new Predis\Client($this->server);
         $this->is_active = true;
     }
 }
 public function __construct($ctrl = null)
 {
     $this->store = array();
     $ctrl_default = array('prefix' => 'K');
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     $this->prefix = $ctrl['prefix'];
 }
 /**
  * Implodes an array of heirarchical datastore keys into a single query $args array
  *
  * @version 1.0
  * @since 1.0
  * 
  * @param array $trie | Trie structure
  * 
  * @param array $columns | Array of column names
  * 
  * @param array $ctrl | Control args 
  *	=> VAL @param string $null_token | String to use as null token 	  
  *
  * @return bool | Exception on failure. True on success.
  */
 function __construct($trie, $columns, $ctrl = null)
 {
     $this->trie = $trie;
     $this->columns = $columns;
     $this->max_depth = count($columns);
     $ctrl_default = array('null_token' => '*');
     $this->ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     $this->null_token = $this->ctrl['null_token'];
     return true;
 }
 /**
  * Implodes an array of heirarchical datastore keys into a single query $args array
  *
  * @version 1.0
  * @since 1.0
  * 
  * @param array $trie | Trie structure
  * @param array $columns | Array of column names
  *
  * @param array $ctrl | Control args
  *	=> VAL @param string $null_token | String to use as null token 	 
  *
  * @return array | Exception on failure. True on success.
  */
 function __construct($trie, $columns, $ctrl = null)
 {
     $this->trie = $trie;
     $this->columns = $columns;
     $ctrl_default = array('null_token' => '*', 'mode' => 'control');
     $this->ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     $this->null_token = $this->ctrl['null_token'];
     $this->mode = $this->ctrl['mode'];
     if ($this->mode == 'data') {
         $this->data_key = array_pop($this->columns);
     }
     $this->max_depth = count($this->columns) - 1;
     try {
         $result = $this->build();
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 1, 'text' => "Error during build process", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     return $result;
 }
 /**
  * Implodes an array of heirarchical datastore keys into a single query $args array
  *
  * @version 1.0
  * @since 1.0
  * 
  * @param array $columns | Array of column names
  * 
  * @param array $args | Array of key arrays
  *	=> ARR @param int '' | Array containing "column_name"=>"value"
  * 
  * @param array $ctrl | Control args
  *	=> VAL @param bool $optimize | True to optimize the $args matrix
  * 	=> VAL @param string $prefix | Prefix to add to column names
  *	=> VAL @param bool $trap_null | Throw an exception if one or more walks 
  *					in the args array collapses to "WHERE 1 = 1"
  *
  * @return array | Exception on failure. True on success.
  */
 function __construct($struct, $columns, $args, $ctrl = null)
 {
     $this->struct = $struct;
     $this->columns = $columns;
     $this->args = $args;
     $this->max_depth = count($columns) - 1;
     $ctrl_default = array('prefix' => '', 'optimize' => true, 'trap_null' => true, 'hash_token_vals' => true, 'null_token' => '*', 'mode' => 'matrix');
     $this->ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     if ($this->ctrl['hash_token_vals'] == true) {
         $this->hash_table = new FOX_hashTable();
     }
     $this->null_token = $this->ctrl['null_token'];
     $this->mode = $this->ctrl['mode'];
     try {
         $result = $this->build();
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 1, 'text' => "Error during build process", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     return $result;
 }
 /**
  * Validates a trie structure 
  *
  * @version 1.0
  * @since 1.0
  *
  * @param array $data | trie structure to validate
  *  
  * @param array $ctrl | Control parameters
  *	=> VAL @param int $order | Order of trie structure
  *	=> VAL @param string $mode | Operation mode 'control' | 'data'
  *	=> VAL @param bool $allow_wildcard | Allow wildcards (universal selector) to be used in control tries
  *	=> VAL @param string $wildcard_token | String to use as wildcard token
  *	=> VAL @param int $clip_order | Order to clip keys at when in 'data' mode	 
  * 
  * @return bool/array | Exception on failure, (bool)true on success, (array)data_array on failure.
  */
 public function validateTrie($data, $ctrl = null)
 {
     $ctrl_default = array('order' => $this->order, 'mode' => 'control', 'allow_wildcard' => false, 'wildcard_token' => '*', 'clip_order' => false);
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     if ($ctrl['order'] > $this->order || $ctrl['order'] < 0) {
         throw new FOX_exception(array('numeric' => 1, 'text' => "Specified order is not valid", 'data' => array("order" => $ctrl['order'], "class_order" => $this->order), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     if ($ctrl['mode'] != 'data' && $ctrl['mode'] != 'control') {
         throw new FOX_exception(array('numeric' => 2, 'text' => "Invalid 'mode' parameter", 'data' => array('ctrl' => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     if ($ctrl['mode'] == 'data' && !is_int($ctrl['clip_order'])) {
         throw new FOX_exception(array('numeric' => 3, 'text' => "The 'clip_order' parameter must be set when operating in 'data' mode", 'data' => array('ctrl' => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     if ($ctrl['mode'] == 'data' && $ctrl['allow_wildcard'] != false) {
         throw new FOX_exception(array('numeric' => 4, 'text' => "Wildcard selectors cannot be used in 'data' mode", 'data' => array('ctrl' => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     try {
         if ($ctrl['order'] == 0) {
             // We're at L0 in a walk
             return true;
         }
         if (is_array($data) && !empty($data)) {
             foreach ($data as $parent_id => $children) {
                 if (!($ctrl['allow_wildcard'] == true && $parent_id == $ctrl['wildcard_token'])) {
                     $check_result = self::validateKey(array('type' => $this->order_dict[$ctrl['order']]['type'], 'format' => 'scalar', 'var' => $parent_id));
                     if ($check_result !== true) {
                         return array('numeric' => 1, 'message' => $check_result, 'key' => $ctrl['order'], 'val' => $parent_id);
                     }
                 }
                 $child_result = self::validateTrie($children, array('order' => $ctrl['order'] - 1, 'mode' => $ctrl['mode'], 'allow_wildcard' => $ctrl['allow_wildcard'], 'clip_order' => $ctrl['clip_order']));
                 if ($child_result !== true) {
                     if (FOX_sUtil::keyExists('trace', $child_result)) {
                         $trace = array_merge($child_result['trace'], array($ctrl['order'] => $parent_id));
                     } else {
                         $trace = array($ctrl['order'] => $parent_id);
                     }
                     return array('numeric' => 2, 'message' => $child_result['message'], 'key' => $ctrl['order'], 'val' => $parent_id, 'trace' => $trace);
                 }
             }
             unset($parent_id, $children);
         } else {
             if ($ctrl['mode'] == 'control') {
                 if (!is_array($data) && (!is_bool($data) || $data === false)) {
                     $message = "Each walk in a control trie must terminate with either (bool)true, ";
                     $message .= "or an empty array, or must extend to the L1 key.";
                     return array('numeric' => 3, 'message' => $message, 'key' => $ctrl['order'], 'val' => $parent_id);
                 } else {
                     return true;
                 }
             } elseif ($ctrl['mode'] == 'data') {
                 if ($ctrl['order'] == $ctrl['clip_order'] - 1) {
                     if (!is_array($data) && (!is_bool($data) || $data === false)) {
                         $message = "Each walk in a data trie, that terminates at the clip_order, must ";
                         $message .= "terminate with an empty array.";
                         return array('numeric' => 4, 'message' => $message, 'key' => $ctrl['order'], 'val' => $parent_id);
                     } else {
                         return true;
                     }
                 } else {
                     $message = "Each walk in a data trie must terminate either at the clip_order ";
                     $message .= "or at the L1 key.";
                     return array('numeric' => 5, 'message' => $message, 'key' => $ctrl['order'], 'val' => $parent_id);
                 }
             }
         }
         // ENDOF: if( is_array($data) && !empty($data) )
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 5, 'text' => "Error in validator", 'data' => array("columns" => $this->order_dict), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     return true;
 }
 /**
  * Strips ASCII and Latin1 control characters. Passes spaces.
  *
  * @version 1.0
  * @since 1.0
  *
  * @param string $input | input string to process
  * @param array $ctrl | control parameters
  * @return string | the processed string
  */
 public function printableCharacter($input, $ctrl = null, &$valid = null, &$error = null)
 {
     $ctrl_default = array("null_input" => "null", "min_len" => 0, "max_len" => 50000);
     // crash on very large strings. For example, preg_replace() crashes
     // at about 94,000 characters.
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     if ($input === null) {
         if ($ctrl["null_input"] == "null") {
             $valid = true;
             return null;
         } elseif ($ctrl["null_input"] == "trap") {
             $valid = false;
             $error = "null input value";
             return null;
         }
     } else {
         // Make absolutely sure PHP treats the input data as a string
         $result = (string) $input;
         // We can't use the [:print:] character class because its a POSIX regex class and it's
         // not available in PHP's PCRE regex implementation (POSIX was deprecated in PHP 5.3).
         // Remove ASCII control characters
         $result = preg_replace('[\\x00-\\x1F\\x7F]', '', $result);
         // Remove Latin1 control characters
         $result = preg_replace('[\\x80-\\x9F]', '', $result);
         $len = strlen($result);
         // Handle string being zero length after trimming off padding characters
         if ($len == 0) {
             if ($ctrl["null_input"] == "null") {
                 $valid = true;
                 return null;
             } elseif ($ctrl["null_input"] == "trap") {
                 $valid = false;
                 $error = "null input value";
                 return null;
             }
         }
         // Truncate strings that exceed the max length
         if ($len > $ctrl["max_len"]) {
             $valid = true;
             $result = substr($result, 0, $ctrl["max_len"]);
             return $result;
         } elseif ($len < $ctrl["min_len"]) {
             $valid = false;
             $error = "string exceeds min_len";
             return $result;
         } else {
             $valid = true;
             return $result;
         }
     }
 }
 /**
  * Drops one or more items of the specified level from ALL WALKS in the datastore.
  * 
  * @version 1.0
  * @since 1.0
  * @param int $level | Level to drop items from	 
  * @param int/string/array $items | Single item as int/string, multiple as array of int/string.
  * 
  * @return int | Exception on failure. Number of rows changed on success.
  */
 public function dropGlobal($level, $items, $ctrl = null)
 {
     if (!$this->init) {
         throw new FOX_exception(array('numeric' => 0, 'text' => "Descendent class must call init() before using class methods", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "method_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     $col = "L" . $level . "_col";
     $ctrl_default = array("validate" => true);
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     // Validate
     // ===================================================
     if ($ctrl['validate'] != false) {
         if ($this->debug_on) {
             extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "validate_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
         }
         // Each variable has to be validated individually. If we spin the variables
         // into a trie, PHP will automatically convert strings that map to ints ("17")
         // into (int) keys, which will defeat the validators
         $struct = $this->_struct();
         try {
             $validator = new FOX_dataStore_validator($struct);
             // If a single item is sent in, we validate it *before* spinning it into an array,
             // so we can trap strings that PHP automatically converts to ints ("17")
             if (!is_array($items)) {
                 $is_valid = $validator->validateKey(array('type' => $struct['columns'][$this->{$col}]['php'], 'format' => 'scalar', 'var' => $items));
             } else {
                 foreach ($items as $key => $val) {
                     $is_valid = $validator->validateKey(array('type' => $struct['columns'][$this->{$col}]['php'], 'format' => 'scalar', 'var' => $val));
                     // Break the loop if we hit an invalid key
                     if ($is_valid !== true) {
                         break;
                     }
                 }
                 unset($key, $val);
             }
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 1, 'text' => "Error in validator", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         // This structure has to be outside the validator try-catch block to prevent it from
         // catching the exceptions we throw (which would cause confusing exception chains)
         if ($is_valid !== true) {
             throw new FOX_exception(array('numeric' => 2, 'text' => "Invalid item", 'data' => $is_valid, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
         }
         if ($this->debug_on) {
             extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "validate_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
         }
     }
     // ENDOF: if($ctrl['validate'] != false){
     // Lock the entire cache namespace
     // ===========================================================
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "persistent_cache_lock_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     try {
         self::lockNamespace();
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 3, 'text' => "Error locking cache namespace", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "persistent_cache_lock_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "db_delete_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     $args = array(array("col" => $this->{$col}, "op" => "=", "val" => $items));
     try {
         $rows_changed = $this->db->runDeleteQuery($struct, $args, $ctrl = null);
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 4, 'text' => "Error while deleting from database", 'data' => $args, 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "db_delete_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     // Since this operation affects ALL L5 pages, we have to flush the
     // entire cache namespace
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "persistent_cache_flush_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     try {
         self::flushCache();
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 5, 'text' => "Cache flush error", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "persisent_cache_flush_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "method_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     return (int) $rows_changed;
 }
 /**
  * Runs a DELETE query on one of the plugin's db tables.
  *
  * @version 1.0
  * @since 1.0
  *
  * @param array $struct | Structure of the db table, @see class FOX_db header for examples
  *
  * @param array $args | Args in the form: array("col"=>column_name, "op" => "<, >, =, !=", "val" => "int | string | array()")
  *	=> ARR @param int '' | Array index
  *	    => VAL @param string $col | Name of the column in the db table this key describes
  *	    => VAL @param string $op | SQL comparison operator to use: ">=" | "<=" | ">" | "<" | "=" | "!=" | "<>"
  *	    => VAL @param int/string/array $val | Value or values to test against. Single value as int/string. Multiple values as array.
  *
  * @param array $ctrl | Control parameters for the query
  *	=> VAL @param string $args_format | "default" to use standard format, "multi", "matrix", or "trie"
  * 
  * @return int | Exception on failure. Int number of rows deleted on success.
  */
 public function runDeleteQuery($struct, $args, $ctrl = null)
 {
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "method_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     // Add default control params
     // ==========================
     $ctrl_default = array("args_format" => "default");
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     // Build query string
     // =======================
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "build_query", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     try {
         $query = $this->builder->buildDeleteQuery($struct, $args, $ctrl);
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 1, 'text' => "Error in query generator", 'data' => array("struct" => $struct, "args" => $args, 'ctrl' => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     // Run on SQL server
     // =======================
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "run_query", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     try {
         $this->runner->runQuery($query, array('format' => 'var'));
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 2, 'text' => "Error executing query on SQL server", 'data' => array("query" => $query), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "method_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     return $this->rows_affected;
 }
 /**
  * Locks the class' entire namespace, giving the locking PID exclusive control of it.
  *
  * @version 1.0
  * @since 1.0
  * 
  * @param array $ctrl | Control parameters 
  *	=> VAL @param int $seconds |  Time in seconds from present time until lock expires	  
  * 
  * @return mixed | Exception on failure. True on success.
  */
 public function lockNamespace($ctrl = null)
 {
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "method_start", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     $struct = $this->_struct();
     if ($struct['cache_strategy'] != 'paged') {
         throw new FOX_exception(array('numeric' => 1, 'text' => "This method can only be used on classes that use a paged cache", 'data' => array('struct' => $struct), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     $ctrl_default = array('seconds' => 5);
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     try {
         $result = $this->mCache->lockNamespace(array('process_id' => $this->process_id, 'engine' => $struct["cache_engine"], 'namespace' => $struct["cache_namespace"], 'seconds' => $ctrl['seconds']));
     } catch (FOX_exception $child) {
         throw new FOX_exception(array('numeric' => 2, 'text' => "Error in mCache->lockNamespace()", 'data' => array('struct' => $struct), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
     }
     if ($this->debug_on) {
         extract($this->debug_handler->event(array('pid' => $this->process_id, 'text' => "method_end", 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'parent' => $this, 'vars' => compact(array_keys(get_defined_vars())))));
     }
     return $result;
 }
 /**
  * Builds a delete query for processing by $wpdb->prepare().
  *
  * @version 1.0
  * @since 1.0
  *
  * @param array $struct | Structure of the db table, @see class FOX_db header for examples
  *
  * @param array $args | Args in the form: array("col"=>column_name, "op" => "<, >, =, !=", "val" => "int | string | array()")
  *	=> ARR @param int '' | Array index
  *	    => VAL @param string $col | Name of the column in the db table this key describes
  *	    => VAL @param string $op | SQL comparison operator to use: ">=" | "<=" | ">" | "<" | "=" | "!=" | "<>"
  *	    => VAL @param int/string/array $val | Value or values to test against. Single value as int/string. Multiple values as array.
  *
  * @param array $ctrl | Control parameters for the query
  *	=> VAL @param string $args_format | "default" to use standard format, "multi", or "matrix"
  * 
  * @return array | Exception on failure. Query array on success.
  */
 public function buildDeleteQuery($struct, $args, $ctrl = null)
 {
     $ctrl_default = array('args_format' => 'default');
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     // Switch between unit test mode (pass as array) and
     // normal mode (pass as class name)
     // ====================================================
     if (is_string($struct)) {
         $struct = call_user_func(array($struct, '_struct'));
     }
     // ====================================================
     // Build WHERE statement
     // ######################################################
     $where = "1 = 1";
     // We need to pre-load it with a value in case the user adds zero 'where' conditions
     // Primary table args. The "if" clause handles the case where the user passes no args because
     // they do not want to constrain the query using a column in the primary table.
     if ($args) {
         try {
             switch ($ctrl['args_format']) {
                 case "multi":
                     $result = self::buildWhereMulti($struct, $args, __FUNCTION__, $prefix = null);
                     break;
                 case "matrix":
                     // Forward the 'hash_token_vals' flag, if set
                     if (FOX_sUtil::keyExists('hash_token_vals', $args)) {
                         $matrix_ctrl = array('hash_token_vals' => $args['hash_token_vals']);
                     } else {
                         $matrix_ctrl = null;
                     }
                     $result = self::buildWhereMatrix($struct, $args["key_col"], $args["args"], $matrix_ctrl);
                     break;
                 case "trie":
                     // Forward the 'hash_token_vals' flag, if set
                     if (FOX_sUtil::keyExists('hash_token_vals', $args)) {
                         $trie_ctrl = array('hash_token_vals' => $args['hash_token_vals']);
                     } else {
                         $trie_ctrl = null;
                     }
                     $result = self::buildWhereTrie($struct, $args["key_col"], $args["args"], $trie_ctrl);
                     break;
                 default:
                     $result = self::buildWhere($struct, $args, __FUNCTION__, $prefix = null);
                     break;
             }
         } catch (FOX_exception $child) {
             throw new FOX_exception(array('numeric' => 1, 'text' => "Error in buildWhere generator", 'data' => array("struct" => $struct, "args" => $args, "ctrl" => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => $child));
         }
         $where .= $result['where'];
         $params_list = $result['params'];
         unset($result);
     } else {
         // From the MySQL site: "DELETE FROM tbl_name does not regenerate the table but instead deletes all rows, one by one."
         // @link http://dev.mysql.com/doc/refman/5.5/en/innodb-restrictions.html
         $text = "\nSAFTEY INTERLOCK TRIP [DESTROY TABLE] - buildDeleteQuery() called with no WHERE args. Running this query would delete ";
         $text .= " ALL rows in the target table. If this is what you really want to do, use buildTruncateTable().\n";
         throw new FOX_exception(array('numeric' => 2, 'text' => $text, 'data' => array("struct" => $struct, "args" => $args, "ctrl" => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     $query = "DELETE FROM " . $this->base_prefix . $struct["table"] . " WHERE " . $where;
     // Merge all return data into an array
     // ###############################################################
     $result = array('query' => $query, 'params' => $params_list);
     return $result;
 }
 /**
  * Runs a query on the database. Returns results in a specific format.
  *
  * @version 1.0
  * @since 1.0
  * @link https://github.com/FoxFire/foxfirewiki/DOCS_FOX_db_select_formatter
  *
  * @param string $sql | SQL query string
  *
  * @param array $ctrl | Control parameters for the query
  *	=> VAL @param string $format | Return format for query: "col", "row", "var", "array_key_object", "array_key_array"
  *				       "array_key_single", "array_object", "array_array", "raw", or (null)
  *				       @see result formatter headers inside this method for detailed docs
  *
  *	=> VAL @see FOX_db::runSelectQuery() and FOX_db::runSelectQueryJoin() for docs on remaining $ctrl options
  *
  * @return bool | Exception on failure. Query results array on success.
  */
 public function runQuery($query, $ctrl = null)
 {
     $ctrl_default = array('format' => 'raw');
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     if ($this->print_query_args == true) {
         ob_start();
         print_r($query);
         print_r($ctrl);
         $out = ob_get_clean();
         FOX_debug::addToFile($out);
     }
     // Handle single parameter as string/int, or multiple
     // parameters passed as an array
     // ==================================================
     if (is_array($query)) {
         $sql = $this->driver->prepare($query['query'], $query['params']);
     } else {
         $sql = $query;
         $query = array('types' => array());
         $ctrl = array("format" => "raw");
     }
     // TODO: This prevents PHP from throwing a warning in queryResult() when the table
     // builder methods run their queries (which have no return type), but it should be
     // improved to prevent queries that are accidentally missing return data types
     // from leaking through
     if (!array_key_exists('types', $query)) {
         $query['types'] = array();
     }
     if ($this->print_query_sql == true) {
         FOX_debug::addToFile($sql);
     }
     // EXAMPLE TABLE "test_table"
     // =================================
     //  col_1 | col_2 | col_3 | col_4 |
     // =================================
     //    1   |  red  |  dog  |  big  |
     //    2   |  green|  cat  |  med  |
     //    3   |  blue |  bird | small |
     //    4   |  black|  fish |  tiny |
     $cast = new FOX_cast();
     switch ($ctrl["format"]) {
         // VAR
         // =============================================================================
         // Used when fetching query results that return a single variable.
         //
         // EXAMPLE: "SELECT COUNT(*) FROM test_table WHERE col_2 = red"
         // RESULT: string "1" (all data is returned in string format)
         case "var":
             try {
                 $sql_result = $this->driver->get_var($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 1, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "\nRAW, format = var\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $result = $sql_result;
             } else {
                 $result = $cast->queryResult($format = "var", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = var\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             break;
             // COL
             // =============================================================================
             // Used when fetching query results which only contain values from a single column.
             //
             // EXAMPLE: "SELECT col2 FROM test_table"
             // RESULT: array("red", "green", "blue", "black")
         // COL
         // =============================================================================
         // Used when fetching query results which only contain values from a single column.
         //
         // EXAMPLE: "SELECT col2 FROM test_table"
         // RESULT: array("red", "green", "blue", "black")
         case "col":
             try {
                 $sql_result = $this->driver->get_col($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 2, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "\nRAW, format = col\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $result = $sql_result;
             } else {
                 $result = $cast->queryResult($format = "col", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = col\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             break;
             // ROW_OBJECT
             // =============================================================================
             // Returns a single database row as an object, with variable names mapped to
             // column names. If the query returns multiple rows, only the first row is returned.
             //
             // EXAMPLE: "SELECT * FROM test_table WHERE col_1 = 2"
             // RESULT: object stdClass(
             //		    col_1->2
             //		    col_2->"green"
             //		    col_3->"cat"
             //		    col_4->"med"
             //	    )
         // ROW_OBJECT
         // =============================================================================
         // Returns a single database row as an object, with variable names mapped to
         // column names. If the query returns multiple rows, only the first row is returned.
         //
         // EXAMPLE: "SELECT * FROM test_table WHERE col_1 = 2"
         // RESULT: object stdClass(
         //		    col_1->2
         //		    col_2->"green"
         //		    col_3->"cat"
         //		    col_4->"med"
         //	    )
         case "row_object":
             try {
                 $sql_result = $this->driver->get_row($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 3, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "\nRAW, format = row\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $result = $sql_result;
             } else {
                 $result = $cast->queryResult($format = "row_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = row_object\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             break;
             // ROW_ARRAY
             // =============================================================================
             // Returns a single database row as an array, with key names mapped to column
             // names. If the query returns multiple rows, only the first row is returned.
             //
             // EXAMPLE: "SELECT * FROM test_table WHERE col_1 = 2"
             // RESULT: array(
             //		    "col_1"=>2
             //		    "col_2"=>"green"
             //		    "col_3"=>"cat"
             //		    "col_4"=>"med"
             //	       )
         // ROW_ARRAY
         // =============================================================================
         // Returns a single database row as an array, with key names mapped to column
         // names. If the query returns multiple rows, only the first row is returned.
         //
         // EXAMPLE: "SELECT * FROM test_table WHERE col_1 = 2"
         // RESULT: array(
         //		    "col_1"=>2
         //		    "col_2"=>"green"
         //		    "col_3"=>"cat"
         //		    "col_4"=>"med"
         //	       )
         case "row_array":
             try {
                 $sql_result = $this->driver->get_row($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 4, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "\nRAW, format = row_array\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "row_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = row_array\n";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 // Convert row object into array
                 foreach ($data as $key => $value) {
                     $result[$key] = $value;
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nFORMATTED, format = row_array\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // ARRAY_KEY_OBJECT
             // =============================================================================
             //
             // When used with a single column name passed as a string:
             //
             // Returns results as an array of objects, where the primary array key names are
             // set based on the contents of a database column.
             //
             // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"]="col_3"
             // RESULT:   array(
             //		    "dog" =>stdClass( "col_1"->1, "col_2"->"red", "col_3"->"dog", "col_4"->"big"),
             //		    "cat" =>stdClass( "col_1"->2, "col_2"->"green", "col_3"->"cat", "col_4"->"med"),
             //		    "bird"=>stdClass( "col_1"->3, "col_2"->"blue", "col_3"->"bird", "col_4"->"small"),
             //		    "fish"=>stdClass( "col_1"->4, "col_2"->"black", "col_3"->"fish", "col_4"->"tiny"),
             //	     )
             // When used with multiple column names passed as an array of strings:
             //
             // Returns results as an array of arrays^N, where the array key names and heirarchy
             // are set based on the contents of the $key_col array. This output format REQUIRES
             // that each taxonomy group (in the example below "col_3" + "col_4") is UNIQUE
             //
             // EXAMPLE TABLE "test_table_2"
             // ======================================
             //  col_1 | col_2 | col_3 | col_4 | col_5
             // ======================================
             //    1   |  red  |  dog  |  big  | heavy
             //    2   |  green|  dog  |  med  | light
             //    3   |  blue |  bird | small | light
             //    4   |  black|  fish |  tiny | average
             //    5   |  black|  fish | large | light
             //
             // UNIQUE KEY col_3_col4(col_3, col_4)
             //
             // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_3, "col_4")
             // RESULT:   array(
             //		    "dog" =>array(
             //				    "big"=>stdClass("col_1"->1, "col_2"->"red", "col_5"->"heavy"),
             //				    "med"=>stdClass("col_1"->2, "col_2"->"green", "col_5"->"light")
             //		    ),
             //		    "bird"=>array(
             //				    "small"=>stdClass("col_1"->3, "col_2"->"blue", "col_5"->"light")
             //		    ),
             //		    "fish"=>array(
             //				    "tiny"=>stdClass("col_1"->4, "col_2"->"black", "col_5"->"average"),
             //				    "large"=>stdClass("col_1"->5, "col_2"->"black", "col_5"->"light")
             //		    )
             //	     )
         // ARRAY_KEY_OBJECT
         // =============================================================================
         //
         // When used with a single column name passed as a string:
         //
         // Returns results as an array of objects, where the primary array key names are
         // set based on the contents of a database column.
         //
         // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"]="col_3"
         // RESULT:   array(
         //		    "dog" =>stdClass( "col_1"->1, "col_2"->"red", "col_3"->"dog", "col_4"->"big"),
         //		    "cat" =>stdClass( "col_1"->2, "col_2"->"green", "col_3"->"cat", "col_4"->"med"),
         //		    "bird"=>stdClass( "col_1"->3, "col_2"->"blue", "col_3"->"bird", "col_4"->"small"),
         //		    "fish"=>stdClass( "col_1"->4, "col_2"->"black", "col_3"->"fish", "col_4"->"tiny"),
         //	     )
         // When used with multiple column names passed as an array of strings:
         //
         // Returns results as an array of arrays^N, where the array key names and heirarchy
         // are set based on the contents of the $key_col array. This output format REQUIRES
         // that each taxonomy group (in the example below "col_3" + "col_4") is UNIQUE
         //
         // EXAMPLE TABLE "test_table_2"
         // ======================================
         //  col_1 | col_2 | col_3 | col_4 | col_5
         // ======================================
         //    1   |  red  |  dog  |  big  | heavy
         //    2   |  green|  dog  |  med  | light
         //    3   |  blue |  bird | small | light
         //    4   |  black|  fish |  tiny | average
         //    5   |  black|  fish | large | light
         //
         // UNIQUE KEY col_3_col4(col_3, col_4)
         //
         // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_3, "col_4")
         // RESULT:   array(
         //		    "dog" =>array(
         //				    "big"=>stdClass("col_1"->1, "col_2"->"red", "col_5"->"heavy"),
         //				    "med"=>stdClass("col_1"->2, "col_2"->"green", "col_5"->"light")
         //		    ),
         //		    "bird"=>array(
         //				    "small"=>stdClass("col_1"->3, "col_2"->"blue", "col_5"->"light")
         //		    ),
         //		    "fish"=>array(
         //				    "tiny"=>stdClass("col_1"->4, "col_2"->"black", "col_5"->"average"),
         //				    "large"=>stdClass("col_1"->5, "col_2"->"black", "col_5"->"light")
         //		    )
         //	     )
         case "array_key_object":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 5, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "\nRAW, format = array_key_object\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_key_object\n";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 // If a single column name is passed as a string, use the more efficient
                 // direct assignment algorithm to build a 1 level tree
                 if (!is_array($ctrl["key_col"])) {
                     foreach ($data as $row) {
                         $key = $row->{$ctrl["key_col"]};
                         $result[$key] = $row;
                     }
                 } else {
                     foreach ($data as $row) {
                         // Since there is no functionality in PHP for creating a new array key
                         // based on a name stored in a variable ( $$ variable variable syntax does
                         // not work for multidimensional arrays, we have to build a string of PHP
                         // code and use eval() to run it
                         $eval_str = "\$result";
                         foreach ($ctrl["key_col"] as $keyname) {
                             $eval_str .= '["' . $row->{$keyname} . '"]';
                         }
                         $eval_str .= " = \$row_copy;";
                         $row_copy = new stdClass();
                         // Copy the row object into a new stdClass, skipping keys that are used as the
                         // branch variables
                         foreach ($row as $key => $value) {
                             if (array_search($key, $ctrl["key_col"]) === false) {
                                 $row_copy->{$key} = $value;
                             }
                         }
                         // Run the PHP string we have built
                         eval($eval_str);
                     }
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nFORMATTED, format = array_key_object\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // ARRAY_KEY_ARRAY
             // =============================================================================
             // When used with a single column name passed as a string:
             //
             // Returns results as an array of arrays, where the primary array key names are
             // set based on the contents of a database column.
             //
             // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"]="col_3"
             // RESULT:   array(
             //		    "dog" =>array( "col_1"=>1, "col_2"=>"red", "col_3"=>"dog", "col_4"=>"big"),
             //		    "cat" =>array( "col_1"=>2, "col_2"=>"green", "col_3"=>"cat", "col_4"=>"med"),
             //		    "bird"=>array( "col_1"=>3, "col_2"=>"blue", "col_3"=>"bird", "col_4"=>"small"),
             //		    "fish"=>array( "col_1"=>4, "col_2"=>"black", "col_3"=>"fish", "col_4"=>"tiny"),
             //	     )
             //
             // When used with multiple column names passed as an array of strings:
             //
             // Returns results as an array of arrays^N, where the array key names and heirarchy
             // are set based on the contents of the $key_col array. This output format REQUIRES
             // that each taxonomy group (in the example below "col_3" + "col_4") is UNIQUE
             //
             // EXAMPLE TABLE "test_table_2"
             // ======================================
             //  col_1 | col_2 | col_3 | col_4 | col_5
             // ======================================
             //    1   |  red  |  dog  |  big  | heavy
             //    2   |  green|  dog  |  med  | light
             //    3   |  blue |  bird | small | light
             //    4   |  black|  fish |  tiny | average
             //    5   |  black|  fish | large | light
             //
             // UNIQUE KEY col_3_col4(col_3, col_4)
             //
             // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_3, "col_4")
             // RESULT:   array(
             //		    "dog" =>array(
             //				    "big"=>array("col_1"=>1, "col_2"=>"red", "col_5"=>"heavy"),
             //				    "med"=>array("col_1"=>2, "col_2"=>"green", "col_5"=>"light")
             //		    ),
             //		    "bird"=>array(
             //				    "small"=>array("col_1"=>3, "col_2"=>"blue", "col_5"=>"light")
             //		    ),
             //		    "fish"=>array(
             //				    "tiny"=>array("col_1"=>4, "col_2"=>"black", "col_5"=>"average"),
             //				    "large"=>array("col_1"=>5, "col_2"=>"black", "col_5"=>"light")
             //		    )
             //	     )
         // ARRAY_KEY_ARRAY
         // =============================================================================
         // When used with a single column name passed as a string:
         //
         // Returns results as an array of arrays, where the primary array key names are
         // set based on the contents of a database column.
         //
         // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"]="col_3"
         // RESULT:   array(
         //		    "dog" =>array( "col_1"=>1, "col_2"=>"red", "col_3"=>"dog", "col_4"=>"big"),
         //		    "cat" =>array( "col_1"=>2, "col_2"=>"green", "col_3"=>"cat", "col_4"=>"med"),
         //		    "bird"=>array( "col_1"=>3, "col_2"=>"blue", "col_3"=>"bird", "col_4"=>"small"),
         //		    "fish"=>array( "col_1"=>4, "col_2"=>"black", "col_3"=>"fish", "col_4"=>"tiny"),
         //	     )
         //
         // When used with multiple column names passed as an array of strings:
         //
         // Returns results as an array of arrays^N, where the array key names and heirarchy
         // are set based on the contents of the $key_col array. This output format REQUIRES
         // that each taxonomy group (in the example below "col_3" + "col_4") is UNIQUE
         //
         // EXAMPLE TABLE "test_table_2"
         // ======================================
         //  col_1 | col_2 | col_3 | col_4 | col_5
         // ======================================
         //    1   |  red  |  dog  |  big  | heavy
         //    2   |  green|  dog  |  med  | light
         //    3   |  blue |  bird | small | light
         //    4   |  black|  fish |  tiny | average
         //    5   |  black|  fish | large | light
         //
         // UNIQUE KEY col_3_col4(col_3, col_4)
         //
         // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_3, "col_4")
         // RESULT:   array(
         //		    "dog" =>array(
         //				    "big"=>array("col_1"=>1, "col_2"=>"red", "col_5"=>"heavy"),
         //				    "med"=>array("col_1"=>2, "col_2"=>"green", "col_5"=>"light")
         //		    ),
         //		    "bird"=>array(
         //				    "small"=>array("col_1"=>3, "col_2"=>"blue", "col_5"=>"light")
         //		    ),
         //		    "fish"=>array(
         //				    "tiny"=>array("col_1"=>4, "col_2"=>"black", "col_5"=>"average"),
         //				    "large"=>array("col_1"=>5, "col_2"=>"black", "col_5"=>"light")
         //		    )
         //	     )
         case "array_key_array":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 6, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "RAW, format = array_key_array\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_key_array\n";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 // If a single column name is passed as a string, use the more efficient
                 // direct assignment algorithm to build a 1 level tree
                 if (!is_array($ctrl["key_col"])) {
                     foreach ($data as $row) {
                         $arr = array();
                         // Convert row object into array
                         foreach ($row as $key => $value) {
                             $arr[$key] = $value;
                         }
                         // Insert row array into primary array as named key
                         $result[$row->{$ctrl["key_col"]}] = $arr;
                     }
                 } else {
                     foreach ($data as $row) {
                         // Since there is no functionality in PHP for creating a new array key
                         // based on a name stored in a variable ( $$ variable variable syntax does
                         // not work for multidimensional arrays), we have to build a string of PHP
                         // code and use eval() to run it
                         $eval_str = "\$result";
                         foreach ($ctrl["key_col"] as $keyname) {
                             $eval_str .= '["' . $row->{$keyname} . '"]';
                         }
                         $eval_str .= " = \$arr;";
                         $arr = array();
                         // Convert row object into array, skipping keys that are used as the
                         // branch variables
                         foreach ($row as $key => $value) {
                             // Check if this is a first-order row. If it is, "lift" it up a
                             // level in the results array to avoid adding an unnecessary "L0"
                             // wrapper array around it
                             $order = count(array_keys((array) $row)) - count($ctrl["key_col"]);
                             if ($order > 1) {
                                 if (array_search($key, $ctrl["key_col"]) === false) {
                                     $arr[$key] = $value;
                                 }
                             } else {
                                 $arr = $value;
                             }
                         }
                         // Run the PHP string we have built
                         eval($eval_str);
                     }
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nFORMATTED, format = array_key_array\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // ARRAY_KEY_ARRAY_GROUPED
             // =============================================================================
             //
             // Requires at least TWO column names, and columns not specified in $key_col are not
             // included in the results set. Returns results as an array of arrays^N-1, where the
             // array key names and heirarchy are set based on the contents of the $key_col array.
             // Results in the last db column specified in $key_col are grouped together in an
             // int-keyed array. The key name corresponds to the order in which a rows is returned
             // from the database and the value of each key is the column's value in the database
             // row. For a working example of how to use this result formatter, see the function
             // database_resultFormatters::test_array_key_array_grouped() in the database unit tests.
             //
             // EXAMPLE TABLE "test_table_2"
             // ===============================
             //  col_1 | col_2 | col_3 | col_4
             // ===============================
             //    1   |  red  |  dog  | A
             //    2   |  green|  dog  | B
             //    3   |  green|  dog  | C
             //    4   |  green|  dog  | D
             //    5   |  blue |  bird | A
             //    6   |  black|  bird | A
             //    7   |  black|  fish | A
             //    8   |  black|  fish | B
             //
             // UNIQUE KEY no_duplicates(col_2, col_3, col_4)
             //
             // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_2, "col_3", "col_4")
             // NOTE: "col_1" is excluded because it is not specified in $ctrl["key_col"]
             // RESULT:   array(
             //		    "dog" =>array(
             //				    "red"=>	array("A"),
             //				    "green"=>	array("B","C","D")
             //		    ),
             //		    "bird" =>array(
             //				    "blue"=>	array("A"),
             //				    "black"=>	array("A")
             //		    ),
             //		    "fish" =>array(
             //				    "black"=>	array("A","B")
             //		    )
             //	     )
         // ARRAY_KEY_ARRAY_GROUPED
         // =============================================================================
         //
         // Requires at least TWO column names, and columns not specified in $key_col are not
         // included in the results set. Returns results as an array of arrays^N-1, where the
         // array key names and heirarchy are set based on the contents of the $key_col array.
         // Results in the last db column specified in $key_col are grouped together in an
         // int-keyed array. The key name corresponds to the order in which a rows is returned
         // from the database and the value of each key is the column's value in the database
         // row. For a working example of how to use this result formatter, see the function
         // database_resultFormatters::test_array_key_array_grouped() in the database unit tests.
         //
         // EXAMPLE TABLE "test_table_2"
         // ===============================
         //  col_1 | col_2 | col_3 | col_4
         // ===============================
         //    1   |  red  |  dog  | A
         //    2   |  green|  dog  | B
         //    3   |  green|  dog  | C
         //    4   |  green|  dog  | D
         //    5   |  blue |  bird | A
         //    6   |  black|  bird | A
         //    7   |  black|  fish | A
         //    8   |  black|  fish | B
         //
         // UNIQUE KEY no_duplicates(col_2, col_3, col_4)
         //
         // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_2, "col_3", "col_4")
         // NOTE: "col_1" is excluded because it is not specified in $ctrl["key_col"]
         // RESULT:   array(
         //		    "dog" =>array(
         //				    "red"=>	array("A"),
         //				    "green"=>	array("B","C","D")
         //		    ),
         //		    "bird" =>array(
         //				    "blue"=>	array("A"),
         //				    "black"=>	array("A")
         //		    ),
         //		    "fish" =>array(
         //				    "black"=>	array("A","B")
         //		    )
         //	     )
         case "array_key_array_grouped":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 7, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "RAW, format = array_key_array_grouped\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_key_array_grouped\n";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 foreach ($data as $row) {
                     // Since there is no functionality in PHP for creating a new array key
                     // based on a name stored in a variable ( $$ variable variable syntax does
                     // not work for multidimensional arrays), we have to build a string of PHP
                     // code and use eval() to run it
                     $eval_str = "\$result";
                     $idx = sizeof($ctrl["key_col"]) - 1;
                     $grouped_col = $ctrl["key_col"][$idx];
                     foreach ($ctrl["key_col"] as $keyname) {
                         if ($keyname != $grouped_col) {
                             $eval_str .= '["' . $row->{$keyname} . '"]';
                         } else {
                             $eval_str .= '[]';
                         }
                     }
                     $eval_str .= " = \$row->" . $grouped_col . ";";
                     // Run the PHP string we have built
                     eval($eval_str);
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nFORMATTED, format = array_key_array_grouped\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // ARRAY_KEY_ARRAY_TRUE
             // =============================================================================
             //
             // Returns results as an array of arrays^N-1, where the array key names and heirarchy
             // are set based on the contents of the $key_col array. Results in the last db column
             // specified in $key_col are grouped together in an result-keyed array where the key
             // name is the column's value in the database row and the key's value is (bool)true.
             // For a working example of how to use this result formatter, see the function
             // database_resultFormatters::test_array_key_array_true() in the database unit tests.
             //
             // EXAMPLE TABLE "test_table_2"
             // ===============================
             //  col_1 | col_2 | col_3 | col_4
             // ===============================
             //    1   |  red  |  dog  | A
             //    2   |  green|  dog  | B
             //    3   |  green|  dog  | C
             //    4   |  green|  dog  | D
             //    5   |  blue |  bird | A
             //    6   |  black|  bird | A
             //    7   |  black|  fish | A
             //    8   |  black|  fish | B
             //
             // UNIQUE KEY no_duplicates(col_2, col_3, col_4)
             //
             // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_2, "col_3", "col_4")
             // NOTE: "col_1" is excluded because it is not specified in $ctrl["key_col"]
             // RESULT:   array(
             //		    "dog" =>array(
             //				    "red"=>	array("A"=>"true"),
             //				    "green"=>	array("B"=>"true","C"=>"true","D"=>"true")
             //		    ),
             //		    "bird" =>array(
             //				    "blue"=>	array("A"=>"true"),
             //				    "black"=>	array("A"=>"true")
             //		    ),
             //		    "fish" =>array(
             //				    "black"=>	array("A"=>"true","B"=>"true")
             //		    )
             //	     )
         // ARRAY_KEY_ARRAY_TRUE
         // =============================================================================
         //
         // Returns results as an array of arrays^N-1, where the array key names and heirarchy
         // are set based on the contents of the $key_col array. Results in the last db column
         // specified in $key_col are grouped together in an result-keyed array where the key
         // name is the column's value in the database row and the key's value is (bool)true.
         // For a working example of how to use this result formatter, see the function
         // database_resultFormatters::test_array_key_array_true() in the database unit tests.
         //
         // EXAMPLE TABLE "test_table_2"
         // ===============================
         //  col_1 | col_2 | col_3 | col_4
         // ===============================
         //    1   |  red  |  dog  | A
         //    2   |  green|  dog  | B
         //    3   |  green|  dog  | C
         //    4   |  green|  dog  | D
         //    5   |  blue |  bird | A
         //    6   |  black|  bird | A
         //    7   |  black|  fish | A
         //    8   |  black|  fish | B
         //
         // UNIQUE KEY no_duplicates(col_2, col_3, col_4)
         //
         // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_2, "col_3", "col_4")
         // NOTE: "col_1" is excluded because it is not specified in $ctrl["key_col"]
         // RESULT:   array(
         //		    "dog" =>array(
         //				    "red"=>	array("A"=>"true"),
         //				    "green"=>	array("B"=>"true","C"=>"true","D"=>"true")
         //		    ),
         //		    "bird" =>array(
         //				    "blue"=>	array("A"=>"true"),
         //				    "black"=>	array("A"=>"true")
         //		    ),
         //		    "fish" =>array(
         //				    "black"=>	array("A"=>"true","B"=>"true")
         //		    )
         //	     )
         case "array_key_array_true":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 8, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "RAW, format = array_key_array_true\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_key_array_true\n";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 foreach ($data as $row) {
                     // Since there is no functionality in PHP for creating a new array key
                     // based on a name stored in a variable ( $$ variable variable syntax does
                     // not work for multidimensional arrays), we have to build a string of PHP
                     // code and use eval() to run it
                     $eval_str = "\$result";
                     foreach ($ctrl["key_col"] as $keyname) {
                         $eval_str .= '["' . $row->{$keyname} . '"]';
                     }
                     $eval_str .= " = true;";
                     // Run the PHP string we have built
                     eval($eval_str);
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nFORMATTED, format = array_key_array_true\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // ARRAY_KEY_ARRAY_FALSE
             // =============================================================================
             //
             // Returns results as an array of arrays^N-1, where the array key names and heirarchy
             // are set based on the contents of the $key_col array. Results in the last db column
             // specified in $key_col are grouped together in an result-keyed array where the key
             // name is the column's value in the database row and the key's value is (bool)false.
             // For a working example of how to use this result formatter, see the function
             // database_resultFormatters::test_array_key_array_false() in the database unit tests.
             //
             // EXAMPLE TABLE "test_table_2"
             // ===============================
             //  col_1 | col_2 | col_3 | col_4
             // ===============================
             //    1   |  red  |  dog  | A
             //    2   |  green|  dog  | B
             //    3   |  green|  dog  | C
             //    4   |  green|  dog  | D
             //    5   |  blue |  bird | A
             //    6   |  black|  bird | A
             //    7   |  black|  fish | A
             //    8   |  black|  fish | B
             //
             // UNIQUE KEY no_duplicates(col_2, col_3, col_4)
             //
             // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_2, "col_3", "col_4")
             // NOTE: "col_1" is excluded because it is not specified in $ctrl["key_col"]
             // RESULT:   array(
             //		    "dog" =>array(
             //				    "red"=>	array("A"=>"false"),
             //				    "green"=>	array("B"=>"false","C"=>"false","D"=>"false")
             //		    ),
             //		    "bird" =>array(
             //				    "blue"=>	array("A"=>"false"),
             //				    "black"=>	array("A"=>"false")
             //		    ),
             //		    "fish" =>array(
             //				    "black"=>	array("A"=>"false","B"=>"false")
             //		    )
             //	     )
         // ARRAY_KEY_ARRAY_FALSE
         // =============================================================================
         //
         // Returns results as an array of arrays^N-1, where the array key names and heirarchy
         // are set based on the contents of the $key_col array. Results in the last db column
         // specified in $key_col are grouped together in an result-keyed array where the key
         // name is the column's value in the database row and the key's value is (bool)false.
         // For a working example of how to use this result formatter, see the function
         // database_resultFormatters::test_array_key_array_false() in the database unit tests.
         //
         // EXAMPLE TABLE "test_table_2"
         // ===============================
         //  col_1 | col_2 | col_3 | col_4
         // ===============================
         //    1   |  red  |  dog  | A
         //    2   |  green|  dog  | B
         //    3   |  green|  dog  | C
         //    4   |  green|  dog  | D
         //    5   |  blue |  bird | A
         //    6   |  black|  bird | A
         //    7   |  black|  fish | A
         //    8   |  black|  fish | B
         //
         // UNIQUE KEY no_duplicates(col_2, col_3, col_4)
         //
         // EXAMPLE: "SELECT * FROM test_table" + $ctrl["key_col"] = array("col_2, "col_3", "col_4")
         // NOTE: "col_1" is excluded because it is not specified in $ctrl["key_col"]
         // RESULT:   array(
         //		    "dog" =>array(
         //				    "red"=>	array("A"=>"false"),
         //				    "green"=>	array("B"=>"false","C"=>"false","D"=>"false")
         //		    ),
         //		    "bird" =>array(
         //				    "blue"=>	array("A"=>"false"),
         //				    "black"=>	array("A"=>"false")
         //		    ),
         //		    "fish" =>array(
         //				    "black"=>	array("A"=>"false","B"=>"false")
         //		    )
         //	     )
         case "array_key_array_false":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 9, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "RAW, format = array_key_array_false";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_key_array_false";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 foreach ($data as $row) {
                     // Since there is no functionality in PHP for creating a new array key
                     // based on a name stored in a variable ( $$ variable variable syntax does
                     // not work for multidimensional arrays), we have to build a string of PHP
                     // code and use eval() to run it
                     $eval_str = "\$result";
                     foreach ($ctrl["key_col"] as $keyname) {
                         $eval_str .= '["' . $row->{$keyname} . '"]';
                     }
                     $eval_str .= " = false;";
                     // Run the PHP string we have built
                     eval($eval_str);
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nFORMATTED, format = array_key_array_false";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // ARRAY_KEY_SINGLE
             // =============================================================================
             // Returns results as an array of ints or strings, where the array key names
             // are set based on the contents of a database column.
             //
             // EXAMPLE: "SELECT col_2, col_3 FROM test_table" + $ctrl["key_col"]="col_2", $ctrl["val_col"]="col_3"
             // RESULT:   array(
             //		     "red"=>"dog",
             //		     "green"=>"cat",
             //		     "blue"=>"bird",
             //		     "black"=>"fish"
             //	     )
         // ARRAY_KEY_SINGLE
         // =============================================================================
         // Returns results as an array of ints or strings, where the array key names
         // are set based on the contents of a database column.
         //
         // EXAMPLE: "SELECT col_2, col_3 FROM test_table" + $ctrl["key_col"]="col_2", $ctrl["val_col"]="col_3"
         // RESULT:   array(
         //		     "red"=>"dog",
         //		     "green"=>"cat",
         //		     "blue"=>"bird",
         //		     "black"=>"fish"
         //	     )
         case "array_key_single":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 10, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "RAW, format = array_key_single\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_key_single\n";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 foreach ($data as $row) {
                     $result[$row->{$ctrl["key_col"]}] = $row->{$ctrl["val_col"]};
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nCAST, format = array_key_single\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // ARRAY_OBJECT
             // =============================================================================
             // Returns results as an array of objects, where the primary array keys are
             // zero-indexed ints
             //
             // EXAMPLE: "SELECT * FROM test_table"
             // RESULT:   array(
             //		    stdClass( "col_1"->1, "col_2"->"red", "col_3"->"dog", "col_4"->"big"),
             //		    stdClass( "col_1"->2, "col_2"->"green", "col_3"->"cat", "col_4"->"med"),
             //		    stdClass( "col_1"->3, "col_2"->"blue", "col_3"->"bird", "col_4"->"small"),
             //		    stdClass( "col_1"->4, "col_2"->"black", "col_3"->"fish", "col_4"->"tiny"),
             //	     )
         // ARRAY_OBJECT
         // =============================================================================
         // Returns results as an array of objects, where the primary array keys are
         // zero-indexed ints
         //
         // EXAMPLE: "SELECT * FROM test_table"
         // RESULT:   array(
         //		    stdClass( "col_1"->1, "col_2"->"red", "col_3"->"dog", "col_4"->"big"),
         //		    stdClass( "col_1"->2, "col_2"->"green", "col_3"->"cat", "col_4"->"med"),
         //		    stdClass( "col_1"->3, "col_2"->"blue", "col_3"->"bird", "col_4"->"small"),
         //		    stdClass( "col_1"->4, "col_2"->"black", "col_3"->"fish", "col_4"->"tiny"),
         //	     )
         case "array_object":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 11, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "RAW, format = array_object\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $result = $sql_result;
             } else {
                 $result = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_object\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($this->print_result_formatted == true) {
                 ob_start();
                 print_r($result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             break;
             // ARRAY_ARRAY
             // =============================================================================
             // Returns results as an array of arrays, where the primary array keys are
             // zero-indexed ints
             //
             // EXAMPLE: "SELECT * FROM test_table"
             // RESULT:   array(
             //		    array( "col_1"=>1, "col_2"=>"red", "col_3"=>"dog", "col_4"=>"big"),
             //		    array( "col_1"=>2, "col_2"=>"green", "col_3"=>"cat", "col_4"=>"med"),
             //		    array( "col_1"=>3, "col_2"=>"blue", "col_3"=>"bird", "col_4"=>"small"),
             //		    array( "col_1"=>4, "col_2"=>"black", "col_3"=>"fish", "col_4"=>"tiny"),
             //	     )
         // ARRAY_ARRAY
         // =============================================================================
         // Returns results as an array of arrays, where the primary array keys are
         // zero-indexed ints
         //
         // EXAMPLE: "SELECT * FROM test_table"
         // RESULT:   array(
         //		    array( "col_1"=>1, "col_2"=>"red", "col_3"=>"dog", "col_4"=>"big"),
         //		    array( "col_1"=>2, "col_2"=>"green", "col_3"=>"cat", "col_4"=>"med"),
         //		    array( "col_1"=>3, "col_2"=>"blue", "col_3"=>"bird", "col_4"=>"small"),
         //		    array( "col_1"=>4, "col_2"=>"black", "col_3"=>"fish", "col_4"=>"tiny"),
         //	     )
         case "array_array":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 12, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "RAW, format = array_array\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_array\n";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 foreach ($data as $row) {
                     $arr = array();
                     // Convert row object into array
                     foreach ($row as $key => $value) {
                         $arr[$key] = $value;
                     }
                     // Insert row array into primary array as unnamed key
                     $result[] = $arr;
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nFORMATTED, format = array_array\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // ARRAY_ARRAY_OFFSET
             // =============================================================================
             // Returns results as an array of arrays, where the primary array keys are
             // zero-indexed ints, and the secondary array keys are the offset of the
             // column in the table definition array
             //
             // EXAMPLE: "SELECT * FROM test_table"
             // RESULT:   array(
             //		    array( 1, "red", "dog", "big"),
             //		    array( 2, "green", "cat", "med"),
             //		    array( 3, "blue", "bird", "small"),
             //		    array( 4, "black", "fish", "tiny"),
             //	     )
         // ARRAY_ARRAY_OFFSET
         // =============================================================================
         // Returns results as an array of arrays, where the primary array keys are
         // zero-indexed ints, and the secondary array keys are the offset of the
         // column in the table definition array
         //
         // EXAMPLE: "SELECT * FROM test_table"
         // RESULT:   array(
         //		    array( 1, "red", "dog", "big"),
         //		    array( 2, "green", "cat", "med"),
         //		    array( 3, "blue", "bird", "small"),
         //		    array( 4, "black", "fish", "tiny"),
         //	     )
         case "array_array_offset":
             try {
                 $sql_result = $this->driver->get_results($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 12, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "RAW, format = array_array_offset\n";
                 print_r($sql_result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             if ($this->disable_typecast_read == true) {
                 $data = $sql_result;
             } else {
                 $data = $cast->queryResult($format = "array_object", $sql_result, $query["types"]);
                 if ($this->print_result_cast == true) {
                     ob_start();
                     echo "\nCAST, format = array_array_offset\n";
                     print_r($data);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
             }
             if ($data) {
                 $result = array();
                 foreach ($data as $row) {
                     $arr = array();
                     // Convert row object into array
                     foreach ($row as $key => $value) {
                         $arr[] = $value;
                     }
                     // Insert row array into primary array as unnamed key
                     $result[] = $arr;
                 }
                 if ($this->print_result_formatted == true) {
                     ob_start();
                     echo "\nFORMATTED, format = array_array_offset\n";
                     print_r($result);
                     $out = ob_get_clean();
                     FOX_debug::addToFile($out);
                 }
                 unset($data);
                 // Reduce memory usage
             }
             break;
             // RAW
             // =============================================================================
             // Runs a default SQL query. Returned result format depends on the query.
         // RAW
         // =============================================================================
         // Runs a default SQL query. Returned result format depends on the query.
         case "raw":
             try {
                 $result = $this->driver->query($sql);
             } catch (FOX_exception $child) {
                 throw new FOX_exception(array('numeric' => 13, 'text' => "Error in database driver", 'data' => array('query' => $query, 'sql' => $sql), 'file' => __FILE__, 'line' => __LINE__, 'method' => __METHOD__, 'child' => $child));
             }
             if ($this->print_result_raw == true) {
                 ob_start();
                 echo "format = null\n";
                 print_r($result);
                 $out = ob_get_clean();
                 FOX_debug::addToFile($out);
             }
             break;
         default:
             throw new FOX_exception(array('numeric' => 14, 'text' => "Invalid query runner format", 'data' => array('faulting_format' => $ctrl["format"], "query" => $query, "ctrl" => $ctrl), 'file' => __FILE__, 'class' => __CLASS__, 'function' => __FUNCTION__, 'line' => __LINE__, 'child' => null));
     }
     // END switch($ctrl["format"])
     return $result;
 }
Example #13
0
 /**
  * Lofts a flat matrix into a trie structure, while hashing its keys
  *
  * @version 1.0
  * @since 1.0
  *
  * @param array $rows | Flat matrix
  * @param array $columns | Array of column names
  * @param array $ctrl | Control args
  * 
  * @return array | Exception on failure. Flattened trie structure on success.
  */
 public static function loftMatrixHash($rows, $columns, &$hash_table, $ctrl = null)
 {
     $ctrl_default = array('null_token' => '*');
     $ctrl = FOX_sUtil::parseArgs($ctrl, $ctrl_default);
     $result = array();
     // If a single column name is passed as a string, use the more efficient
     // direct assignment algorithm to build a 1 level trie
     if (!is_array($columns)) {
         foreach ($rows as $row) {
             // Convert row object into array
             foreach ($row as $tokens) {
                 $result[$hash_table->set($tokens[$columns])] = true;
             }
             unset($tokens);
         }
         unset($row);
     } else {
         foreach ($rows as $row) {
             // Since there is no functionality in PHP for creating a new array key
             // based on a name stored in a variable ( $$ variable variable syntax does
             // not work for multidimensional arrays), we have to build a string of PHP
             // code and use eval() to run it
             $eval_str = "\$result";
             foreach ($columns as $keyname) {
                 if (FOX_sUtil::keyExists($keyname, $row)) {
                     $eval_str .= '["' . $hash_table->set($row[$keyname]) . '"]';
                 } else {
                     $eval_str .= '["' . $ctrl['null_token'] . '"]';
                 }
             }
             unset($keyname);
             $eval_str .= " = true;";
             // Run the PHP string we have built
             eval($eval_str);
         }
         unset($row);
     }
     return $result;
 }
 public function __construct($args = null)
 {
     // Handle dependency-injection
     // ===========================================================
     // NOTE: Memcached's flush() has one-second granularity. It only affects items
     // set a minimum of 1 second before it, and it could affect items set for up to
     // one second after it. This it probably in Memcached's implementation to handle
     // network latency across multiple servers, and would never be a problem in production
     // because the only time a site would dump the *entire* cache is on a server reboot.
     // @see http://ca2.php.net/manual/en/memcache.flush.php
     // However, its a HUGE issue during unit testing when the cache has to be flushed
     // between every test fixture ...potentially hundreds of times a second, and the unit
     // tests are usually run against a SINGLE memcached instance. As such, the unit tests
     // usually set this value to almost zero. If you experience problems with the memcached
     // test fixture on your system, you may need to increase the 'flush_propagation_delay'
     // parameter
     $args_default = array('max_offset' => 2147483646, 'servers' => array(array('ip' => '127.0.0.1', 'port' => 11211, 'persist' => false, 'weight' => 100)), 'compress_threshold' => 0.2, 'flush_propagation_delay' => 1200000, 'set_propagation_delay' => 0);
     $args = FOX_sUtil::parseArgs($args, $args_default);
     foreach ($args as $key => $var) {
         $this->{$key} = $var;
     }
     unset($key, $var);
     // Handle process-id binding
     // ===========================================================
     if (FOX_sUtil::keyExists('process_id', $args)) {
         // Binding to a reference is important. It makes the cache engine $process_id
         // update if the FOX_mCache is changed, which we do during unit testing.
         $this->process_id =& $args['process_id'];
     } else {
         global $fox;
         $this->process_id = $fox->process_id;
     }
     // CASE 1: Try for the "Memcached" extension, which is the fastest and
     // has the most advanced features.
     // =======================================================================
     $this->has_libs = false;
     if (class_exists("Memcached") && $this->use_full == true) {
         $this->has_libs = true;
         $this->engine = new Memcached();
         $active_servers = $this->engine->getServerList();
         if (count($active_servers) == 0) {
             $formatted_servers = array();
             foreach ($this->servers as $server) {
                 $temp = array($server['ip'], $server['port'], $server['weight']);
                 $formatted_servers[] = $temp;
             }
             unset($server);
             $this->engine->addServers($formatted_servers);
         }
         $this->engine->setCompressThreshold($this->compress_threshold);
         $this->mode = 'full';
         if ($this->enable == true) {
             $this->is_active = true;
         }
     } elseif (class_exists("Memcache") && $this->use_basic == true) {
         $this->has_libs = true;
         $this->engine = new Memcache();
         foreach ($this->servers as $server) {
             $this->engine->addServer($server['ip'], $server['port'], $server['persist']);
         }
         unset($server);
         $this->engine->setCompressThreshold($this->compress_threshold);
         $this->mode = 'basic';
         if ($this->enable == true) {
             $this->is_active = true;
         }
     } elseif ($this->use_portable == true) {
         require dirname(__FILE__) . '/class.portable.memcached.php';
         $this->has_libs = true;
         $this->engine = new FOX_memcached_portable();
         $this->mode = 'portable';
         if ($this->enable == true) {
             $this->is_active = true;
         }
     }
 }