SyBase con Kumbia

Un grupo de programadores estamos por empezar a desarrollar una aplicacion web utilizando el framework de kumbia, solo que tenemos como premisa que la base de datos a utilizar fue creada bajo SyBase. Ahora creemos que la solucion optima es modificar alguno de los archivos de configuracion de kumbia para que trabaje con sybase igual como lo hace con mysql. Ahora no sabemos si ya existe dicho patch. Que opinan? que nos aconsejan que podemos utilizar o cambiar? tienen algun metodo de trabajo o estandar? porque vemos que ya para la version 0.5 RC3 incorporan Oracle... Gracias de antemano!

Comentarios

  • La idea en este caso es que crees un adaptador, como? bien te explico un poco... kumbia tiene una interfaz library/kumbia/db/interfaz.php que se definen los métodos implementados por el adaptador en si, la idea es que te ayudes con los que ya existen puedes ver el de Mysql o Postgres por ejemplo, si te das cuenta existe para todos los adaptadores un método llamado connect() y que este de acuerdo al adaptador se comporta de una manera en postgres es pg_connet la implementación y en mysql es mysq_connect así puedes hacer con el Manejador de BD que utilizas, con solo hacer y llamar al archivo que implementa todos los estos métodos por ejemplo el archivo del adaptador de Mysql es mysql.php y la clase se llama DbMySQL esto es parte de las convencciones, para que tu adaptador se inicie de forma automática mediante kumbia y utilizar las bondades de ActiveRecord...

    Cualquier duda estamos a la orden!

    Éxito!

    P.D: si lo terminan lo podemos incluir al SVN como parte de un adaptador mas soportado...
  • edited 11:05
    Hemos estado trabajando en el tema en cuestion aniadimos u archivo llamado sybase.php al directorio "/library/kumbia/db/adapters", el cualcontiene este codigo:
    <?php
    /**
     * Kumbia PHP Framework
     *
     * LICENSE
     *
     * This source file is subject to the GNU/GPL that is bundled
     * with this package in the file docs/LICENSE.txt.
     * It is also available through the world-wide-web at this URL:
     * http://www.kumbia.org/license.txt
     * If you did not receive a copy of the license and are unable to
     * obtain it through the world-wide-web, please send an email
     * to kumbia@kumbia.org so we can send you a copy immediately.
     *
     * @category Kumbia
     * @package Db
     * @subpackage Adapters
     * @copyright Copyright (c) 2005-2007 Andres Felipe Gutierrez (andresfelipe at vagoogle.net)
     * @copyright Copyright (c) 2007-2008 Emilio Rafael Silveira Tovar (emilio.rst at gmail.com)
     * @license http://www.kumbia.org/license.txt GNU/GPL
     */
    
    /**
     * MySQL Database Support
     *
     * Estas funciones le permiten acceder a servidores de bases de datos MySQL.
     * Puede encontrar m�s informaci�n sobre MySQL en http://www.mysql.com/.
     * La documentaci�n de MySQL puede encontrarse en http://dev.mysql.com/doc/.
     *
     * @category Kumbia
     * @package Db
     * @subpackage Adapters
     * @copyright Copyright (c) 2005-2007 Andres Felipe Gutierrez (andresfelipe at vagoogle.net)
     * @copyright Copyright (c) 2008-2008 Emilio Rafael Silveira Tovar (emilio.rst at gmail.com)
     * @license http://www.kumbia.org/license.txt GNU/GPL
     * @link http://www.php.net/manual/es/ref.mysql.php
     * @access Public
     *
     */
    class DbSyBase extends DbBase implements DbBaseInterface  {
    
    	/**
    	 * Resource de la Conexion a MySQL
    	 *
    	 * @var resource
    	 */
    	public $id_connection;
    
    	/**
    	 * Ultimo Resultado de una Query
    	 *
    	 * @var resource
    	 */
    	public $last_result_query;
    
    	/**
    	 * Ultima sentencia SQL enviada a MySQL
    	 *
    	 * @var string
    	 */
    	private $last_query;
    
    	/**
    	 * Ultimo error generado por MySQL
    	 *
    	 * @var string
    	 */
    	public $last_error;
    
    	/**
    	 * Resultado de Array Asociativo
    	 *
    	 */
    	const DB_ASSOC = SYBASE_ASSOC;
    
    	/**
    	 * Resultado de Array Asociativo y Numerico
    	 *
    	 */
    	const DB_BOTH = SYBASE_BOTH;
    
    	/**
    	 * Resultado de Array Numerico
    	 *
    	 */
    	const DB_NUM = SYBASE_NUM;
    
    	/**
    	 * Tipo de Dato Integer
    	 *
    	 */
    	const TYPE_INTEGER = "INTEGER";
    
    	/**
    	 * Tipo de Dato Date
    	 *
    	 */
    	const TYPE_DATE = "DATE";
    
    	/**
    	 * Tipo de Dato Varchar
    	 *
    	 */
    	const TYPE_VARCHAR = "VARCHAR";
    
    	/**
    	 * Tipo de Dato Decimal
    	 *
    	 */
    	const TYPE_DECIMAL = "DECIMAL";
    
    	/**
    	 * Tipo de Dato Datetime
    	 *
    	 */
    	const TYPE_DATETIME = "DATETIME";
    
    	/**
    	 * Tipo de Dato Char
    	 *
    	 */
    	const TYPE_CHAR = "CHAR";
    
    	/**
    	 * Hace una conexión a la base de datos de MySQL
    	 *
    	 * @param string $dbhost
    	 * @param string $dbuser
    	 * @param string $dbpass
    	 * @param string $dbname
    	 * @param string $dbport
    	 * @param string $dbdsn
    	 * @return resource_connection
    	 */
    	public function connect($dbhost='', $dbuser='', $dbpass='', $dbname='', $dbport=5000, $dbdsn=''){
    	
    		if(!extension_loaded('sybase')){
    			throw new DbException('Debe cargar la extensión de PHP llamada php_sybase');
    			return false;
    		}
    		if(!$dbport) $dbport = 5000;
    		
    		if($this->id_connection = @sybase_connect(&;quot;{$dbhost}:{$dbport}", $dbuser, $dbpass, true)){
    			if($dbname!=='') {
    				if(!sybase_select_db($dbname, $this->id_connection)){
    					throw new DbException($this->error(), $this->no_error(), false);
    					return false;
    				} else {
    					$this->db_name = $dbname;
    				}
    			}
    			return true;
    		} else {
    			throw new DbException($this->error(), $this->no_error(), false);
    			return false;
    		}
    
    	}
    
    	/**
    	 * Efectua operaciones SQL sobre la base de datos
    	 *
    	 * @param string $sqlQuery
    	 * @return resource or false
    	 */
    	public function query($sql_query){
    		$this->debug($sql_query);
    		$this->log($sql_query, Logger::DEBUG);
    		if(!$this->id_connection){
    			$this->connect();
    			if(!$this->id_connection){
    				return false;
    			}
    		}
    
    		$this->last_query = $sql_query;
    		if($result_query = sybase_query($sql_query, $this->id_connection)){
    			$this->last_result_query = $result_query;
    			return $result_query;
    		} else {
    			$this->last_result_query = false;
    			throw new DbException($this->error(" al ejecutar <i>\"$sql_query\"</i>"), $this->no_error());
    			return false;
    		}
    	}
    
    	/**
    	 * Cierra la Conexi�n al Motor de Base de datos
    	 */
    	public function close(){
    		if($this->id_connection) {
    			return sybase_close();
    		}
    		return false;
    	}
    
    	/**
    	 * Devuelve fila por fila el contenido de un select
    	 *
    	 * @param resource $result_query
    	 * @param integer $opt
    	 * @return array
    	 */
    	public function fetch_array($result_query='', $opt=''){
    		if($opt==='') {
    			$opt = db::DB_BOTH;
    		}
    		if(!$this->id_connection){
    			return false;
    		}
    		if(!$result_query){
    			$result_query = $this->last_result_query;
    			if(!$result_query){
    				return false;
    			}
    		}
    		return sybase_fetch_array($result_query, $opt);
    	}
    
    	/**
    	 * Constructor de la Clase
    	 */
    	public function __construct($dbhost=null, $dbuser=null, $dbpass=null, $dbname='', $dbport='', $dbdsn=''){
    		$this->connect($dbhost, $dbuser, $dbpass, $dbname, $dbport, $dbdsn);
    	}
    
    	/**
    	 * Devuelve el numero de filas de un select
    	 */
    	public function num_rows($result_query=''){
    		if(!$this->id_connection){
    			return false;
    		}
    		if(!$result_query){
    			$result_query = $this->last_result_query;
    			if(!$result_query){
    				return false;
    			}
    		}
    		if(($number_rows = sybase_num_rows($result_query))!==false){
    			return $number_rows;
    		} else {
    			throw new DbException($this->error(), $this->no_error());
    			return false;
    		}
    		return false;
    	}
    
    	/**
    	 * Devuelve el nombre de un campo en el resultado de un select
    	 *
    	 * @param integer $number
    	 * @param resource $result_query
    	 * @return string
    	 */
    	public function field_name($number, $result_query=''){
    /*		if(!$this->id_connection){
    			return false;
    		}
    		if(!$result_query){
    			$result_query = $this->last_result_query;
    			if(!$result_query){
    				return false;
    			}
    		}
    		if(($fieldName = mysql_field_name($result_query, $number))!==false){
    			return $fieldName;
    		} else {
    			throw new DbException($this->error(), $this->no_error());
    			return false;
    		}
    		return false;
    */	}
    
    
    	/**
    	 * Se Mueve al resultado indicado por $number en un select
    	 *
    	 * @param integer $number
    	 * @param resource $result_query
    	 * @return boolean
    	 */
    	public function data_seek($number, $result_query=''){
    		if(!$result_query){
    			$result_query = $this->last_result_query;
    			if(!$result_query){
    				return false;
    			}
    		}
    		if(($success = sybase_data_seek($result_query, $number))!==false){
    			return $success;
    		} else {
    			throw new DbException($this->error(), $this->no_error());
    			return false;
    		}
    		return false;
    	}
    
    	/**
    	 * Numero de Filas afectadas en un insert, update o delete
    	 *
    	 * @param resource $result_query
    	 * @return integer
    	 */
    	public function affected_rows($result_query=''){
    		if(($numberRows = sybase_affected_rows())!==false){
    			return $numberRows;
    		} else {
    			$this->lastError = $this->error();
    			throw new DbException($this->error(), $this->no_error());
    			return false;
    		}
    		return false;
    	}
    
    	/**
    	 * Devuelve el error de MySQL
    	 *
    	 * @return string
    	 */
    	public function error($err=''){
    		if(!$this->id_connection){
    			$this->last_error = sybase_get_last_message() ? sybase_get_last_message() : "[Error Desconocido en MySQL: $err]";
    			$this->log($this->last_error, Logger::ERROR);
    			return $this->last_error;
    		}
    		$this->last_error = sybase_get_last_message() ? sybase_get_last_message() : "[Error Desconocido en MySQL: $err]";
    		$this->last_error.= $err;
    		$this->log($this->last_error, Logger::ERROR);
    		return $this->last_error;
    	}
    
    	/**
    	 * Devuelve el no error de MySQL
    	 *
    	 * @return integer
    	 */
    	public function no_error(){
    /*		if(!$this->id_connection){
    			return false;
    		}
    		return mysql_errno();
    */	}
    
    	/**
    	 * Devuelve el ultimo id autonumerico generado en la BD
    	 *
    	 * @return integer
    	 */
    	public function last_insert_id($table='', $primary_key=''){
    		if(!$this->id_connection){
    			return false;
    		}
    		return sybase_get_last_message($this->id_connection);
    	}
    
    	/**
    	 * Verifica si una tabla existe o no
    	 *
    	 * @param string $table
    	 * @return boolean
    	 */
    	public function table_exists($table, $schema=''){
    		$table = addslashes("$table");
    		if($schema==''){
    			$num = $this->fetch_one("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '$table'");
    		} else {
    			$schema = addslashes("$schema");
    			$num = $this->fetch_one("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '$table' AND TABLE_SCHEMA = '$schema'");
    		}
    		return $num[0];
    	}
    
    	/**
    	 * Devuelve un LIMIT valido para un SELECT del RBDM
    	 *
    	 * @param string $sql consulta sql
    	 * @return string
    	 */
    	public function limit($sql){
    		$params = get_params(func_get_args());
    		$sql_new = $sql;
    	
    		if(isset($params['limit']) && is_numeric($params['limit'])){
    			$sql_new.=" LIMIT $params[limit]";
    		}
    		
    		if(isset($params['offset']) && is_numeric($params['offset'])){
    			$sql_new.=" OFFSET $params[offset]";
    		}
    		
    		return $sql_new;
    	}
    
    	/**
    	 * Borra una tabla de la base de datos
    	 *
    	 * @param string $table
    	 * @return boolean
    	 */
    	public function drop_table($table, $if_exists=true){
    		if($if_exists){
    			return $this->query("DROP TABLE IF EXISTS $table");
    		} else {
    			return $this->query("DROP TABLE $table");
    		}
    	}
    
    	/**
    	 * Crea una tabla utilizando SQL nativo del RDBM
    	 *
    	 * TODO:
    	 * - Falta que el parametro index funcione. Este debe listar indices compuestos multipes y unicos
    	 * - Agregar el tipo de tabla que debe usarse (MySQL)
    	 * - Soporte para campos autonumericos
    	 * - Soporte para llaves foraneas
    	 *
    	 * @param string $table
    	 * @param array $definition
    	 * @return boolean
    	 */
    	public function create_table($table, $definition, $index=array()){
    /*		$create_sql = "CREATE TABLE $table (";
    		if(!is_array($definition)){
    			new DbException("Definición invalida para crear la tabla '$table'");
    			return false;
    		}
    		$create_lines = array();
    		$index = array();
    		$unique_index = array();
    		$primary = array();
    		$not_null = "";
    		$size = "";
    		foreach($definition as $field => $field_def){
    			if(isset($field_def['not_null'])){
    				$not_null = $field_def['not_null'] ? 'NOT NULL' : '';
    			} else {
    				$not_null = "";
    			}
    			if(isset($field_def['size'])){
    				$size = $field_def['size'] ? '('.$field_def['size'].')' : '';
    			} else {
    				$size = "";
    			}
    			if(isset($field_def['index'])){
    				if($field_def['index']){
    					$index[] = "INDEX(`$field`)";
    				}
    			}
    			if(isset($field_def['unique_index'])){
    				if($field_def['unique_index']){
    					$index[] = "UNIQUE(`$field`)";
    				}
    			}
    			if(isset($field_def['primary'])){
    				if($field_def['primary']){
    					$primary[] = "`$field`";
    				}
    			}
    			if(isset($field_def['auto'])){
    				if($field_def['auto']){
    					$field_def['extra'] = isset($field_def['extra']) ? $field_def['extra']." AUTO_INCREMENT" :  "AUTO_INCREMENT";
    				}
    			}
    			if(isset($field_def['extra'])){
    				$extra = $field_def['extra'];
    			} else {
    				$extra = "";
    			}
    			$create_lines[] = "`$field` ".$field_def['type'].$size.' '.$not_null.' '.$extra;
    		}
    		$create_sql.= join(',', $create_lines);
    		$last_lines = array();
    		if(count($primary)){
    			$last_lines[] = 'PRIMARY KEY('.join(",", $primary).')';
    		}
    		if(count($index)){
    			$last_lines[] = join(',', $index);
    		}
    		if(count($unique_index)){
    			$last_lines[] = join(',', $unique_index);
    		}
    		if(count($last_lines)){
    			$create_sql.= ','.join(',', $last_lines).')';
    		}
    		return $this->query($create_sql);
    
    */	}
    
    	/**
    	 * Listar las tablas en la base de datos
    	 *
    	 * @return array
    	 */
    	public function list_tables(){
    		return $this->fetch_all("SHOW TABLES");
    	}
    
    	/**
    	 * Listar los campos de una tabla
    	 *
    	 * @param string $table
    	 * @return array
    	 */
    	public function describe_table($table, $schema=''){
    		if($schema==''){
    			return $this->fetch_all("DESCRIBE `$table`");
    		} else {
    			return $this->fetch_all("DESCRIBE `$schema`.`$table`");
    		}
    	}
    
    }
    
    ?>
    

    y nos aparece este error al tratar de montar la base de datos

    errorK.png
    http://bipolar.com.ve/errorK.png
  • Veo que el problema es con la carga de la extensión, se me vienen dos preguntas...
      1->estas seguro que esa extensión se llama así osea la verificas con
    extension_loaded('sybase') ?[/list:u]
      2->Antes de hacer eso habías hecho prueba desde scripts normales y silvestres tratando de hacer operaciones con ese drivers?[/list:u]
      3->Si la
    respuesta 2 es afirmativa, quita esa validación if(!extension_loaded('sybase')) de la extensión y vuelve hacer las pruebas desde kumbia[/list:u]
  • edited 11:05
    1.- Estamos modificando el archivo mysql.php porque es el que presenta mas conincidencias con sybase en cuanto comandos, solo estamos modificando este archivo y claro que cambiamos los arametros en el archivo environment.ini para que trabaje con este nuevo driver sybase.php
    2.- Hay que modificar o crear algun otro archivo? es decir, registrar que el sybase.php dentro de adapters es un driver nuevo y listo para usar? hay algun archivo de configuracion donde se tenga que "declarar" el nuevo driver??
    3.- Ya probamos los driver nativos que tiene php, cosa que pueden comprobar en esta direccion http://190.198.6.224/info.php
    4.- Ahora vamos a probar comentando la parte de extension_loaded('sybase') ? ,y avisamos...
  • edited 11:05
    Probamos comentando el extension_loaded('sybase') ? y funciona, carga la libreria y monta la base de datos, pero hasta probando no funcionan los query(), ni fetch_array() porque el query() retorna valor 0 lo cual lo sabemos porque la funcion affected_rows() si funciona y retorna 0. Por otra parte el manejo de errores esta perfecto porque nos muestra errores jajajajajajaja! <!-- s:lol: --><img src="{SMILIES_PATH}/icon_lol.gif" alt=":lol:" title="Laughing" /><!-- s:lol: -->

    Este es el trozo de codigo en sybase.php que define query()
    public function query($sql_query){
    		$this-&gt;debug($sql_query);
    		$this-&gt;log($sql_query, Logger&#58;&#58;DEBUG);
    		if(!$this-&gt;id_connection){
    			$this-&gt;connect();
    			if(!$this-&gt;id_connection){
    				return false;
    			}
    		}
    
    		$this-&gt;last_query = $sql_query;
    		if($result_query = sybase_query($sql_query, $this-&gt;id_connection)){
    			$this-&gt;last_result_query = $result_query;
    			return $result_query;
    		} else {
    			$this-&gt;last_result_query = false;
    			throw new DbException($this-&gt;error(&quot; al ejecutar &lt;i&gt;\&quot;$sql_query\&quot;&lt;/i&gt;&quot;), $this-&gt;no_error());
    			return false;
    		}
    	}
    

    El comando nativo de sybase para resolver query es sybase_query(string *query, int id_conection)

    Estamos entusiasmados porque la vaina va caminando... seria ademas un aporte al paquete Kumbia <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->
  • no me queda claro que es lo que funciona correctamente :S
  • edited 11:05
    Lo que funciona bien:
    -affected_rows()
    -connect()
    -menejo de errores

    Lo que no funciona:
    -fetch_array()
    -query()
  • Ummm, bueno bien raro, deberías hacer ciertos print_r a ver si tienes correcto del ID de la conexión, me parece raro ya que si te funcionan los otros métodos...
  • edited 11:05
    La solucion a todos estos problemas es olvidar el asunto... en lugar de esto usar una capa de abstraccion distinta a la propia de kumbia...

    http://adodb.sourceforge.net/
    Esta libreria es perfecta... es mas deberia implementarce como capa de abstraccion propia de kumbia... <!-- s:D --><img src="{SMILIES_PATH}/icon_biggrin.gif" alt=":D" title="Very Happy" /><!-- s:D -->
  • adodb, en comparacion con nuestro ORM es mas complicado, lo interesante es que pudiste resolver... y podras seguir utilizando Kumbia...
  • edited 11:05
    Bueno si, pero no... seguimos utilizando kumbia y no es tan complicado es muy facil implementarlo, trae una serie de ejemplos sencillos... es muy bueno! nos resulto bastante amigable y totalmente compatible con kumbia... <!-- s8) --><img src="{SMILIES_PATH}/icon_cool.gif" alt="8)" title="Cool" /><!-- s8) -->
Sign In or Register to comment.