*
false
.
*/
public function __construct($dsn, $persistent=false)
{
//Cogemos la referencia de la variable de error global
global $g_error;
$this->obj_errorConexion = & $g_error;
//Realizamos la conexión
$this->driver = self::DEFAULT_DRIVER;
if( isset($dsn['driver']) && $dsn['driver']=='pdo' )
{
$this->driver = 'pdo';
}
unset( $dsn['driver'] );
$this->v_dsn = $dsn;
$this->persistent = $persistent;
$this->obj_conexion = null;
} //Fin del constructor
public function __sleep()
{
$this->obj_conexion = null;
return 0;
} //Fin de __sleep
public function __wakeUp()
{
$this->obj_conexion = null;
return 0;
} //Fin de __wakeUp
//destructor
public function __destruct()
{
$desconectar = ( $this->driver=='pdo' ? 'desconectarPDO' : 'desconectarMDB2');
$this->$desconectar();
} //Fin de __destruct
/**
* Conectar
*/
public function conectar()
{
$dsn = $this->v_dsn;
//Si ya hay conexión existente, salimos.
if( !is_null($this->obj_conexion) )
{
return;
}
//No hay conexion, conectamos
$conectar = ( $this->driver=='pdo' ? 'conectarPDO' : 'conectarMDB2');
$this->obj_conexion = $this->$conectar( $dsn );
} //Fin de conectar
/**
* Realiza la conexión a la base de datos especificada por MDB2
*
* @param array $dsn
* @return MDB2_Driver_Common
*/
private function conectarMDB2($dsn)
{
// truco para que el autoload cargue la clase, y asi esten definidas las constantes
if (!class_exists('MDB2'))
throw new gvHidraException('No existe la clase MDB2');
IgepDB::preConexion($dsn);
$options = array(
'portability' => MDB2_PORTABILITY_NONE,
);
//Para evitar problemas con el funcionamiento del MDB2, forzamos a que se utilice una
//nueva conexion siempre. La informacion esta en el bug Pear::MDB2 (Bug #17198)
//Forzamos a que siempre utilice una nueva conexion
if(!$this->isPersistent())
$dsn['new_link'] = true;
$res = MDB2::connect($dsn,$options);
if (PEAR::isError($res)) {
$this->obj_errorConexion->setError( 'IGEP-6', basename(__FILE__), __FUNCTION__, $res );
}
else {
IgepDB::postConexion($dsn,$res);
//Finalmente marcamos el fetchMode por defecto
$res->setFetchMode(MDB2_FETCHMODE_ASSOC);
}
return $res;
} //Fin de conectarMDB2
/**
* Realiza la conexión a la base de datos especificada por PDO
*
* @return PDO
*/
private function conectarPDO($dsn)
{
IgepDB::preConexion($dsn);
if(!$this->isPersistent())
{
$dsn['new_link'] = true;
}
if (!defined('PDO::MYSQL_ATTR_FOUND_ROWS')) {
$options = array(
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC , //Finalmente marcamos el fetchMode por defecto
// REDMINE #23346
//PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING ,
);
}
else {
$options = array(
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC , //Finalmente marcamos el fetchMode por defecto
// REDMINE #23346
//PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ,
PDO::ATTR_ERRMODE => PDO::ERRMODE_WARNING ,
PDO::MYSQL_ATTR_FOUND_ROWS => true //FIX error concurrencia. Cambiamos el comportamiento de MyQL para que en un update se devuelva el número de filas MATCHEADAS con WHERE y no el número de actualizadas
);
}
$user = $dsn['username'];
$password = $dsn['password'];
$phptype = $dsn['phptype'];
if( $phptype == 'informix' )
{
$database = $dsn['database'];
$host = $dsn['hostspec'];
if (isset($dsn['port']))
{
$cadenaPort = ";
service={$dsn['port']}";
}
// TODO : Revisar si para Informix se debe usar 'client_locale=es_es.8859-1' ya que ahora se soporta/recomienda UTF8.
$dsn_string = "{$phptype}:host={$host}{$cadenaPort};database={$database};server={$host};client_locale=es_es.8859-1;protocol=onsoctcp;";
}
else
{
$dsn_string = self::buildConnectionStringPDO($dsn);
}
try
{
$res = new PDO( $dsn_string, $user, $password, $options );
}
catch (PDOException $e)
{
error_log( "Error en conexion: ".$dsn_string.$e->getMessage().'. ['.print_r($res, true).']');
$this->obj_errorConexion->setError('IGEP-6', basename(__FILE__), __FUNCTION__, $res);
}
IgepDB::postConexion($dsn, $res);
return $res;
} //Fin de conectar
/**
* Realiza la desconexión a la base de datos a la que actualmente
* se está conectado mediante MDB2.
*/
private function desconectarMDB2()
{
if( !isset($this->obj_conexion) || !is_object($this->obj_conexion)
|| !method_exists($this->obj_conexion, 'rollback') )
{
return;
}
$this->obj_conexion->rollback();
//Si no es persistente, desconectamos.
if( !$this->isPersistent() )
{
$res = $this->obj_conexion->disconnect();
if( PEAR::isError($res) )
{
$this->obj_errorConexion->setError( 'IGEP-7', basename(__FILE__), __FUNCTION__, $res );
}
$this->obj_conexion = null;
}
} //Fin de desconectarMDB2
/**
* Realiza la desconexión a la base de datos a la que actualmente
* se está conectado mediante PDO.
*/
private function desconectarPDO()
{
if( !isset($this->obj_conexion) || !is_object($this->obj_conexion)
|| !method_exists($this->obj_conexion, 'rollBack') )
{
return;
}
try
{
$this->obj_conexion->rollBack();
}
catch( Exception $e )
{
// NOP : en algunas ocasiones lanza excepción al no haber transacción activa
}
//Si no es persistente desconectamos
if( !$this->isPersistent() )
{
unset( $this->obj_conexion );
}
} //Fin de desconectarPDO
/**
* Devuelve el objeto conexión al que se está conectado.
*
* @return IgepConexion
*/
public function getConnection()
{
$this->conectar();
return $this->obj_conexion;
} //Fin de getConnection
/**
* Devuelve el objeto conexión al que se está conectado.
*
* @deprecated 3.2 - 21/01/2010
* @return IgepConexion
*/
/* public function getPEARConnection()
{
IgepDebug::setDebug( WARNING, 'DEPRECATED ' . __METHOD__ . '. Usar IgepConexion::getConnection '.
'tipoConsulta
.
*
* Este es un metodo alternativo a construirWhereBusqueda
, donde solo se descartan caracteres especiales y mayusculas en tipo 3
* Llamado desde gvHidraForm_DB->prepareDataSource
.
*
* Dependiendo del valor de la variable realiza una construcción de la Where u otra. Los tipos son:
* construirWhereConLike
, donde siempre se descartan caracteres especiales y mayusculas
* Llamado desde gvHidraForm_DB->prepareDataSource
*
* Dependiendo del valor de la variable realiza una construcción de la Where u otra. Los tipos son:
* 1
.
* @param boolean $prepareChar (Opcional) Indica si hay que transformar el valor a bd. Por omisión, es true
.
* @param mixed $queryModeParams (Opcional) Parámetros a usar para el queryMode.
* @return string
*/
public function unDiacriticCondition( $column, $value, $tipo=1, $prepareChar=true, $queryModeParams = null )
{
return $this->formatCondition( $column, $value, $tipo, true, $prepareChar, $queryModeParams );
} //Fin de unDiacriticCondition
/**
* Para formar condiciones de busqueda con tipos de datos diferentes a string.
*
* @param string $column Nombre de la columna.
* @param string $value Valor a filtrar en la columna.
* @param integer $tipo (Opcional) [0..2], igual que el queryMode. Por omisión, es 1
.
* @param mixed $queryModeParams (Opcional) Parámetros a usar para el queryMode.
* @return string
*/
public function normalCondition( $column, $value, $tipo=1, $queryModeParams = null)
{
return $this->formatCondition( $column, $value, $tipo, false, false, $queryModeParams );
} //Fin de normalCondition
/**
* Para formar condiciones de búsqueda.
*
* @param string $column Nombre de la columna.
* @param string $value Valor a filtrar en la columna.
* @param integer $tipo (Opcional) Igual que el queryMode: [0..2]. Por omisión, es 1
.
* @param boolean $undiacritic (Opcional) Ignorar, o no, acentos y mayúsculas. Por omisión, es true
.
* @param boolean $prepareChar (Opcional) Indica si hay que transformar el valor a bd. Por omisión, es true
.
* @param mixed $queryModeParams (Opcional) Parámetros a usar para el queryMode.
* @return string
*/
public function formatCondition( $column, $value, $tipo=1, $undiacritic=false, $prepareChar=true, $queryModeParams = null)
{
$dsn = $this->getDSN();
if ($undiacritic) {
$strtolower = (function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower');
$value = $strtolower( $value, 'UTF-8' );
}
if( $prepareChar )
{
$this->prepararOperacion( $value, TIPO_CARACTER );
}
$property = IgepDB::toTextForVS( $dsn, $column );
if ($undiacritic) {
$property = IgepDB::unDiacritic( $dsn, "lower ({$property})" );
}
$val_nolike = "'{$value}'";
if ($undiacritic) {
$val_nolike = IgepDB::unDiacritic( $dsn, $val_nolike );
}
$sqlEspecial = '';
$digitoEspecial = floor($tipo / 10);
switch( $digitoEspecial )
{
case '1' :
$umbral = $queryModeParams;
$sqlEspecial = "\n OR " . IgepDB::obtenerSimilarity( $dsn, $property, "'{$value}'" ) . " >= {$umbral}";
break;
}
switch( $tipo % 10 )
{
case 0:
$operator = '=';
$value = $val_nolike;
break;
case 1:
$operator = 'like';
$value = "'%{$value}%'";
if ($undiacritic) {
$value = IgepDB::unDiacritic( $dsn, $value );
}
break;
case 2:
$operator = 'like';
if( strpos($value,'%')===false && strpos($value,'_') === false )
{
$operator = '=';
}
$value = $val_nolike;
break;
default:
//if ($digitoEspecial == 0) {
throw new gvHidraException( __METHOD__ . " : valor de tipo no soportado: {$tipo}" );
//}
break;
}
$expresion = "{$property} {$operator} {$value}";
if (!empty ($sqlEspecial)) {
$expresion = "($expresion {$sqlEspecial})";
}
return $expresion;
} //Fin de formatCondition
/**
* Método encargado de, dadas una serie de cadenas, componerlas para crear una única
* cadena para la where de una SQL.
*
* @param array $v_cadenas Array que contiene las diferentes cadenas que componen la WHERE.
* @return string
*/
public function combinarWhere( $v_cadenas )
{
// Eliminamos las cadenas vacías (o con solo espacios).
$v_cadenas = array_filter( $v_cadenas, function($value) {
$value = trim($value);
return !empty($value);
} );
// Si no quedan cadenas, salimos.
if( empty($v_cadenas) )
{
return null;
}
// Parentizamos las cadenas de filtro.
$v_cadenas = array_map( function($cadena){
return '( '.trim($cadena).' )';
}, $v_cadenas );
// Concatemos con 'AND' las cadenas de filtro, y devolvemos el WHERE
$str_where = "\nWHERE " . implode( "\n\tAND ", $v_cadenas );
return $str_where;
} //Fin de combinarWhere
/**
* Método encargado de construir el limit para las consultas
*
* @param string $str_where
* @param int $int_limiteConsulta (Opcional) Por omisión, es 100.
* @return string
*/
public function construirLimite( & $str_where, $int_limiteConsulta=100 )
{
$limite = '';
if( $int_limiteConsulta != -1 && is_int($int_limiteConsulta) )
{
$limite = IgepDB::obtenerLimit( $str_where, $this->v_dsn, $int_limiteConsulta );
}
return $limite;
} //Fin de construirLimite
/**
* Dada una una consulta realiza la SELECT correspondiente.
* Si se indica el parametro typeDesc cambiará los datos de origen al formato FW.
*
* @param string $str_select Cadena con la query SQL.
* @param array $typeDesc (Opcional) Descripcion de los campos para posibles transformaciones. Por omisión, es null.
* @param string $debug Cadena con la que indicaremos si se quiere o no mostrar en el debug la consulta.
* @return array
*/
// REDMINE #23299
public function consultar( $str_select, $typeDesc=NULL, $debug = NULL )
{
//Si no hay conexion, conectamos
$this->conectar();
//Debug:Indicamos que ejecutamos la consulta
if ($debug === NULL)
{
IgepDebug::setDebug( DEBUG_IGEP, __CLASS__ . ": Ejecutamos consulta: {$str_select}
" );
}
elseif (!empty($debug))
{
IgepDebug::setDebug( DEBUG_IGEP, __CLASS__ . ": Ejecutamos consulta: {$debug}
" );
}
if( $this->obj_errorConexion->hayError() )
{
return null;
}
$resc = $this->obj_conexion->query( $str_select );
if( ($this->driver=='mdb2' && MDB2::isError($resc) )
|| ($this->driver=='pdo' && $resc===FALSE) )
{
$msg = $str_select;
// REDMINE #23277
if (!empty($debug)) {
$msg = $debug;
}
$this->obj_errorConexion->setError( 'IGEP-5', basename(__FILE__), __FUNCTION__, $resc, $msg );
return -1;
}
$res = $resc->fetchAll();
$this->transformResultSet( $res, $typeDesc );
return $res;
} //Fin de consultar
/**
* Dada una consulta realiza la SELECT correspondiente pero bloqueando las filas para modificacion
*
* @param string $str_select
* @param array $typeDesc (Opcional) Descripcion de los campos para posibles transformaciones. Por omisión, es null.
* @return array
*/
public function consultarForUpdate( $str_select, $typeDesc=NULL )
{
//Si no hay conexion, conectamos
$this->conectar();
IgepDebug::setDebug( DEBUG_IGEP, __CLASS__ . ': Ejecutamos ' . __FUNCTION__ . ": {$str_select}
" );
$tran = $this->obj_conexion->inTransaction();
// devuelve null si no hemos abierto la transaccion con mdb2
if( !is_null($tran) && !$tran )
{
throw new gvHidraNotInTransException( 'Para llamar a consultarForUpdate hay que estar en una transaccion' );
}
$str_select .= ' ' . IgepDB::obtenerBloqueo($this->getDSN());
$res = $this->consultar( $str_select, $typeDesc );
if( $res == -1 )
{
// ver si error de bloqueado o timeout
$cod = $this->obj_errorConexion->getDescErrorDB();
if( IgepDB::isLocked($this->getDSN(), $cod[0]) )
{
$msg = __CLASS__ .': no se puede bloquear los registros solicitados';
IgepDebug::setDebug( DEBUG_IGEP, $msg );
throw new gvHidraLockException( $msg, 4, null, $this->obj_errorConexion->obj_dbError );
}
}
return $res;
} //Fin de consultarForUpdate
/**
* Ejecución de consulta preparada
* Si se usan placeholders con nombre, en los parametros pasaremos array asociativo.
*
* @param string $str_select
* @param boolean $dml_ddl False para select, true para el resto.
* @param array $params
* @param array $typeDesc (Opcional) Descripcion de los campos para posibles transformaciones. Por omisión, es null.
* @param PDOStatement $cur (Opcional) Por omisión, es null.
* @return int|array Si dml_ddl, devuelve número de registros afectados; sino devuelve vector.
* Excepciones:
* $str_select
con dml_ddl: ".($dml_ddl? 'true': 'false'));
$db_pear = $this->obj_conexion;
$in = null; // por defecto todo text
$out = ( $dml_ddl ? MDB2_PREPARE_MANIP : null);
$cur = $db_pear->prepare( $str_select, $in, $out );
if( PEAR::isError($cur) )
{
$this->obj_errorConexion->setError( 'IGEP-5', basename(__FILE__), __FUNCTION__, $cur, $str_select );
throw new gvHidraPrepareException( 'Error: '.$cur->getMessage()." - Preparando sql: $str_select
", 1, null, $cur );
}
}
IgepDebug::setDebug( DEBUG_IGEP, "Ejecutando sql: {$str_select}
$str_select
) con parámetros: ".var_export($params,true), 2, null, $res );
}
if( $dml_ddl )
{
return $res;
}
$vec = $res->fetchAll( MDB2_FETCHMODE_ASSOC );
if( PEAR::isError($vec) )
{
$this->obj_errorConexion->setError( 'IGEP-5', basename(__FILE__), __FUNCTION__, $vec, $str_select );
throw new gvHidraFetchException( 'Error: '.$vec->getMessage()." - Ejecutando recuperación de registros", 3, null, $vec);
}
$this->transformResultSet( $vec, $typeDesc );
return $vec;
} //Fin de preparedQuery
/**
* Dada una consulta realiza la SELECT correspondiente pero bloqueando las filas para modificacion
* y usando sentencias preparadas.
*
* @param string $str_select
* @param array $params
* @param array $typeDesc (Opcional) Descripcion de los campos para posibles transformaciones. Por omisión, es null.
* @param PDOStatement $cur (Opcional) Por omisión, es null.
* @return int|array Devuelve vector. Excepciones:
* {$str_select}
" );
$tran = $this->obj_conexion->inTransaction();
// devuelve null si no hemos abierto la transaccion con mdb2
if( !is_null($tran) && !$tran )
{
throw new gvHidraNotInTransException( 'Para llamar a preparedQueryForUpdate hay que estar en una transaccion' );
}
$str_select .= ' '.IgepDB::obtenerBloqueo( $this->getDSN() );
try
{
$res = $this->preparedQuery( $str_select, false, $params, $typeDesc, $cur );
}
catch( gvHidraExecuteException $e )
{
// ver si error de bloqueado o timeout
$cod = $this->obj_errorConexion->getDescErrorDB();
if (IgepDB::isLocked( $this->getDSN(), $cod[0]) )
{
throw new gvHidraLockException( __CLASS__ . ': no se puede bloquear los registros solicitados', 4, null, $e->getSqlerror() );
}
throw $e;
}
return $res;
} //Fin de preparedQueryForUpdate
/**
* Transforma los datos obtenidos por consultar y preparedQuery.
*
* @param array $res
* @param array $typeDesc Descripcion de los campos para posibles transformaciones.
*/
public function transformResultSet( & $res, $typeDesc )
{
if( empty($typeDesc) )
{
return;
}
if( array_key_exists('DATATYPES',$typeDesc) )
{
// convertimos los tipos a la estructura usada en this->v_descCamposPanel si es necesario
$datatypes = array();
foreach( $typeDesc['DATATYPES'] as $clave => $valor )
{
if( is_array($valor) and array_key_exists('tipo',$valor) )
{
$datatypes[$clave] = $valor;
}
else
{
$datatypes[$clave] = array( 'tipo' => $valor );
}
}
}
else
{
$datatypes = null;
}
$this->transform_BD2FW( $res, $datatypes );
} //Fin de transformResultSet
/**
* Dada una una consulta realiza la SELECT correspondiente.
*
* @param string $str_select
* @return integer
*/
public function operar( $str_operar )
{
//Si no hay conexion, conectamos
$this->conectar();
//Debug:Indicamos que ejecutamos la operacion
IgepDebug::setDebug( DEBUG_IGEP, "IgepConexion: Ejecutamos operación: {$str_operar}
" );
if( $this->obj_errorConexion->hayError() )
{
return null;
}
$res = $this->obj_conexion->exec( $str_operar );
if( ($this->driver=='mdb2' && MDB2::isError($res))
|| ($this->driver=='pdo' && $res===FALSE) )
{
$this->obj_errorConexion->setError( 'IGEP-11', basename(__FILE__), __FUNCTION__, $res, $str_operar );
return -1;
}
return $res;
} //Fin de operar
/**
* Convierte de FW a DB
* Este método debe ser invocado por el usuario antes de realizar cualquier consulta/operacion a la BD
* para garantizar la portabilidad.
*
* @param array $a_parametros
* @param mixed $a_tipo (Opcional) Por omisión, es TIPO_CARACTER
.
*/
public function prepararOperacion( & $a_parametros, $a_tipo=TIPO_CARACTER )
{
//Si no hay conexion, conectamos
$this->conectar();
$transformer = new IgepTransformer();
$carfw = ConfigFramework::getNumericSeparatorsFW();
$backslash = IgepDB::backSlashScape( $this->getDsn() );
$carbd = IgepDB::caracteresNumericos( $this->getDsn() );
$transformer->setDecimal( $carfw['DECIMAL'], $carbd['DECIMAL'], $carfw['GROUP'], $carbd['GROUP'] );
//Cogemos la mascara a la que tenemos que transformar el timestamp
$fechafw = ConfigFramework::getDateMaskFW();
$fechabd = IgepDB::mascaraFechas( $this->getDsn() );
$transformer->setDate( $fechafw, $fechabd );
$transformer->setCharacter( "'", "''" );
$transformer->setCharacter( "\\", $backslash );
$vector = true;
if( !is_array($a_parametros) && $a_parametros!='' )
{
//si el tipo es nulo le ponemos TIPO_CARACTER
if( empty($a_tipo) )
{
$a_tipo = TIPO_CARACTER;
}
// le doy estructura de vector para no repetir el codigo
$vector = false;
$a_parametros = array(
array(
'col' => $a_parametros ,
) ,
);
$a_tipo = array(
'col' => array(
'tipo' => $a_tipo ,
) ,
);
}
if (is_array($a_tipo))
{
foreach( $a_parametros as $fila => $tupla )
{
foreach( $tupla as $campo => $notUsed )
{
if( empty($a_parametros[$fila][$campo]) )
{
continue;
}
$tipo_efectivo = (empty($a_tipo[$campo]['tipo'])
? TIPO_CARACTER
: ($a_tipo[$campo]['tipo']==TIPO_ENTERO ? TIPO_DECIMAL : $a_tipo[$campo]['tipo'])
);
if ($tipo_efectivo == TIPO_DECIMAL)
{
$tupla[$campo] = $transformer->expandExponent( $tupla[$campo], $carfw['DECIMAL'], $carfw['GROUP'] );
}
if( ($tipo_efectivo == TIPO_FECHA or $tipo_efectivo == TIPO_FECHAHORA) && is_object($tupla[$campo]) )
{
$a_parametros[$fila][$campo] = $tupla[$campo]->format( $fechabd.($tipo_efectivo==TIPO_FECHAHORA ? ' H:i:s' : '') );
}
else
{
$a_parametros[$fila][$campo] = $transformer->process($tipo_efectivo, $tupla[$campo] );
}
}
}
}
if( !$vector )
{
$a_parametros = $a_parametros[0]['col'];
}
}//Fin de prepararOperacion
/**
* Convierte datos de DB a FW
* No valida los datos en origen, por lo que de momento si en origen tenemos una fecha con hora,
* en el destino estaría sin hora.
*
* @param array $a_parametros
* @param string $a_tipo (Opcional) Por omisión, es TIPO_CARACTER
.
*/
public function transform_BD2FW( & $a_parametros, $a_tipo=TIPO_CARACTER )
{
$transformer = new IgepTransformer();
$carbd = IgepDB::caracteresNumericos( $this->getDsn() );
$carfw = ConfigFramework::getNumericSeparatorsFW();
$transformer->setDecimal( $carbd['DECIMAL'], $carfw['DECIMAL'], $carbd['GROUP'], $carfw['GROUP'] );
$fechabd = IgepDB::mascaraFechas( $this->getDsn() );
$fechafw = ConfigFramework::getDateMaskFW();
$transformer->setDate( $fechabd, $fechafw );
$vector = true;
if( !is_array($a_parametros) )
{
// le doy estructura de vector para no repetir el codigo
$vector = false;
$a_parametros = array(
array(
'col' => $a_parametros ,
) ,
);
$a_tipo = array(
'col' => array(
'tipo' => $a_tipo ,
) ,
);
}
if( is_array($a_tipo) )
{
foreach( $a_parametros as $fila => $tupla )
{
foreach ($tupla as $campo => $valor)
{
$tipo_efectivo = (empty($a_tipo[$campo]['tipo'])
? TIPO_CARACTER
: ($a_tipo[$campo]['tipo']==TIPO_ENTERO ? TIPO_DECIMAL : $a_tipo[$campo]['tipo'])
);
if( empty($a_parametros[$fila][$campo]) )
{
if( $tipo_efectivo==TIPO_FECHA || $tipo_efectivo==TIPO_FECHAHORA )
{
$a_parametros[$fila][$campo] = null;
}
continue;
}
$a_parametros[$fila][$campo] = $transformer->process( $tipo_efectivo, $valor );
if( $tipo_efectivo==TIPO_FECHA || $tipo_efectivo==TIPO_FECHAHORA )
{
$a_parametros[$fila][$campo] = new gvHidraTimestamp( $a_parametros[$fila][$campo] );
}
}
}
}
if( !$vector )
{
$a_parametros = $a_parametros[0]['col'];
}
} //Fin de transform_BD2FW
/**
* Transforma un numero de capa negocio a capa datos.
*Nota: El argumento será tratado como de tipo TIPO_DECIMAL
Transforma una fecha de capa negocio a capa datos
*Nota: El argumento será tratado como de tipo TIPO_FECHAHORA