Ticket Details

Added Geospatial feature to MySQL adapter, as well as reversing the formatter pattern

ENHANCEMENT Ticket (pending)

This patch adds POINT type to MySQL, and translates it automatically between native MySQL and array(X,Y).   It also converts things like 'boolean' to real PHP boolean types (instead of "0"). 

{{{
diff --git a/libraries/lithium/data/source/database/adapter/MySql.php b/libraries/lithium/data/source/database/adapter/MySql.php
index f578627..6d6583c 100644
--- a/libraries/lithium/data/source/database/adapter/MySql.php
+++ b/libraries/lithium/data/source/database/adapter/MySql.php
@@ -21,14 +21,15 @@ class MySql extends \lithium\data\source\Database {
 		'primary_key' => array('name' => 'NOT NULL AUTO_INCREMENT'),
 		'string' => array('name' => 'varchar', 'length' => 255),
 		'text' => array('name' => 'text'),
-		'integer' => array('name' => 'int', 'length' => 11, 'formatter' => 'intval'),
-		'float' => array('name' => 'float', 'formatter' => 'floatval'),
-		'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
+		'integer' => array('name' => 'int', 'length' => 11, 'formatter' => 'intval','phpizer'=>'intval'),
+		//'point' => array('name'=>'point','formatter'=> function(){}), //defined below
+		'float' => array('name' => 'float', 'formatter' => 'floatval','phpizer'=>'floatval'),
+		'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date','phpizer'=>'strtotime'),
 		'timestamp' => array(
-			'name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'
+			'name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'//,'phpizer'=>'strtotime'
 		),
-		'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'),
-		'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'),
+		'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date','phpizer'=>'strtotime'),
+		'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date','phpizer'=>'strtotime'),
 		'binary' => array('name' => 'blob'),
 		'boolean' => array('name' => 'tinyint', 'length' => 1)
 	);
@@ -70,6 +71,11 @@ class MySql extends \lithium\data\source\Database {
 	public function __construct(array $config = array()) {
 		$defaults = array('port' => '3306', 'encoding' => null);
 		parent::__construct($config + $defaults);
+
+
+                $this->_columns['point'] = array('name'=>'point','phpizer'=> function($point){list($X,$Y)=explode('|',$point); return compact('X','Y');});
+                $this->_columns['boolean'] = $this->_columns['boolean'] + array('phpizer'=> function($bool){return $bool=='1';});
+
 	}
 
 	/**
@@ -212,7 +218,6 @@ class MySql extends \lithium\data\source\Database {
 		if (!is_resource($resource)) {
 			return null;
 		}
-
 		switch ($type) {
 			case 'next':
 				$result = mysql_fetch_row($resource);
@@ -223,9 +228,40 @@ class MySql extends \lithium\data\source\Database {
 			break;
 			default:
 				$result = parent::result($type, $resource, $context);
+                        
 			break;
 		}
-		return $result;
+               if(!empty($context) && !empty($result)){
+                  $meta = $context->meta();
+                  $model = $meta['model'];
+                  $schema = $model::schema();
+                  
+                  $cnt=0;
+                  foreach($schema as $columnSchema){;
+                      if(isset($this->_columns[$columnSchema['type']])){
+
+                      
+                      $column=$this->_columns[$columnSchema['type']];
+                      if(isset($column['phpizer'])){
+                                $formatter=$column['phpizer'];
+                                if(isset($column['phpizer_format'])){
+                                    $result[$cnt]=$formatter($result[$cnt],$column['phpizer_format']);
+                                }else{
+                                    $result[$cnt]=$formatter($result[$cnt]);
+                                }
+                            }
+                          //  var_dump($columnSchema['type'],$result[$cnt]);
+                      }
+                      $cnt++;
+                  }
+
+                  
+
+                 // */
+               }
+               
+              
+                return $result;
 	}
 
 	/**
@@ -237,10 +273,20 @@ class MySql extends \lithium\data\source\Database {
 	 * @return mixed Value with converted type.
 	 */
 	public function value($value, array $schema = array()) {
-		if (is_array($value)) {
+                //handle special MySQL features
+                if(isset($schema['type']))
+		switch($schema['type']){
+                    case 'point':
+                        if(is_array($value)){
+                            return "PointFromText('POINT({$value['X']} {$value['Y']})')";
+                        }
+                }
+
+                if (is_array($value)) {
 			return parent::value($value, $schema);
 		}
-		$result = parent::value($value, $schema);;
+               
+                $result = parent::value($value, $schema);;
 
 		if (is_string($result)) {
 			return "'" . mysql_real_escape_string($value, $this->connection) . "'";
@@ -335,7 +381,7 @@ class MySql extends \lithium\data\source\Database {
 			$column = mysql_fetch_field($results, $j);
 			$name = $column->name;
 			$table = $column->table;
-			$this->map[$index++] = empty($table) ? array(0, $name) : array($table, $name);
+                        $this->map[$index++] = empty($table) ? array(0, $name) : array($table, $name);
 			$j++;
 		}
 	}
@@ -374,12 +420,13 @@ class MySql extends \lithium\data\source\Database {
 		$column = array_intersect_key($column, array('type' => null, 'length' => null));
 
 		switch (true) {
-			case in_array($column['type'], array('date', 'time', 'datetime', 'timestamp')):
+			case in_array($column['type'], array('date', 'time', 'datetime', 'timestamp','point')):
 				return $column;
 			case ($column['type'] == 'tinyint' && $column['length'] == '1'):
 			case ($column['type'] == 'boolean'):
 				return array('type' => 'boolean');
 			break;
+
 			case (strpos($column['type'], 'int') !== false):
 				$column['type'] = 'integer';
 			break;
@@ -399,9 +446,35 @@ class MySql extends \lithium\data\source\Database {
 				$column['type'] = 'text';
 			break;
 		}
+			//var_dump($real,$column);echo "<br>";
 		return $column;
 	}
-
+        /**
+	 * Returns
+	 *
+	 * @param string $fields
+	 * @param string $context
+	 * @return void
+	 */
+	public function fields($fields, $context) {
+            if($context->type()=='read'){
+            $fields = array();
+            $model = $context->model();
+            $schema= $model::schema();
+            foreach($schema as $name => $column){
+                switch($column['type']){
+                    case 'point':
+                        $fields[]="CONCAT(X(`{$name}`),'|',Y(`{$name}`)) as `{$name}`";
+                        break;
+                    default:
+                        $fields[]="`{$name}`";
+                }
+            }
+            return implode(', ',$fields);
+            }
+            return parent::fields();
+
+        }
 	/**
 	 * Helper method that retrieves an entity's name via its metadata.
 	 *
@@ -416,4 +489,4 @@ class MySql extends \lithium\data\source\Database {
 	}
 }
 
-?>
\ No newline at end of file
+?>
}}}
on 06.08.10 reported by: thelonecabbage

Updates