Pagina principal ADODB en español

Libreria ADOdb para PHP

V4.92 29 Ago 2006 (c) 2000-2006 John Lim (jlim#natsoft.com)

Este programa tiene licencia dual BSD-Style y LGPL. Esto significa que lo puedes usar tanto en productos comerciales como en propietarios.

Ligas utules de ADOdb: Descarga   Otros manuales (en ingles)   Otros manuales (en español

Introduccion
Caracteristicas Unicas
Como se esta usando actualmente ADOdb
Solicitud de mejoras y reporte de fallas
Instalacion
Instalacion Minima
Codigo de Inicio y Ejemplos de conexion
  Soporte a DSN (Data Source Name)   Ejemplos de conexion
ADOdb de alta velocidad - trucos de optimizacion

Modificando y extendiendo ADOdb con seguridad
Caracteristicas para PHP5

  foreach iterators exceptions
Base de datos soportadas
Tutoriales
Ejemplo 1: Select
Ejemplo 2: Select avanzado
Ejemplo 3: Insert
Ejemplo 4: Depurando  Ejemplo rs2html
Ejemplo 5: MySQL y Menus
Ejemplo 6: Conectarase a multiples bases de datos al mismo tiempo
Ejemplo 7: Generando enunciados SQL de Update e Insert
Ejemplo 8: Implementando cursores con Siguiente y Anterior
Ejemplo 9: Exportando a formatos delimitados por Tabulador o comas
Ejemplo 10: Filtros a la medida
Ejemplo 11: Transacciones inteligentes

Usando manejadores de errores a la medida o de PEAR
Nombres de DSN
Memoria intermedia (Caching)
Tablas Pivote

REFERENCIA

Variables: $ADODB_COUNTRECS $ADODB_ANSI_PADDING_OFF $ADODB_CACHE_DIR $ADODB_FORCE_TYPE $ADODB_FETCH_MODE $ADODB_LANG
Constantes: ADODB_ASSOC_CASE
ADOConnection
Conecciones: Connect PConnect NConnect IsConnected
Ejecutando SQL: Execute CacheExecute SelectLimit CacheSelectLimit Param Prepare PrepareSP InParameter OutParameter AutoExecute
              GetOne CacheGetOne GetRow CacheGetRow GetAll CacheGetAll GetCol CacheGetCol GetAssoc CacheGetAssoc Replace
               ExecuteCursor (oci8 unicamente)
Generando enunciados SQL: GetUpdateSQL GetInsertSQL Concat IfNull length random substr qstr Param OffsetDate SQLDate DBDate DBTimeStamp BindDate BindTimeStamp
Blobs: UpdateBlob UpdateClob UpdateBlobFile BlobEncode BlobDecode
Paginacion/Desplazamiento: PageExecute CachePageExecute
Limpieza: CacheFlush Close
Transacciones: StartTrans CompleteTrans FailTrans HasFailedTrans BeginTrans CommitTrans RollbackTransSetTransactionMode
Recuperando Datos: SetFetchMode
Cadenas: concat length qstr quote substr
Fechas: DBDate DBTimeStamp UnixDate UnixTimeStamp OffsetDate SQLDate
Renglones: Affected_Rows Insert_ID RowLock GenID CreateSequence DropSequence
Manejo de Errores: ErrorMsg ErrorNo MetaError MetaErrorMsg IgnoreErrors
Diccionario de datos (metadata): MetaDatabases MetaTables MetaColumns MetaColumnNames MetaPrimaryKeys MetaForeignKeys ServerInfo
Estadisticas y modifacion de SQL: LogSQL fnExecute and fnCacheExecute
Descontinuado: Bind BlankRecordSet Parameter

ADORecordSet

Regresa un campo: Fields
Regresa un renglon:FetchRow FetchInto FetchObject FetchNextObject FetchObj FetchNextObj GetRowAssoc
Regresa todos los renglones:GetArray GetRows GetAssoc
Desplazamiento:Move MoveNext MoveFirst MoveLast AbsolutePosition CurrentRow AtFirstPage AtLastPage AbsolutePage
Generacion de Menu:GetMenu GetMenu2
Fechas:UserDate UserTimeStamp UnixDate UnixTimeStamp
Informacion del Recordset:RecordCount PO_RecordSet NextRecordSet
Informacion de un campo:FieldCount FetchField MetaType
Limpieza: Close

rs2html  ejemplo
Diferencias entre ADOdb y ADO
Guia para manejadores de base de datos
Bitacora de cambios

Introduccion

Las funciones de acceso a base de datos en PHP no estan estandarizadas. Esto requiere una libreria que esconda las diferencias entre cada API de base de datos (encapsular las diferencias) para que podamos cambiar facilmente de base de datos. Se requiere la version de PHP 4.0.5 o posterior (debido a que usamos la funcion str_replace con arreglos).

Actualmente manejamos MySQL, Oracle, Microsoft SQL Server, Sybase, Sybase SQL Anywhere, Informix, PostgreSQL, FrontBase, SQLite, Interbase (versiones de Firebird y Borland), Foxpro, Access, ADO, DB2, SAP DB and ODBC. Tenemos noticias que se puede conectar a Progress y CacheLite via ODBC. Esperamos que mas personas contribuyan con drivers para manejar mas base de datos.

PHP4 maneja variables de sesion. Puedes almacenar la informacion de tu sesion usando ADOdb para tener una verdadera portabilidad y escalabilidad. Para mas informacion ve el archivo adodb-session.php.

Tambie lee tips_portable_sql-es.htm (tambien dispobible en ingles en el archivo tips_portable_sql.htm) para consejos para escribir enunciados SQL portables.

Caracteristicas especiales de ADOdb

Como se esta usando ADOdb

Aqui hay algunos ejemplos de personas que usan ADOdb (para una lista mas larga, visita http://adodb.sourceforge.net/):

Solicitud de mejoras y reporte de fallas

Las solicitudes de mejoras o reporte de fallas pueden ser enviadas por correo electronico a jlim#natsoft.com.my o publicadas en el foro de ayuda de ADOdb en http://phplens.com/lens/lensforum/topics.php?id=4.

Guia de Instalacion

Asegurate de estar usando PHP 4.0.5 o posterior. Descomprime todos los archivos en un directorio accesible por tu servidor Web.

Para probar, intenta modificar algunos de los ejemplos del tutorial. Asegurate de corregir los parametros de coneccion a tus necesidades. Puedes depurar el codigo usando $db->debug = true como se muestra a continuacion:

<?php
	include('adodb/adodb.inc.php');
	$db = ADONewConnection($dbdriver); # eg 'mysql' o 'postgres'
	$db->debug = true;
	$db->Connect($servidor, $usuario, $contraseña, $database);
	$rs = $db->Execute('select * from alguna_tabla_pequeña');
	print "<pre>";
	print_r($rs->GetRows());
	print "</pre>";
?>

Instalacion Minima

Para los desarrolladores que quieran distribuir una version minima de ADOdb, se requieren los siguientes archivos:

Opcionalmente:

Ejemplos de Codigo de Inicio

Al ejecutar ADOdb, al menos se cargan dos archivos. Primero adodb/adodb.inc.php, que contienen todas las funciones usadas por todas las clases de bases de datos. El codigo especifico a una base de datos en particular esta en el archivo adodb/driver/adodb-????.inc.php.

Por ejemplo, para conectarse a una base de datos mysql:

include('adodb/adodb.inc.php');
$conn = &ADONewConnection('mysql');

Cada vez que necesitas conectarte a una base de datos, debes de crear un objeto de conexion usando la funcion ADONewConnection($driver). NewADOConnection($driver) es un nombre alterno para la misma funcion.

En este momento, no estas conectado a la base de datos (ya no es cierto si como parametro usas un dsn). Primero tienes que decidir si vas a usar una coneccion persistente o no persistente. La ventaja de las conexiones persistentes es que son mas rapidas, debido a que la conexion no es cerrada nunca (aun si usas Close()). Las conexiones No persistentes consumen menos recursos reduciendo el riesgo de sobrecargar la base de datos o el servidor Web.

Para conexiones persistentes, usa $conn->PConnect(), o $conn->Connect() para conexiones no persistentes. Algunas bases de datos tambien manejan NConnect(), la cual forza la creacion de una nueva conexion.

Problemas con Conexiones: Si creas dos conexiones, pero ambas usan el mismo usuario y contraseña, PHP compartira las conexiones. Esto puede causar problemas si se supone que las conexiones son a diferentes bases de datos. La solucion es usar siempre diferentes usuarios para diferentes bases de datos o usar NConnect().

Soporte a Data Source Name (DSN)

Desde la version 4.51 de ADOdb, te puedes conectar a la base de datos pasando como argumento a NewADOConnection() (o ADONewConnection, que es la misma funcion) un dsn. El formato del dsn es:

   $driver://$username:$password@hostname/$database?options[=value]

NewADOConnection() llama a Connect() o PConnect() internamente por ti. Si la conexion falla, te regresa false.

   # Conexion no persistente
    $dsn = 'mysql://root:pwd@localhost/mydb'; 
    $db = NewADOConnection($dsn);
    if (!$db) die("Conexion incorrecta");   
    
    # no se requiere llamar connect/pconnect!
    $arr = $db->GetArray("select * from table");
    
    # conexion persistente
    $dsn2 = 'mysql://root:pwd@localhost/mydb?persist'; 

Si tienes caracteres especiales como /:?_ en tu dsn, entonces tienes que invocar a rawurlencode primero:

   $pwd = rawurlencode($pwd);
$dsn = "mysql://root:$pwd@localhost/mydb"; $dsn2=rawurlencode("sybase_ase")."://user:pass@host/path?query";

Las opciones permitidas son:

Para todas los drivers 'persist', 'persistent', 'debug', 'fetchmode', 'new'
Interbase/Firebird 'dialect','charset','buffers','role'
M'soft ADO 'charpage'
MySQL 'clientflags'
MySQLi 'port', 'socket', 'clientflags'
Oci8 'nls_date_format','charset'

Para todos los drivers, cuando se activa la opcion persist o persistent, se forza una conexionpersistente; asi mismo, cuando se activa new, entonces la conexion se creara usando NConnect si el driver lo maneja. La opcion debug habilita la depuracion. La opcion fetchmode invoca SetFetchMode(). Si no se le indica el valor a alguna oopcion se asume el valor de 1.

La version DSN de ADOdb DSN es compatible con el formato de la version 1.0 de PEAR DB.

Ejemplos de Conexion a Bases de Datos

MySQL y la mayoria de bases de datos

Las conexiones a MySQL son muy sencillas, y los parametros son identicos a mysql_connect:

    $conn = &ADONewConnection('mysql'); 
$conn->PConnect('localhost','usuario','contraseña','database');
# o dsn $dsn = 'mysql://user:pwd@localhost/mydb'; $conn = ADONewConnection($dsn); # no necesita Connect() # o dsn persistente $dsn = 'mysql://user:pwd@localhost/mydb?persist'; $conn = ADONewConnection($dsn); # no necesita PConnect() # un ejemplo mas complejo: $pwd = urlencode($pwd); $flags = MYSQL_CLIENT_COMPRESS; $dsn = "mysql://user:$pwd@localhost/mydb?persist&clientflags=$flags"; $conn = ADONewConnection($dsn); # no need for PConnect()

La mayoria de las demas bases de datos usan la misma convencion: Connect($servidor, $usuario, $contraseña, $database). Las excepciones se enlistas a continuacion.

PDO

PDO, que solo funciona en PHP5, acepta una cadena de driver especifica:

    $conn =& NewADConnection('pdo');
    $conn->Connect('mysql:host=localhost',$user,$pwd,$mydb);
    $conn->Connect('mysql:host=localhost;dbname=mydb',$user,$pwd);
    $conn->Connect("mysql:host=localhost;dbname=mydb;username=$user;password=$pwd");

El mecanismo via DSN tambien funciona:

    $conn =& NewADConnection("pdo_mysql://user:pwd@localhost/mydb?persist"); # persist es opcional

PostgreSQL

PostgreSQL 7 y 8 acepta conexiones usando:

a. La cadena estandard de conexcion:

	$conn = &ADONewConnection('postgres'); 
	$conn->PConnect('host=localhost port=5432 dbname=maria');

b. Los 4 parametros clasicos:

	$conn->PConnect('localhost','usuario','contraseña','database');
 

c. dsn:

   $dsn = 'postgres://user:pwd@localhost/mydb?persist';  # persist es opcional
    $conn = ADONewConnection($dsn);  # no se requiere Connect/PConnect

LDAP

Este es un ejemplo de busqueda en un servidor LDAP. Gracias a Josh Eldridge por el driver y este ejemplo:

 <?php
require('adodb/adodb.inc.php');

/* Make sure to set this BEFORE calling Connect() */
$LDAP_CONNECT_OPTIONS = Array(
    Array ("OPTION_NAME"=>LDAP_OPT_DEREF, "OPTION_VALUE"=>2),
    Array ("OPTION_NAME"=>LDAP_OPT_SIZELIMIT,"OPTION_VALUE"=>100),
    Array ("OPTION_NAME"=>LDAP_OPT_TIMELIMIT,"OPTION_VALUE"=>30),
    Array ("OPTION_NAME"=>LDAP_OPT_PROTOCOL_VERSION,"OPTION_VALUE"=>3),
    Array ("OPTION_NAME"=>LDAP_OPT_ERROR_NUMBER,"OPTION_VALUE"=>13),
    Array ("OPTION_NAME"=>LDAP_OPT_REFERRALS,"OPTION_VALUE"=>FALSE),
    Array ("OPTION_NAME"=>LDAP_OPT_RESTART,"OPTION_VALUE"=>FALSE)
);

$host = 'ldap.baylor.edu';
$ldapbase = 'ou=People,o=Baylor University,c=US';

$ldap = NewADOConnection( 'ldap' );
$ldap->Connect( $host, $user_name='', $password='', $ldapbase );

echo "<pre>";

print_r( $ldap->ServerInfo() );
$ldap->SetFetchMode(ADODB_FETCH_ASSOC);
$userName = 'eldridge';
$filter="(|(CN=$userName*)(sn=$userName*)(givenname=$userName*)(uid=$userName*))";

$rs = $ldap->Execute( $filter );
if ($rs)
	while ($arr = $rs->FetchRow()) {
	     print_r($arr);	
	}

$rs = $ldap->Execute( $filter );
if ($rs) 
	while (!$rs->EOF) {
 		print_r($rs->fields);	
		$rs->MoveNext();
	} 
	
print_r( $ldap->GetArray( $filter ) );
print_r( $ldap->GetRow( $filter ) );

$ldap->Close();
echo "</pre>";
?>

Using DSN:

$dsn = "ldap://ldap.baylor.edu/ou=People,o=Baylor University,c=US";
$db = NewADOConnection($dsn);

Interbase/Firebird

Hay que definir la base de datos en el parametro $host:
	$conn = &ADONewConnection('ibase'); 
	$conn->PConnect('localhost:c:\ibase\employee.gdb','sysdba','masterkey');

O con dsn:

   $dsn = 'firebird://user:pwd@localhost/mydb?persist&dialect=3';  # persist es opcional
   $conn = ADONewConnection($dsn);  # no se requiere Connect/PConnect
SQLite Sqlite creara la base de datos si no existe.
	$conn = &ADONewConnection('sqlite'); 
	$conn->PConnect('c:\path\to\sqlite.db'); # sqlite la creara si no existe

O con dsn:

   $path = urlencode('c:\path\to\sqlite.db');
    $dsn = "sqlite://$path/?persist";  # persist es opcional
    $conn = ADONewConnection($dsn);  # no se requiere Connect/PConnect

Oracle (oci8)

Con oci8 te puedes conectar de varias maneras.

a. PHP y Oracle estan en la misma maquina, usar SID.

	$conn->Connect(false, 'scott', 'tiger');

b. Nombre TNS definido en tnsnames.ora (o ONAMES o HOSTNAMES), ej. 'miTNS'

	$conn->PConnect(false, 'scott', 'tiger', 'miTNS');

o

 	$conn->PConnect('miTNS', 'scott', 'tiger');

c. Direccion del servidor y SID

       $conn->connectSID = true;
$conn->Connect('192.168.0.1', 'scott', 'tiger', 'SID');

d. Direccion del servidor y nombre del servicio

	$conn->Connect('192.168.0.1', 'scott', 'tiger', 'servicename');

e. Cadena de conexion de Oracle:

    $cstr = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=$host)(PORT=$port))(CONNECT_DATA=(SID=$sid)))";
    $conn->Connect($cstr, 'scott', 'tiger');

f. ADOdb dsn:

    $dsn = 'oci8://user:pwd@tnsname/?persist';  # persist is optional
    $conn = ADONewConnection($dsn);  # no need for Connect/PConnect

    $dsn = 'oci8://user:pwd@host/sid';
    $conn = ADONewConnection($dsn);

    $dsn = 'oci8://user:pwd@/';   # oracle on local machine
    $conn = ADONewConnection($dsn);

Tamnbien puedes usar el charSet para Oracle 9.2 y posterior, soportado desde PHP 4.3.2, ADOdb 4.54:

    $conn->charSet = 'we8iso8859p1';
    $conn->Connect(...);

    # o
    $dsn = 'oci8://user:pwd@tnsname/?charset=WE8MSWIN1252';
    $db = ADONewConnection($dsn);

DSN-less ODBC (ejemplos con access and mssql)

Las conexiones DSN via ODBC pueden ser creadas en el panel de control de ODBC, o puedes usar una conexion DSN-less. Para usar una conexion DSN-less se necesita PHP version 4.3 o posterior.

Para Microsoft Access:

	$db =& ADONewConnection('access');
	$dsn = "Driver={Microsoft Access Driver (*.mdb)};Dbq=d:\\northwind.mdb;Uid=Admin;Pwd=;";
	$db->Connect($dsn);
Para Microsoft SQL Server:
	$db =& ADONewConnection('odbc_mssql');
	$dsn = "Driver={SQL Server};Server=localhost;Database=northwind;";
	$db->Connect($dsn,'userid','password');
o si lo prefieres, se puede usar la extension mssql (que esta limitada a la funcionalildad de la version 6.5):
   $db =& ADONewConnection('mssql');
$db->Execute('localhost', 'userid', 'password', 'northwind');
Para DB2:
    $dbms = 'db2'; # or 'odbc_db2' if db2 extension not available
    $db =& ADONewConnection($dbms);
    $dsn = "driver={IBM db2 odbc DRIVER};Database=sample;hostname=localhost;port=50000;protocol=TCPIP;".
                "uid=root; pwd=secret";
    $db->Connect($dsn);
Conexiones DSN-less con ADO
Si estas usando una version de PHP anterior a 4.3.0, Las conexiones DSN-less solo trabajaran con el ADO de Microsoft, el cual esta basada en las APIs COM de Microsoft. Un ejemplo de uso de la libreria ADOdb y el ADO de Microsoft:
<?php
	include('adodb.inc.php'); 
	$db = &ADONewConnection("ado_mssql");
	print "<h1>Connecting DSN-less $db->databaseType...</h1>";
		
	$myDSN="PROVIDER=MSDASQL;DRIVER={SQL Server};"
		. "SERVER=flipper;DATABASE=ai;UID=sa;PWD=;"  ;
	$db->Connect($myDSN);
	
	$rs = $db->Execute("select * from table");
	$arr = $rs->GetArray();
	print_r($arr);
?>

ADOdb de alta velocidad - trucos de optimizacion

La libreria ADOdb es una clase grande, aun asi regularmente derrota a las 'otras' clases PHP en rendimiento. Esto es por su diseño en forma de capas, como una cebolla, con las funciones mas rapidas en la capa mas profunda. Usa principalmente estas funciones para el mejor rendimiento:

Capa mas profunda

Connect, PConnect, NConnect
Execute, CacheExecute
SelectLimit, CacheSelectLimit
MoveNext, Close
qstr, Affected_Rows, Insert_ID

La manera mas rapida de acceder a los campos es usando el arreglo array $recordset->fields. Tambien hay que asignar la variable global $ADODB_FETCH_MODE = ADODB_FETCH_NUM, y (para oci8, ibase/firebird y odbc) $ADODB_COUNTRECS = false antes de conectarse a la base de datos. Esto al momento (Dec 2003).

Considera usar parametros posisicionales (bind) si tu base de datos los soporta, ya que mejora la reutilizacion de los planes de ejecucion. Usa el sistema de 'performance tuning de ADodb para identificar rapidamente los cuellos de botella.

Finalmente asegurate de que tienes un acelerador de PHP instalado como APC, Turck MMCache, Zend Accelerator o ionCube.

Algunos ejemplos:

Recuperacion de datos mas rapida usando PHPRecuperacion de datos mas rapida usando la extension ADOdb
$rs =& $rs->Execute($sql);
while (!$rs->EOF) {
var_dump($rs->fields);
$rs->MoveNext();
}
$rs =& $rs->Execute($sql);
$array = adodb_getall($rs);
var_dump($array);


Sugerencias Avanzadas

Si tienes instalada la extension C ADOdb, puedes modificar tus llamados a $rs->MoveNext() por adodb_movenext($rs). Esto duplica la velocidad de esta operacion. Para obtener todo un conjunto de rsultados en una operacion, usa GetArray(), el cual usa internamente la funcion de alta velocidad de la extension adodb_getall($rs).

Execute() es la manera usal para ejecutar enunciados SQL. Puedes usar la funcion de bajo nivel _Execute() y _query() para reducir el costo. Ambas funciones comparten los mismos parametros que Execute().

Si no tienes ningun parametro posicional o si tu base de datos soporta los parametros posicionales (sin emulacion), entonces puedes llamar _Execute() directamente. AL invocar esta funcion eliminas la emulacion de parametros. La depuracion tambien es manejada por _Execute().

Si no requuieres depuracion ni emulacion de parametros, no requieres obtener un recordset, entonces puedes llamar _query. Es muy buena para inserts, updates y deletes. Al invocar esta funcion omites la emulacion de parametros, la depuracion y el majejo de recordsets. _query() regresa el resultid, true o false.

Recomendacion para INFORMIX: Desabilita los cursores navegables 'scroll' con $db->cursorType = 0.

Modfificando ADOdb con seguridad

Tu puedes modificar ADOdb para tus propios usos. Por suerte puedes mantener la compatibilidad extendiendo las clases de ADodb y por medio de la variable $ADODB_NEWCONNECTION. $ADODB_NEWCONNECTION nos permite modificar el comportamiento de ADONewConnection(). ADOConnection() verifica esta variable e invocara la funcion cuyo nombre tenga la variable.

En el siguiente ejemplo, se le agrega mas funcionabilidad al objeto de conexion por medio de las clases hack_mysql y hack_postgres7. La convencion en el nombre de las clases recordset se controla por medio de la propiedad $rsPrefix. En este caso se le asigna el valor de 'hack_rs_', lo que proboca que ADOdb use hack_rs_mysql y hack_rs_postgres7 como los nombres de las clases recordset. En caso de que se requiera usar los drivers normales de ADODB hay que regresar el valor 'false' en la funcion.

class hack_mysql extends adodb_mysql {
var $rsPrefix = 'hack_rs_';
  /* aqui van las modificaciones */
}

class hack_rs_mysql extends ADORecordSet_mysql {
 /* aqui van las modificaciones */
}

class hack_postgres7 extends adodb_postgres7 {
var $rsPrefix = 'hack_rs_';
 /* aqui van las modificaciones */
}

class hack_rs_postgres7 extends ADORecordSet_postgres7 {
 /* aqui van las modificaciones */
}

$ADODB_NEWCONNECTION = 'hack_factory';

function& hack_factory($driver)
{
	if ($driver !== 'mysql' && $driver !== 'postgres7') return false;
	
	$driver = 'hack_'.$driver;
	$obj = new $driver();
	return $obj;
}

include_once('adodb.inc.php');

No olvides invocar el constructor de la clase padre.

Caracteristicas para PHP5

A partir de la version 4.02 ADOdb determina automaticamente que version de PHP estas usando. Si detecta la version PHP5, activa automaticamente las siguientes caracteriticas:

Bases de Datos soportadas

La columna nombre es el valor que se le pasa a NewADOConnection($nombre) para crear el objecto de conexion para esa base de datos.

Nombre Verificada Base de datos sirve RecordCount() Pre-requisitos Sistemas operativos
access B Microsoft Access/Jet. Hay que crear el DSN en el ODBC. S/N ODBC Windows unicamente
ado B

ADO generico, no esta optimizado para ninguna base de datos especifica. Permite conexiones DSN-less. Para un mejor rendimiento, utilizar un proveedor de OLEDB. Esta la clase basa para todos los drivers ado.

Hay que configurar $db->codePage antes de conextarse.

? depende de la base de datos ADO o proveedor OLEDB Windows unicamente
ado_access B Microsoft Access/Jet usando ADO. Permite conexiones DSN-less. Para mejor rendimiento usar un proveedor OLEDB. S/N ADO o proveedor OLEDB Windows unicamente
ado_mssql B Microsoft SQL Server usando ADO. Permite conexiones DSN-less. Para mejor rendimiento usar un proveedor OLEDB. S/N ADO o proveedor OLEDB Windows unicamente
db2 A DB2. Debe de funcionar satisfactoriamente porque se base en el driver ODBC based on ODBC. S/N Interfase CLI/ODBC de DB2

Unix y Windows. Trucos de instalacion en Unix. Hay reportes de que los parametros $host y $database del Connect() tienen que ir invertidos si se usa la interfase CLI.

odbc_db2 C Se conecta a DB2 usando la extesion ODBC generica. S/N Interfase CLI/ODBC de DB2

Unix y Windows. sugerencias para instalacion en Unix. Tengo reportes que los parametros $host y $database tienen que ser invertidos en el Connect() cuando se usa la interfase CLI.

vfp A Microsoft Visual FoxPro. Hay que crear un DSN. S/N ODBC Windows unicamente
fbsql C FrontBase. S ?

Unix y Windows

ibase B Interbase 6 o anterior. Algunos usuarios dicen que puedes necesitar esta sintaxis para conectarte
$db->PConnect('localhost:c:/ibase/employee.gdb', "sysdba", "masterkey") . Actualmente le falta Affected_Rows.

Antes de conectarte puedes modificarle $db->dialect, $db->buffers y $db->charSet.
S/N cliente Interbase Unix y Windows
firebird C version Firebird de interbase. S/N cliente Interbase Unix y Windows
borland_ibase C version Borland de Interbase 6.5 o posterior. Desafortunadamente las version son diferentess. S/N cliente Interbase Unix y Windows
informix72 C Versiones Informix anteriores a 7.3 que no soportan SELECT FIRST. S/N Cliente Informix Unix y Windows
informix C Driver generico para informix. S/N Cliente Informix Unix y Windows
ldap C Driver LDAP driver. Ver el ejemplo para informacion de uso.   Extension LDAP ?
mssql A

Microsoft SQL Server 7 y posterior. Tanbien funciona con Microsoft SQL Server 2000. Toma en cuenta que el formato de las fechas es problematico con este driver. Por ejemplo, la extension mssql de PHP no regresa los segundos de los campos datetime!

S/N cliente Mssql

Unix y Windows.
Guia de instalacion de Unix y otra mas.

mssqlpo A

Driver portable de mssql. Es identico al driver de mssqk anteriorm excepto que el operador de concatenacion '||' se convirtio a '+'. Esto es util para migrar codigo desde otras versiones de SQL.

S/N Cliente Mssql

Unix y Windows.
Guia de instlacion en Unix
.

mysql A MySQL sin manejo de transacciones. Puedes usar $db->clientFlags antes de conectarte. S/N Cliente MySQL Unix y Windows
mysqlt or maxsql A

MySQL con soporte de transacciones. Recomendamos usar || como el operador de concatenacion para una mejor portabilidad. Esto se logra ejectuando MySQL con:
mysqld --ansi o mysqld --sql-mode=PIPES_AS_CONCAT

S/N Cliente MySQL Unix y Windows
oci8 A Oracle 8/9. Tiene mas funcionabilidad que el driver oracle (ej. Affected_Rows). Puedes tener que hacer un putenv('ORACLE_HOME=...') antes del Connect/PConnect.

hay dos maneras de conectarse - Con la direccion IP del servidor y el nombre del servicio:
PConnect('serverip:1521','scott','tiger','service')
o en base a un renglon en TNSNAMES.ORA o ONAMES o HOSTNAMES:
PConnect(false, 'scott', 'tiger', $oraname).

A partir de la version 2.31, se manejan las variables de cursores REF directamente (ver ExecuteCursor).

S/N Cliente Oracle Unix y Windows
oci805 C Maneja un funcionaldiad reducida para la version 8.0.5 de Oracle. SelectLimit no es tan eficiente como en los drivers oci8 o oci8po. S/N Cliente Oracle Unix y Windows
oci8po A Driver portable de Oracle 8/9. Esta es casi identica al driver oci8 execpto que (a) Las variables 'bind' en los Prepare() usan ? en lugar de :bindvar, (b) los nombres de campos estan en minusculas (la manera mas usual en PHP).

Usa este driver si la portabilidad de tu codigo a otras bases de datos es importante. En caso contrario usa el driver oci8 ya que da mejor rendimiento.

S/N Cliente Oracle Unix y Windows
odbc A Driver generico para ODBC, no esta optimizado para ninguna base de datos especifica. Para conectarse usa
PConnect('DSN','user','pwd'). Esta es la clase base para todos los drivers basados en ODBC .
? depende de la base de datos ODBC Unix y Windows. Trucos para Unix.
odbc_mssql C Usa ODBC para conectarse a MSSQL S/N ODBC Unix y Windows.
odbc_oracle C Usa ODBC para conectarse a Oracle S/N ODBC Unix y Windows.
odbtp C Driver odbtp generico. Odbtp es un programa para poder usar los DSN en el ODBC de Windows desde OTROS sistemas operativos (ej. Linux). S/N odbtp Unix y Windows
odbtp_unicode C Odtbp con soporte unicode S/N odbtp Unix y Windows
oracle C Implementa el viejo API de Oracle 7. Si te es posible usa el driver oci8 para un mejor rendimiento. S/N Cliente Oracle Unix y Windows
netezza C Driver para Netezza. Netezza esta basado en el codigo base de postgres. Y ? ?
postgres A Driver generico PostgreSQL. Actualmente es identico al driver postgres7. S Cliente PostgreSQL Unix y Windows.
postgres64 A Para PostgreSQL 6.4 y anteriores que no manejan LIMIT internamente. S Cliente PostgreSQL Unix y Windows.
postgres7 A PostgreSQL que soporta LIMIT y caracteristicas de la version 7. S Cliente PostgreSQL Unix y Windows.
postgres8 A PostgreSQL que maneja la funcionalidad de la version 8. S Cliente PostgreSQL Unix y Windows.
sapdb C SAP DB. Debe de funcionar bien ya que esta basado en el driver ODBC. S/N Cliente ODBC de SAPdb

?

sqlanywhere C Sybase SQL Anywhere. Debe de funcionar bien ya que esta basado en el driver ODBC. S/N Cliente ODBC de SQL Anywhere ODBC

?

sqlite B SQLite. Unicamente verificada en PHP5. S -

Unix y Windows.

sqlitepo B Driver portable para SQLLite. Es debido a que el modo asociativo no funciona como en los otros drivers. Al seleccionar multiples tablas (joining), se incluye el nombre de la tabla en la llave del arreglo asociativo.

En el driver "sqlitepo", el nombre de la tabla es eliminado del nombre de la columna. Cuando hay conflictos, el primer campo tiene preferencia.

S -

Unix y Windows.

sybase C Sybase. S/N Cliente Sybase

Unix y Windows.

sybase_ase C Sybase ASE. S/N Cliente Sybase

Unix y Windows.

La columna "Verificada" indica que tan profusamente el codigo a sido verificado y usado.
A = bien verificado y usado con mucha gente
B = verificado y usable, pero algunas caracteristicas pueden no estar implementadas
C = driver proporcionado por los usuarios o experimental. Puede no manejar todas las ultimas caracteristcicas de ADOdb.

La columna "sirve RecordCount()" indica si RecordCount() regresa la cantidad de renglones o regresa -1 cuando se ejectuta un enunciado SELECT. Si la columna muestra S/N entonces RecordCount() es simulado cuando la variable global $ADODB_COUNTRECS=true (esto es el valor por omision). Nota que para recordsets muy grandes, puede ser mejor desabilitar la emulacion de RecordCount()debido a la gran cantidad de memoria para leer el recordset para contarlo. Tambien hay una penalizacion del 40-50% si se tiene que emular la funcion. Es emulada en la mayoria de las bases de datos excepto para PostgreSQL y MySQL. Esta variable es verificada cada vez que se ejecuta un SELECT, por lo que puedes escoger selectivamente cuales recordset contar.


Tutoriales

Ejemplo 1: SELECT

Tarea: Conectarse al DSN MS Access de la base de datos Nortwind, mostrar las primeras 2 columnas de cada renglon.

En este ejemplo, se crea un objeto ADOConnection que representa la conexion a la base de datos. La conexion se inicia con PConnect, que es una conexion persistente. Para interrogar a las base de datos llamamos a la funcion ADOConnection.Execute() . Esto regresa un objeto ADORecordSet que es de hecho un cursor que contiene el renglon actual en el arreglo fields[]. Tambien usamos el metodo MoveNext() para avanzar de renglon en renglon.

Nota: Una funcion muy util que NO usamos en este ejemplo es SelectLimit, que nos permite limitar la cantidad de renglones a mostrar.

<?
include('adodb.inc.php');	   # Carga el codigo comun de ADOdb
$conn = &ADONewConnection('access');	# crea la conexion
$conn->PConnect('northwind');   # se conecta a la base detos northwind via el DSN MS-Access
$recordSet = &$conn->Execute('select * from products');
if (!$recordSet) 
	print $conn->ErrorMsg();
else
while (!$recordSet->EOF) {
	print $recordSet->fields[0].' '.$recordSet->fields[1].'<BR>';
	$recordSet->MoveNext();
}

$recordSet->Close(); # opcional
$conn->Close(); # opcional

?>

La variable $recordSet obtenida contiene el renglon actual en el arreglo $recordSet->fields , indexado por numero de columna (empezando en cero). Usamos el metodo MoveNext() para avanxar al renglon siguiente. La propiedad EOF tiene valor verdadero (true) cuando se llega al final del archivo. Si hay algun error en el Execute() se regresa falso (false) en lugar del recordset.

El arreglo $recordSet->fields[] es generado por la extension PHP de la base de datos correspondiente. Algunas extensiones unicamente indexan por numero y no por nombre del campo. Para provocar que se indexe por nombre (o sea con arreglos asociativos) hay que usar la funcion SetFetchMode. Cada recordset almacena y usa el metodo que estuvo vigente cuando se creo el recordset con un Execute() o SelectLimit().

	$db->SetFetchMode(ADODB_FETCH_NUM);
	$rs1 = $db->Execute('select * from table');
	$db->SetFetchMode(ADODB_FETCH_ASSOC);
	$rs2 = $db->Execute('select * from table');
	print_r($rs1->fields); # muestra array([0]=>'v0',[1] =>'v1')
	print_r($rs2->fields); # muestra array(['col1']=>'v0',['col2'] =>'v1')

Para obtener el numero de renglones en el enunciado SELECT, se puede usar la funcion $recordSet->RecordCount(). Observa que la funcion puede regresar -1 si no se puede determinar la cantidad de renglones.

Ejemplo 2: SELECT Avanzado con objetos de campos

Seleccionar los registros de una tabla, desplegar las primeras dos columnas. Si la segunda columna es un campo DATE o TIMESTAMP entonces reformatear la fecha al formato americano.

<?php
include('adodb/adodb.inc.php');	   # Carga el codigo comun de ADOdb
$conn = &ADONewConnection('access');	# crea la conexion
$conn->PConnect('northwind');   # se conecta al DSN de northwind 
$recordSet = &$conn->Execute('select CustomerID,OrderDate from Orders');
if (!$recordSet) 
	print $conn->ErrorMsg();
else
while (!$recordSet->EOF) {
	$fld = $recordSet->FetchField(1);
	$type = $recordSet->MetaType($fld->type);

	if ( $type == 'D' || $type == 'T') 
		print $recordSet->fields[0].' '.
			$recordSet->UserDate($recordSet->fields[1],'m/d/Y').'<BR>';
	else 
		print $recordSet->fields[0].' '.$recordSet->fields[1].'<BR>';

	$recordSet->MoveNext();
}
$recordSet->Close(); # opcional
$conn->Close(); # opcional

?>

En este ejemplo se verifica el tipo de campo de la segunda columna usando la funcion FetchField(). Esto obtiene un objeto con al menos tres propiedades.

Posteriormente usamos MetaType() para traducir el tipo nativo a un tipo generico. Actualmente estan definidos los siguientes tipos genericos:

Si el metatype es de tipo date o timestamp, entonces se imprime usando la funcion definida por el usuario UserDate(), la cual convierte la cadena de texto en formato PHP SQL al formato definido por el usuario. otro uso para la funcion MetaType() es para validar los datos antes de ejecutar un enunciado SQL de INSERT o UPDATE.

Ejemplo 3: Insert

Insertar un renglon en la tabla Orders conteniendo fechas y cadenas de caracteres que necesitan ser encomillados antes de que sean aceptados por la base de datos, por ejemplo el apostrofo en la palabra John's.

<?php
include('adodb/adodb.inc.php');	   # carga el codigo comun de ADOdb
$conn = &ADONewConnection('access');	# crea la connection

$conn->PConnect('northwind');   # Se conecta al DSN northwind 
$shipto = $conn->qstr("John's Old Shoppe");

$sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) ";
$sql .= "values ('ANATR',2,".$conn->DBDate(time()).",$shipto)";

if ($conn->Execute($sql) === false) {
	print 'error al insertar: '.$conn->ErrorMsg().'<BR>';
}
?>

En este ejemplo observamos el manejo avanzado de encomillado y de fechas que tiene ADOdb. El valor unix del tiempo (que es un entero largo) se formatea correctamente para Access con DBDate(), y se usa el caracter adecuado para encomillar John's Old Shoppe, lo correcto es John''s Old Shoppe y no lo que hace PHP normalmente John's Old Shoppe con qstr().

Observa el manejo de errores en el enunciado Execute. Se obtiene Falso si hubo un error al ejectutar Execute(). El mensaje de error del ultimo error encontrado se muestra con ErrorMsg(). Ojo: Se necesita que php_track_errors este habiliatado para que se salven los mensajes de error.

Ejemplo 4: Depurando

<?php
include('adodb/adodb.inc.php');	   # carga el codigo comun de ADOdb
$conn = &ADONewConnection('access');	# crea la conexion
$conn->PConnect('northwind');   # se conecta al DSN de northwind
$shipto = $conn->qstr("John's Old Shoppe");
$sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) ";
$sql .= "values ('ANATR',2,".$conn->FormatDate(time()).",$shipto)";
$conn->debug = true;
if ($conn->Execute($sql) === false) print 'error inserting';
?>

En el ejemplo anterior se activo la depuracion asignando debug = true. Esto desplegara los enunciados SQL antes de ejectuarse, y ademas mostrara cualquier mensaje de error. En este caso no hay necesidad de llamar la funcion ErrorMsg(). Para mostrar el contenido del recordset, ve el ejemplo de rs2html().

Tambien ve la seccion de Manejadores de error a la medida.

Ejemplo 5: MySQL y Menus

Conectarse a la base de datos MySQL agora, y generar un menu <select> a partir de un enunciado SQL donde cada leyenda del <option> se saca de la primera columna y el valor a enviar al servidor se obtiene de la segunda columna.

<?php
include('adodb/adodb.inc.php'); # Carga el codigo comun de ADOdb
$conn = &ADONewConnection('mysql');  # crea la conexion
$conn->PConnect('localhost','userid','','agora');# se conecta a la base de datos agora
$sql = 'select CustomerName, CustomerID from customers';
$rs = $conn->Execute($sql);
print $rs->GetMenu('GetCust','Mary Rosli');
?>

Aqui definimos un menu llamado GetCust, con la opcion del menu 'Mary Rosli' pre seleccionada. Ve el metodo GetMenu(). Tambien hay funciones que regresan el recordset como un arreglo: GetArray(), y como un arreglo asociativo con la primera columna como llave: GetAssoc().

Ejemplo 6: Conectarse a dos bases de datos al mismo tiempo

<?php
include('adodb/adodb.inc.php');	 # Carga el codigo comun de ADOdb
$conn1 = &ADONewConnection('mysql');  # Crea la conexion a mysql
$conn2 = &ADONewConnection('oracle');  # Crea la conexion a oracle

$conn1->PConnect($server, $userid, $password, $database);
$conn2->PConnect(false, $ora_userid, $ora_pwd, $oraname);

$conn1->Execute('insert ...');
$conn2->Execute('update ...');
?>

Ejemplo 7: Generando enunciados SQL de Update e Insert

Desde la version 4.56 de ADOdb,manejamos AutoExecute(), el cual simplifica las cosas proporcionando una funcion de nivel superior que encapsula los llamados a GetInsertSQL() y GetUpdateSQL(). Por ejemplo, un INSERT puede hacerse asi:

    $record["firstname"] = "Bob"; 
    $record["lastname"] = "Smith"; 
    $record["created"] = time(); 
    $insertSQL = $conn->AutoExecute($rs, $record, 'INSERT'); 
y un UPDATE asi:
    $record["firstname"] = "Caroline"; 
    $record["lastname"] = "Smith"; # Actualiza iel apellido de Caroline de Miranda a Smith 
    $insertSQL = $conn->AutoExecute($rs, $record, 'UPDATE', 'id = 1'); 

El resto de esta section esta desactualizada:

A partir de la version 1.31 de ADOdb 1.31 hay dos metodos nuevos para recordset: GetUpdateSQL( ) y GetInsertSQL( ). Esto nos permite ejecutar un "SELECT * FROM table query WHERE...", copiar los valores de $rs->fields, modificar los campos y generar el SQL correcto para hacer un update o insert en la tabla.

Mostraremos como pueden ser empleadas las funciones en una tabla con los siguiente campos: (ID, FirstName, LastName, Created).

Antes de que estos metodos puedan ser invocados, necesitas inicializar el recordset ejecutando un select en la tabla. En base a una idea de Jonathan Younger jyounger#unilab.com. a partir de la version de 2.42 de ADOdb, puedes mandar como parametro el nombre de la tabla en lugar del recordset y se generara un enunciado insert para la tabla.

<?php
#=====================================================
# codigo de Ejemplo de GetUpdateSQL()y GetInsertSQL() 
#=====================================================
include('adodb/adodb.inc.php');
include('adodb/tohtml.inc.php');

#==========================
# Codigo para probar un insert

$sql = "SELECT * FROM ADOXYZ WHERE id = -1"; 
# Selecciona un registro en blanco de la base de datos

$conn = &ADONewConnection("mysql");  # crea la conexion
$conn->debug=1;
$conn->PConnect("localhost", "admin", "", "test"); # se conecta a la base de datos testdb
$rs = $conn->Execute($sql); # Ejecuta la busqueda y obtiene el recordset vacio

$record = array(); # Inicializa el arreglo que contiene los datos a insertar

# Asignar el valor de los campos en el registro
# Observa que el nombre de los campos pueden ser mayusculas o minusculas
$record["firstname"] = "Bob";
$record["lastNamE"] = "Smith";
$record["creaTed"] = time();

# Mandar como parametro el recordset vacio y el arreglo conteniendo los datos a insertar
# a la funcion GetInsertSQL. Esta procesara los datos y regresara un enunciado SQL
# para procesar el INSERT.
$insertSQL = $conn->GetInsertSQL($rs, $record);

$conn->Execute($insertSQL); # Inserta el registro en la base de datos

#==========================
# Codigo de prueba para UPDATE

$sql = "SELECT * FROM ADOXYZ WHERE id = 1"; 
# Selecciona el registro a actualizar

$rs = $conn->Execute($sql); # Executa la busqueda y obtiene el registro a actualizar.

$record = array(); # Inicializa el arreglo que contiene los datos a modificar

# Asignar el valor de los campos en el registro
# Observa que el nombre de los campos pueden ser mayusculas o minusculas
$record["firstname"] = "Caroline";
$record["LasTnAme"] = "Smith"; # Corrige el apellido de Carolina de Miranda a Smith

# Mandar como parametro el recordset y el arreglo conteniendo los datos a actualizar
# a la funcion GetUpdateSQL. Esta procesara los datos y regresara el enunciado sql del
# update necesario con clausula WHERE correcta.
# Si no se modificaron los datos no regresa nada.
$updateSQL = $conn->GetUpdateSQL($rs, $record);

$conn->Execute($updateSQL); # Actualiza el registro en la base de datos
$conn->Close();
?>
$ADODB_FORCE_TYPE

El comportamiento de AutoExecute(), GetUpdateSQL() y GetInsertSQL() al convertir variables PHP vacias o nulas a varibales SQL is controlado por la nueva variable global $ADODB_FORCE_TYPE. Asignale alguno de los valores enlistados abajo. El valor por omision es ADODB_FORCE_VALUE (3):

0 = ignorar campos vacios. Todos los campos vacios en el arreglo son ignorados.
1 = forzar null. Todos los campos vacios, con valor null (de php) o con la cadena 'null' se cambian al 
    valor SQL de NULL.
2 = forzar vacio. Todos los campos vacios, con valor null (de php) o con la cadena 'null' se cambian a la 
    cadena vacia de SQL '' o a 0.
3 = forzar valor value. El valor se deja como esta. Lo null (de php) y las cadenas 'null' se cambien a NULL 
    de SQL y los camnpos vacios con '' se convierten a vacio de SQL ''. 

define('ADODB_FORCE_IGNORE',0);
define('ADODB_FORCE_NULL',1);
define('ADODB_FORCE_EMPTY',2);
define('ADODB_FORCE_VALUE',3);

Gracias a Niko (nuko#mbnet.fi) por el codigo de $ADODB_FORCE_TYPE.

Nota: la constante ADODB_FORCE_NULLS es obsoleta desde la version 4.52 y es ignorada. Asigna $ADODB_FORCE_TYPE = ADODB_FORCE_NULL para un comportamiento similar.

Desde la version 4.62, el nombre de la tabla a ser usada puede ser modificado al poner $rs->tableName antes de invocar AutoExecute(), GetInsertSQL() o GetUpdateSQL().

Ejemplo 8: Implementando cursores con Siguiente y Anterior

El siguiente codigo crea un navegador por paginas muy sencillo, donde puedes navegar de pagina en pagina de un recordset.

<?php
include_once('adodb/adodb.inc.php');
include_once('adodb/adodb-pager.inc.php');
session_start();

$db = NewADOConnection('mysql');

$db->Connect('localhost','root','','xphplens');

$sql = "select * from adoxyz ";

$pager = new ADODB_Pager($db,$sql);
$pager->Render($rows_per_page=5);
?>

Esto crea un paginador de registros que es asi:

|<   <<   >>   >|  
ID First Name Last Name Date Created
36  Alan  Turing  Sat 06, Oct 2001 
37  Serena  Williams  Sat 06, Oct 2001 
38  Yat Sun  Sun  Sat 06, Oct 2001 
39  Wai Hun  See  Sat 06, Oct 2001 
40  Steven  Oey  Sat 06, Oct 2001 
Page 8/10

El numero de renglones a mostrar en cada pagina se controla con el metodo Render($rows). Si no le mandas ningun parametro a Render(), ADODB_Pager toma como valor por omision 10 renglones por pagina.

Puedes controlar el titulo de cada columna modificando el SQL (funciona en la mayoria de las bases de datos):

$sql = 'select id as "Clave", firstname as "Nombre", 
		  lastname as "Apellido", created as "Fecha Creacion" 
from adoxyz';

El codigo anterior lo puedes encontrar en los ejemplos incluidos con la distribucion en el archivo adodb/tests/testpaging.php, y la clase ADODB_Pager esta en adodb/adodb-pager.inc.php. El codigo de ADODB_Pager puede ser modificado por el programador para que las ligas sean imagenes en lugar de textos, y el aburrido fondo blanco tenga colores mas interesantes.

Tambien puedes habilitar que se muestre HTML modificando $pager->htmlSpecialChars = false.

Parte del codigo usado aqui fue proporcionado por Iván Oliva and Cornel G.

Ejemplo 9: Exportando a formatos delimitados por tabulador o comas

Se proporcionan funciones de ayuda para exportar en formatos delimitado por coma (CSV) y delimitado por tabuladores:

<?php
include_once('adodb/toexport.inc.php');
include_once('adodb/adodb.inc.php');
$db = &NewADOConnection('mysql'); $db->Connect($server, $userid, $password, $database); $rs = $db->Execute('select fname as "Nombre", surname as "Apellido" from table'); print "<pre>"; print rs2csv($rs); # obtenemos un texto en formao CSV print '<hr>'; $rs->MoveFirst(); # Nota, en algunas bases de datos no funciona el MoveFirst print rs2tab($rs,false); # obtenemos el texto delimitado por tabuladores # false == omite el nombre de los campos en el primer renglon print '<hr>'; $rs->MoveFirst(); rs2tabout($rs); # manda a la salida estandar (stdout) (tambien existe la funcion rs2csvout) print "</pre>"; $rs->MoveFirst(); $fp = fopen($path, "w"); if ($fp) { rs2csvfile($rs, $fp); # Escribe a un archivo (tambien existe la funcion rs2tabfile) fclose($fp); } ?>

Los regresos de carro y saltos de linea (CR/LF) se convierten a espacios. Los nombres de los campos se muestran en el primer renglon del texto. Las cadenas de caracteres que contengan el caracter de delimitador se encierran entre comillas dobles. Las comillas dobles se encierran tambien entre comillas. Esto cumple las guias de importacion y exportacion de MS Excel.

Todas las funciones anteriores tienen un ultimo parametro opcional, $addtitles que tiene como valor por omision true. Cuando se le manda false se omite el nombre de los campos en la primera linea.

Ejemplo 10: Filtros a la medida

Algunas veces se desea pre procesar todos los renglones de un recordset antes de usarlos. Por ejemplo, deseamos convertir a mayusculas todo el texto de un recordset.

<?php
include_once('adodb/rsfilter.inc.php');
include_once('adodb/adodb.inc.php');

// Procesar con ucwords() cada elemento en un recordset
function do_ucwords(&$arr,$rs)
{
	foreach($arr as $k => $v) {
		$arr[$k] = ucwords($v);
	}
}

$db = NewADOConnection('mysql');
$db->PConnect('server','user','pwd','db');

$rs = $db->Execute('select ... from table');
$rs = RSFilter($rs,'do_ucwords');

La funcion RSFilter requiere dos parametros, el recordset y el nombre de la funcion del filtro. Regresa el recordset apuntando nuevamente al primer registro. La funcion filter requiere otros dos parametros, el renglon como un arreglo, y el objeto recordset. Para compatibilidad con futuras versiones se recomienda no usar el objeto recordset original.

Ejemplo 11: Transacciones Inteligentes

El metodo anterior de manejo de transaciones requeria que hicieras esto
$conn->BeginTrans();
$ok = $conn->Execute($sql);
if ($ok) $ok = $conn->Execute($sql2);
if (!$ok) $conn->RollbackTrans();
else $conn->CommitTrans();
Esto es muy compliado para proyectos largos debido a que debes de ir siguiendole la huella a los errores. Con transacciones inteligentes es mas sencillo. Se empieza una transaccion invocando StartTrans():
$conn->StartTrans();
$conn->Execute($sql);
$conn->Execute($Sql2);
$conn->CompleteTrans();
El metodo CompleteTrans() detecta cuando ocurrio un error SQL, y procesara Rollback o Commit segun sea necesario. Para forzar especificamente un evento rollback si no ha ocurrido un error, usa el metodo FailTrans(). Toma en cuenta que el rollback se efectua HASTA el CompleteTrans(), y no con el FailTrans().
$conn->StartTrans();
$conn->Execute($sql);
if (!CheckRecords()) $conn->FailTrans();
$conn->Execute($Sql2);
$conn->CompleteTrans();

Tambien se puede verificar si una transaccion a fallado usando HasFailedTrans(), el cual nos devuelve verdadero si se ha invocado FailTrans() o si hubo un error en la ejecucion de los SQL. Asegurese de usar HasFailedTrans() antes de llamar a CompleteTrans(), ya que esta unicamente funciona dentro de StartTrans y CompleteTrans.

Finalmente, StartTrans/CompleteTrans son anidables, y unicamente el bloque exterior se ejecuta. En contraste BeginTrans/CommitTrans/RollbackTrans NO son anidables.

$conn->StartTrans();
$conn->Execute($sql);
  $conn->StartTrans();    # ignorado
  if (!CheckRecords()) $conn->FailTrans();
  $conn->CompleteTrans(); # ignorado
$conn->Execute($Sql2);
$conn->CompleteTrans();

Nota: Actualmente no se manajean 'Savepoints'.

Usando manejadores de errores a la medida y PEAR_Error

ADOdb maeja las exception de PHP5. Solamente incluye adodb-exceptions.inc.php y ya puedes atrapar las excepciones conforme ocurran los errores.

   include("../adodb-exceptions.inc.php"); 
   include("../adodb.inc.php");     
   try { 
      $db = NewADOConnection("oci8://scott:bad-password@mytns/"); 
   } catch (exception $e) { 
      var_dump($e);
      adodb_backtrace($e->gettrace());
   } 

ADOdb proporciona dos estilos de manejo de errores que se pueden ajustar a nuestras necesidades. El primero esta en el archivo adodb-errorhandler.inc.php. Este utiliza las funciones estandard de PHP error_reporting para controlar los tipos de mensajes de error a mostrar, y trigger_error que invoca al manejador de errores usual de PHP.

Si se incluye el archivo anterior se provoca que se invoque a la funcion trigger_error($errorstring,E_USER_ERROR) cuando:
(a) Falla Connect() o PConnect(), o
(b) Una funcion que ejecuta un enunciado SQL como Execute() or SelectLimit() tiene un error.
(c) Parezca que GenID() esta en un ciclo sin fin.

La variable $errorstring generada por ADOdb contra informacion util de depuracion similar a los datos del error.log siguiente. El archivo adodb-errorhandler.inc.php debe de ser incluido antes de crear cualquier objeto ADOConnection.

Si se define error_reporting(0), ningun error llegara al manejador de errores. Si se define error_reporting(E_ALL), todos los errores llegaran al manejador de errores. Ademas es ncesario usar ini_set("display_errors", "0" or "1") para controlar el despliegue de errores.

<?php
error_reporting(E_ALL); # pasa cualquier mensaje de error al manajeador de errores
include('adodb/adodb-errorhandler.inc.php');
include('adodb/adodb.inc.php');
include('adodb/tohtml.inc.php');
$c = NewADOConnection('mysql');
$c->PConnect('localhost','root','','northwind');
$rs=$c->Execute('select * from productsz'); # Table invalida productsz');
if ($rs) rs2html($rs);
?>

Si desea llevar una bitacora de los mensajes de error, puede definir las siguientes constantes opcionales ADODB_ERROR_LOG_TYPE y ADODB_ERROR_LOG_DEST. ADODB_ERROR_LOG_TYPE es el tipo de mensaje (ver error_log en el manual de PHP). En este ejemplo lo asignamos a 3 que significa registar en el archivo definido por la constante ADODB_ERROR_LOG_DEST.

<?php
error_reporting(E_ALL); # reporta todos los errores
ini_set("display_errors", "0"); # pero no los muestra en la pantalla
define('ADODB_ERROR_LOG_TYPE',3);
define('ADODB_ERROR_LOG_DEST','C:/errors.log');
include('adodb/adodb-errorhandler.inc.php');
include('adodb/adodb.inc.php');
include('adodb/tohtml.inc.php');

$c = NewADOConnection('mysql');
$c->PConnect('localhost','root','','northwind');
$rs=$c->Execute('select * from productsz'); ## Tabla invalida productsz
if ($rs) rs2html($rs);
?>
El siguiente mensaje se registrara en el archivo error.log:
(2001-10-28 14:20:38) mysql error: [1146: Table 'northwind.productsz' doesn't exist] in
 EXECUTE("select * from productsz")

PEAR_ERROR

El segundo manjeador de errores es adodb-errorpear.inc.php. Este crea una objeto de la clase PEAR_Error cada vez que hay un error. El ultimo objeto PEAR_Error creado puede ser obtenido usando la funcion ADODB_Pear_Error().
<?php
include('adodb/adodb-errorpear.inc.php');
include('adodb/adodb.inc.php');
include('adodb/tohtml.inc.php');
$c = NewADOConnection('mysql');
$c->PConnect('localhost','root','','northwind');
$rs=$c->Execute('select * from productsz'); #invalid table productsz');
if ($rs) rs2html($rs);
else {
	$e = ADODB_Pear_Error();
	echo '<p>',$e->message,'</p>';
}
?>

Puedes usar una clase derivada de la clase PEAR_Error definiendo la constante ADODB_PEAR_ERROR_CLASS antes de incluir adodb-errorpear.inc.php. Para facilitar la depuracion, se puede fijar el manejador por omision al principio el codigo PHP a PEAR_ERROR_DIE, lo cual provocara que se muestre el mensaje de error y que se detenga la ejecucion del codigo:

include('PEAR.php');
PEAR::setErrorHandling('PEAR_ERROR_DIE');

Toma en cuenta que ADOdb no regresa un objeto PEAR_Error cuando ocurre un error. Se regresa falso. Hay que llamar a ADODB_Pear_Error() para obtener el ultimo error o usa la tecnica de PEAR_ERROR_DIE.

MetaError y MetaErrMsg

SI tu necesitas mensajes que error que funcionen en varios manejadores de bases de datos, entonces usa MetaError(), que regresa un numero de error virtual basado en el sistema de numeracion de errores de PEAR DB, y MetaErrMsg().

Mensajes de Error

Los mensajes de error son mostrados usando el metodo estatico ADOConnnection::outp($msg,$newline=true). Normalmente se manda el mensaje al cliente (IE, Netscape, Mozilla, etc.). Se puede modificar esto para efectuar un registro de errores.

Nombres de DSN

ADOdb ahora tambien soporta conectarse usando DSN con el estilo de PEAR. Un nombre DSN es una cadena de texto con el siguiente formato:

$dsn = "$driver://$usuario:$contraseña@$servidor/$basededatos";

Un ejemploe:

   $username = 'root';
$password = '';
$hostname = 'localhost';
$databasename = 'xphplens';
$driver = 'mysql';
$dsn = "$driver://$username:$password@$hostname/$databasename"
$db = NewADOConnection();
# DB::Connect($dsn) also works if you include 'adodb/adodb-pear.inc.php' at the top
$rs = $db->query('select firstname,lastname from adoxyz');
$cnt = 0;
while ($arr = $rs->fetchRow()) {
print_r($arr); print "<br>";
}

Mas informacion y ejemplos de conexion usando el formato DSN.

Compatibilidad con PEAR

Soportamos DSNs (ver arriba), y las siguientes funciones:
 DB_Common
    query - si regresa PEAR_Error si hay error
    limitQuery - si regresa PEAR_Error si hay error
    prepare - no regresa PEAR_Error si hay error
    execute - no regresa PEAR_Error si hay error
    setFetchMode - maneja ASSOC y ORDERED
    errorNative
    quote
    nextID
    disconnect
    
    getOne
    getAssoc
    getRow
    getCol
    
 DB_Result
    numRows - regresa -1 si no esta soportado
    numCols
    fetchInto - no maneja indicar el fetchmode
    fetchRows - no maneja indicar el fetchmode
    free

Guardando recordsets en Memoria Intermedia (Caching)

ADOdb maneja el caching de recordsets usando las funciones CacheExecute( ), CachePageExecute( ) y CacheSelectLimit( ). Son similares a las funciones sin cache excepto que tienen un nuevo primer parametro, $secs2cache.

Un ejemplo:

<?php
include('adodb/adodb.inc.php'); # carga el codigo comun de ADOdb
$ADODB_CACHE_DIR = '/usr/ADODB_cache';
$conn = &ADONewConnection('mysql');  # crea la conexion
$conn->PConnect('localhost','userid','','agora');# se conecta a agora
$sql = 'select CustomerName, CustomerID from customers';
$rs = $conn->CacheExecute(15,$sql);

El primer parametros es el numero de segundos a almacenar la busqueda. Las siguientes llamadas a esa misma busqueda usaran la version almacenda en memoria en el directorio $ADODB_CACHE_DIR. Para provocar que un busqueda se ejecute y se limpie del cache, hay que inviocar CacheExecute() con el primer parametro en cero. Tambien sirve invocar la funcion CacheFlush($sql).

Por seguridad se recomienda que tengas register_globals=off en el archivo php.ini si usas $ADODB_CACHE_DIR.

A partir de la vsersion 1.80 de ADOdb, el parametro secs2cache es opcional en las funciones CacheSelectLimit() y CacheExecute(). Si se omiten, usaran el valor que tenga el parametro $connection->cacheSecs, por omision son 60 minutos.

	$conn->Connect(...);
	$conn->cacheSecs = 3600*24; # 24 horas de cache
	$rs = $conn->CacheExecute('select * from table');

Observe que magic_quotes_runtime debe de estar desactivado. Mas informacion, y no cambie $ADODB_FETCH_MODE (o SetFetchMode) ya que el recordset en memoria usara el valor de $ADODB_FETCH_MODE que tenia cuando el SQL fue ejecutada.

Tablas Pivote

Desde la version 2.30, ADOdb maneja la generacion de SQL para crear tablas pivote, tambien conocidas como tablas cruzadas. Para una mayor explicacion lea este tutorial de DevShed Cross-Tabulation tutorial. Suponemos que la base de datos maneja la expresion SQL case-when.

En este ejemplo se usara la base de datos Northwind de MS Access. En la base de datos hay un tabla de productos, y deseamos analizar esta tabla proveedores versus categoria de productos. Se mostraran los proveedores uno en cada renglon, y tabulado contra categoria. De esta manera en base a la tabla de la izquierda se generara la tabla pivote de la derecha:

Proveedor Categoria
proveedor1 categoria1
proveedor2 categoria1
proveedor2 categoria2
-->
  categoria1 categoria2 total
proveedor1 1 0 1
proveedor2 1 1 2

El seiguiente codigo generara el SQL para la tabla pivote:

# Consultar la tabla principal de "productos" 
# Poner los renglones al campo CompanyName
# y las columnas al valor de Categories
# definir las ligas para unir las tablas de busqueda
# "categories" y "suppliers"
#
 include "adodb/pivottable.php";
 $sql = PivotTableSQL(
 	$conn,                                     # conexion adodb
 	'products p ,categories c ,suppliers s',   # tablas
	'CompanyName',                             # rows (multiple fields allowed)
	'CategoryName',                            # column to pivot on 
	'p.CategoryID = c.CategoryID and s.SupplierID= p.SupplierID' # joins/where
);

Esto generara el siguiente SQL:

SELECT CompanyName,
SUM(CASE WHEN CategoryName='Beverages' THEN 1 ELSE 0 END) AS "Beverages",
SUM(CASE WHEN CategoryName='Condiments' THEN 1 ELSE 0 END) AS "Condiments",
SUM(CASE WHEN CategoryName='Confections' THEN 1 ELSE 0 END) AS "Confections",
SUM(CASE WHEN CategoryName='Dairy Products' THEN 1 ELSE 0 END) AS "Dairy Products",
SUM(CASE WHEN CategoryName='Grains/Cereals' THEN 1 ELSE 0 END) AS "Grains/Cereals",
SUM(CASE WHEN CategoryName='Meat/Poultry' THEN 1 ELSE 0 END) AS "Meat/Poultry",
SUM(CASE WHEN CategoryName='Produce' THEN 1 ELSE 0 END) AS "Produce",
SUM(CASE WHEN CategoryName='Seafood' THEN 1 ELSE 0 END) AS "Seafood",
SUM(1) as Total
FROM products p ,categories c ,suppliers s WHERE p.CategoryID = c.CategoryID and s.SupplierID= p.SupplierID
GROUP BY CompanyName

Tambien se puede tomar como eje una columna (campo) numerico y generar totales usando rangos. Este codigo se reviso en la version 2.41 de ADOdb y no es compatible con versiones anteriores. El segundo ejemplo es:

 $sql = PivotTableSQL(
 	$conn,                                      # conexion adodb 
 	'products p ,categories c ,suppliers s',    # tablas
	'CompanyName',                              # renglones (se permiten, muiples campos)
   array(                                       # rango de columnas
	' 0 '      => 'UnitsInStock <= 0',
	"1 to 5"   => '0 < UnitsInStock and UnitsInStock <= 5',
	"6 to 10"  => '5 < UnitsInStock and UnitsInStock <= 10',
	"11 to 15" => '10 < UnitsInStock and UnitsInStock <= 15',
	"16+"      => '15 < UnitsInStock'
	),
	' p.CategoryID = c.CategoryID and s.SupplierID= p.SupplierID', # joins/where
	'UnitsInStock',                             # sum this field
	'Sum '                                      # sum label prefix
);

Lo anterior generar este enunciado SQL:

SELECT CompanyName,
SUM(CASE WHEN UnitsInStock <= 0 THEN UnitsInStock ELSE 0 END) AS "Sum 0 ",
SUM(CASE WHEN 0 < UnitsInStock and UnitsInStock <= 5 THEN UnitsInStock ELSE 0 END) AS "Sum 1 to 5",
SUM(CASE WHEN 5 < UnitsInStock and UnitsInStock <= 10 THEN UnitsInStock ELSE 0 END) AS "Sum 6 to 10",
SUM(CASE WHEN 10 < UnitsInStock and UnitsInStock <= 15 THEN UnitsInStock ELSE 0 END) AS "Sum 11 to 15",
SUM(CASE WHEN 15 < UnitsInStock THEN UnitsInStock ELSE 0 END) AS "Sum 16+",
SUM(UnitsInStock) AS "Sum UnitsInStock",
SUM(1) as Total,
FROM products p ,categories c ,suppliers s WHERE p.CategoryID = c.CategoryID and s.SupplierID= p.SupplierID
GROUP BY CompanyName


REFERENCIA de la Clase

Los parametros de funcion encerrados entre [ ] son opcionales.

Variables Globales

$ADODB_COUNTRECS

Si el API de la base de datos no cuenta el numero de registros encontrados por el enunciado SELECT, la funcion RecordCount() es simulada cuando la variable global $ADODB_COUNTRECS tiene el valor true, que es el valor por omision. Esto se simula almacenando los registros, lo cual puede consumir mucha memoria para recordset muy grandes. Asignele el valor falso a esta variable para un mejor rendimiento. El valor de esta variable se verifica cada vez que se ejecuta una consulta, por lo cual se puede escoger cuales recordsets se desean contar.

$ADODB_CACHE_DIR

Si se utiliza la memoria intermedia (cache), esta variable contiene el directorio donde se almacenan los recordsets. Hay que definirla antes de invocar cualquier funcion de cache como CacheExecute( ). Por razones de seguridad se recomienda tener register_globals=off en el archivo php.ini si se usa el cache.

Con Unix y Apache, hay que modificar los permisos del directorio de cache a algo similar a lo siguiente:

chown -R apache /ruta/al/cache
chgrp -R apache /ruta/al/cache

$ADODB_ANSI_PADDING_OFF

Nos indica cuando hay que eliminar los espacios a la derecha de los campos CHAR (y tambien VARCHAR en el caso de ibase/firebird). Hay que asignarle true para que los elimine, el valor por omision es false. Por el momento funciona para los drivers de oci8po, ibase y firebird. Se agrego en la version 4.01 de ADOdb.

$ADODB_LANG

Determina el lenguaje que usa la funcion MetaErrorMsg(). El valor por omision es 'en', que significa mensajes en ingles. Para ver que lenguajes estan disponibles, vea los archivos en adodb/lang/adodb-$leng.inc.php, donde $leng son los lenguajes disponibles.

$ADODB_FETCH_MODE

Determina como se obtienen los arreglos generados por los recordsets. Los recordsets salvan este valor cuando se crean (ej. al Execute( ) o SelectLimit( )), y cualquier cambio siguiente al valor de $ADODB_FETCH_MODE no tiene efecto en los recordsets existentes, unicamente en los recordsets creados posteriormente.

Se difinen la siguientes constantes:

define('ADODB_FETCH_DEFAULT',0);
define('ADODB_FETCH_NUM',1);
define('ADODB_FETCH_ASSOC',2);
define('ADODB_FETCH_BOTH',3);

Un ejemplo:

	$ADODB_FETCH_MODE = ADODB_FETCH_NUM;
	$rs1 = $db->Execute('select * from table');
	$ADODB_FETCH_MODE = ADODB_FETCH_ASSOC;
	$rs2 = $db->Execute('select * from table');
	print_r($rs1->fields); # muestra array([0]=>'v0',[1] =>'v1')
	print_r($rs2->fields); # muestra array(['col1']=>'v0',['col2'] =>'v1')

Como se observa en el ejemplo anterior, cada recordset almacena y usa un metodo diferente en base al valor que tenia $ADODB_FETCH_MODE cuando se creo el recordset al llamar el Execute().

Si no se le asigna valor, el valor por omision es ADODB_FETCH_DEFAULT. El comportamiento en este modo es diferente en cada driver, por lo cual no confie en ADODB_FETCH_DEFAULT. Para portabilidad, se recomienda usar ADODB_FETCH_NUM o ADODB_FETCH_ASSOC. Algunos drivers no manejan ADODB_FETCH_BOTH.

Funcion SetFetchMode

Algunos programadores prefieren usar una solucion mas orientada a objetos, donde el metodo de recuperacion se selecciona por medio de una funcion del objeto (metodo), SetFetchMode. Una vez que esta funcion se usa para un objeto de conexion, este objeto ignorara la variable global $ADODB_FETCH_MODE y solo usara la propiedad interna fetchMode.

	$db->SetFetchMode(ADODB_FETCH_NUM);
	$rs1 = $db->Execute('select * from table');
	$db->SetFetchMode(ADODB_FETCH_ASSOC);
	$rs2 = $db->Execute('select * from table');
	print_r($rs1->fields); # muestra array([0]=>'v0',[1] =>'v1')
	print_r($rs2->fields); # muestra array(['col1']=>'v0',['col2'] =>'v1')

Para obtener el valor anterior del metodo de recuperacion, se puede usar la propiedad $db->fetchMode, o el valor regresado por SetFetchMode( ).

ADODB_ASSOC_CASE

Para algunos drivers se puede controlar si los nombres de los campos de los indices de los arreglos asociativos esten en mayusculas o minusculas. Para los drivers de sybase, oci8po, mssql, odbc e ibase y todos los otros drivers derivados de ellos, ADODB_ASSOC_CASE generara por omision recordset donde los nombres de los campos esten en minusculas. Hay tres posibles valores de la constante ADODB_ASSOC_CASE:

0 = Nombres de campo en minusculas. $rs->fields['orderid']
1 = Nombres de campo en mayusculas. $rs->fields['ORDERID']
2 = Nombres de campo sin cambio. $rs->fields['OrderID'] -- Valor por omision desde ADOdb 2.90.

Para usarla hay que declarala antes de incluir adodb.inc.php.

define('ADODB_ASSOC_CASE', 2); # No cambiar las letras para ADODB_FETCH_ASSOC
include('adodb/adodb.inc.php');

$ADODB_FORCE_TYPE

Ve el tutorial de GetUpdateSQL.


ADOConnection

Objeto que realiza la conexion a la base de datos, ejecuta enunciados SQL y tiene un conjunto de funciones de utileria para estandirzar el formato de enunciados SQL para cosas coma la concatenacion y el formateo de fechas.

Campos (propiedades) de ADOConnection

databaseType: Nombre del sistema de base de datos al cual nos conectamos. Ej. odbc o mssql o mysql.

dataProvider: El mecanismo subyacente usado para conectarse a la base de datos. Normalmente vale native, a menos que se use odbc o ado.

host: Nombre del servidor o DSN a conectarse.

database: Nombre de la base de datos a conectarse. Si se usa ado contiene el proveedor de datos (ado data provider).

user: Nombre del usuario para conectarse a la base datos de datos. Por seguridad la contraseña no se almacena.

raiseErrorFn: Permite definir una funcion para el manejo de errores. Para un ejemplo ve el archivo adodb-errorhandler.inc.php.

debug: Con el valor true provoca que se muestren los mensajes de depuracion.

concat_operator: Normalmente con valor '+' o '||'. Es el operador usado para concatenar cadenas en SQL. Lo usa la funcion Concat.

fmtDate: El formato usado por la funcion DBDate para enviar fechas a las base de datos. Ej. '#Y-m-d#' para Microsoft Access, y ''Y-m-d'' para MySQL.

fmtTimeStamp: El formato usado por la funcion DBTimeStamp para enviar campos timestamp/datetime a la base de datos.

true: El valor usado para representar 'verdadero' .Ej. '.T.' para Foxpro, '1' para Microsoft SQL.

false: El valor usado para representar 'falso'. Ej. '.F.' para Foxpro, '0' para Microsoft SQL.

replaceQuote: La cadena usada para protejer las comillas. Ej. dos comillas sencillas ('') para Microsoft SQL, y diagonal invertida-comilla (\") para MySQL. Usado por la funcion qstr.

autoCommit: Indica si esta habilitado el 'commit' automatico. Por omision el valor es true.

charSet: Indica el conjunto de caracteres por omision. Actualmente solo lo maneja interbase.

dialect: Indica el dialecto por omision a usar. Actualmente solo lo maneja interbase.

role: Asigna el rol. Actualmente solo interbase/firebird lo manejan.

metaTablesSQL: Enunciado SQL para obtener la lista de las tablas disponibles. Ej. SHOW TABLES para MySQL.

genID: El ultimo identificador generado por la funcion GenID(), si lo maneja la base de datos.

cacheSecs: El numero de segundos para guardar en cache los recordsets si se omite el parametro #secs2cache en la funciones CacheExecute() o CacheSelectLimit(). El valor por omision es 60 minutos.

sysDate: Cadena que contiene el nombre de la funcion de la base de datos que genera la fecha fecha actual. Util en los INSERT y UPDATE.

sysTimeStamp: Cadena que contiene el nombre de la funcion de la base de datos que genera el valor actual en formato current timestamp/datetime.

leftOuter: Cadena que contiene el operador para hacer 'left outer join'. Si no se conoce con valor false.

rightOuter: Cadena que contiene el operador para hacer 'right outer join'. Si no se conoce con valor false.

ansiOuter: Valor boleano que es verdadero si se permite hacer 'outer joins' con la sintaxis ANSI. Ej. select * from table1 left join table2 on p1=p2.

connectSID: Valor boleano que indica si se debe considerar el parametro $database en la conexion como SID para el driver oci8. Lo normal es falso. Utill para las version 8.0.5 o anteriores de Oracle.

autoRollback: Si tiene valor true las conexiones persistentes hacen un rollback automatico al momento del PConnect( ). El valor por omision es false.


Funciones/metodos principales de ADOConnection

ADOConnection( )

Funcion constructor. No se invoque directamente. En su lugar usar ADONewConnection( ).

Connect($host,[$user],[$password],[$database])

Conexion no persistente al DSN o servidor $host, usando el usuario $user y la contraseña $password. Si el servidor maneja varias bases de datos, se conecta a la base de datos $database.

Regresa true/false dependiendo de la conexion.

Nota para ADO: Si usas Microsoft ADO y no OLEDB, el parametro $database puede tener el 'OLEDB data provider' utilizado.

PostgreSQL: Otra manera de conectarse a la base de datos es mandando en el primer parametro $host la cadena de conexion estandard de PostgreSQL, y de esa forma se ignoran los demas parametros.

Para Oracle y Oci8, hay dos maneras de conectarse. La primera usando el nombre TNS deinido en el archivo local tnsnames.ora (o ONAMES o HOSTNAMES). Colocar el nombre en el parametro $database, y poner el parametro $host a false. Como alternativa poner el servidor en $host, y el SID en $database , esto se brinca el archivo tnsnames.ora.

Ejemplos:

 # $oraname en tnsnames.ora/ONAMES/HOSTNAMES
 $conn->Connect(false, 'scott', 'tiger', $oraname); 
 $conn->Connect('server:1521', 'scott', 'tiger', 'ServiceName'); # bypass tnsnames.ora

Hay varios ejemplos de conexiones a bases de datos en la parte de ejemplos.

PConnect($host,[$user],[$password],[$database])

Para conexiones persistententes al DSN o servidor $host, usando el usuario $user y contraseña $password. Si el servidor maneja multiples bases de datos, se conecta a la base de datos $database.

Ahora se realiza un rollback en las conexiones persistentes para algunas bases de datos desde la version 2.21, como se recomienda en el manual de PHP. Ver la bitacora de cambios o el codigo fuente para ver cuales bases de datos se afectaron.

Regresa true/false dependiendo de la conexion. Para mas informacion vea Connect( ).

Desde ADOdb 2.21, se incluye el rollback automatico, ejemplo de uso:

 $conn = &NewADOConnection('mysql');
 $conn->autoRollback = true; # el valor por omision es false
 $conn->PConnect(...); # aqui hace el rollback

Con esto al hacer una conexion persistente con PConnect( ), ADOdb realizara primero un rollback. Esto porque el documento que PHP no garantiza que se haga un rollback de las transacciones que fallen cuando se usan transacciones persistentes. Actualmente funciona para Oracle, MySQL, PgSQL, MSSQL, ODBC.

Desde ADOdb 3.11 se puede forzar el uso de conexiones no persistentes aunque se invoque PConnect definiendo la constante ADODB_NEVER_PERSIST antes de invocar PConnect.

Desde ADOdb 4.23, se regresa null si la extension no esta cargada.

NConnect($host,[$user],[$password],[$database])

Siempre genera una nueva conexion. En comparacion con PHP que algunas veces reutiliza las conexiones cuando se usa Connect() o PConnect(). Por lo pronto solo funciona con mysql (PHP 4.3.0 o posterior), postgresql y drivers derivado de oci8. Para los otros drivers NConnect() funciona como Connect().

IsConnected( )

Regresa true si esta conectado a la base de datos. Se agrego en la version 4.53.

Execute($sql,$inputarr=false)

Ejecuta el enunciado SQL en $sql y regresa un objeto de la clase ADORecordSet si es correcto. Observe que si se ejectuta correctamente el SQL, siempre regresa un recordset, aun si se ejecuto un insert o un update. Tambien se puede mandar como parametro $sql un enunciado preparado con prepared Prepare().

Regresa un objeto derivado de la clase ADORecordSet. Ej. si esta conectado a mysql, se obtiene un objeto de la clase ADORecordSet_mysql. Se regresa False si hubo un error en la ejecucion del sql.

El parametro $inputarr puede ser usado para ligar variables a parametros. A continuacion un ejemplo con Oracle:

 $conn->Execute("SELECT * FROM TABLE WHERE COND=:val", array('val'=> $val));
 

Otro ejemplo usando ODBC, usa ?:

  $conn->Execute("SELECT * FROM TABLE WHERE COND=?", array($val));
Ligando variables a parametros SQL (binding)

El uso de variables en los enunciados SQL acelera la compilacion y el almacenamiento de los enunciados SQL, resultando en un mayor desepeño. Actualmente Oracle, Interbase y ODBC manejan los SQL con variables. El estilo de variables con ? de Interbase/ODBC se emula en las bases de datos que no manejan los SQL con variables. No hay que encerrar entre comillas las cadenas de cacrateres si se usa este metodo.

El manejo de variables en SQL para los drivers odbc, interbase y oci8po es:

$rs = $db->Execute('select * from table where val=?', array('10'));
Manejo de variables SQL para el driver oci8:
$rs = $db->Execute('select name from table where val=:key', array('key' => 10));
Liga de parametros en masa (Bulk binding)

Desde la version ADOdb 3.80, se maneja la liga de parametros en masa en el Execute(), habiendo que pasar una arreglo bidimencional para que se ligue al enunciado INSERT, UPDATE o DELETE.

$arr = array(
	array('Ahmad',32),
	array('Zulkifli', 24),
	array('Rosnah', 21)
	);
$ok = $db->Execute('insert into table (name,age) values (?,?)',$arr);

Esto proporciona un gran rendimiento ya que el enunciado SQL se prepara primero. El enunciado ya preparado se ejecuta sucesivamente para cada renglon del arreglo hasta que se procesan todos los renglones o hasta que ocurra un error. Es muy util para importar datos.

CacheExecute([$secs2cache,]$sql,$inputarr=false)

Es similar al Execute, excepto que el recordset es almacenado en cache por $secs2cache segundos en el directorio $ADODB_CACHE_DIR, y $inputarr solo recibe arreglos de una dimension (no soporte 'bulk'). Si se ejecuta CacheExecute() otra vez con los mismos parametros de $sql, $inputarr, y tambien la misma base datos, usuario, y el recordset almacenado en cache no a caducado, se regresa el recordset almacenado en el cache.

<?php
  include('adodb/adodb.inc.php'); 
  include('adodb/tohtml.inc.php');
  $ADODB_CACHE_DIR = '/usr/local/ADOdbcache';
  $conn = &ADONewConnection('mysql'); 
  $conn->PConnect('localhost','userid','password','database');
  $rs = $conn->CacheExecute(15, 'select * from table'); # en cache por 15 secs
  rs2html($rs); /* muestra el recordset como tabla html */  
?>

Como alternativa, desde la version 1.80 de ADOdb, el parametro $secs2cache es opcional:

	$conn->Connect(...);
   	$conn->cacheSecs = 3600*24; // en cache por 24 horas
	$rs = $conn->CacheExecute('select * from table');
Si se omite el parametro $secs2cache, se usa el valor en $connection->cacheSecs (el valor por omision es de 3600 segundos, o 1 hora). Use CacheExecute() unicamente con enunciados SELECT.

Nota del desempeño: Haciendo varias medidas de desempeño (benchmarks) encontre que varian tanto que es mejor hablar de cuando es de beneficio el uso del cache. Cuando el servidor de base de datos es mas lento que tu servidor Web o si la base de datos esta muy sobrecargada entonces el cache de ADOdb es bueno porque reduce la carga a tu servidor de base de datos. Si tu servidor de base de datos esta con poca carga o es mucho mas rapido que tu servidor Web, entonces el uso del cache podria de hecho reducir el desempeño.

ExecuteCursor($sql,$cursorName='rs',$parameters=false)

Ejecuta un procedimiento almacenado (SP) de Oracle, y regresa una variable de cursor REF de Oracle como un recordset de ADOdb. No funciona con ninguna otra base de datos excepto oci8. Gracias a Robert Tuttle por el diseño.

    $db = ADONewConnection("oci8"); 
    $db->Connect("foo.com:1521", "uid", "pwd", "FOO"); 
    $rs = $db->ExecuteCursor("begin :cursorvar := getdata(:param1); end;", 
					'cursorvar',
					array('param1'=>10)); 
    # $rs es ahora como cualquier otro objeto recordset de ADOdb
    rs2html($rs);

ExecuteCursor() es una funcion de ayuda que internamente hace esto:

	$stmt = $db->Prepare("BEGIN :RS := SP_FOO(); END;", true); 
	$db->Parameter($stmt, $cur, 'RS', false, -1, OCI_B_CURSOR);
	$rs = $db->Execute($stmt);

ExecuteCursor solo acepta un parametro de salida. Si tu SP tiene 2 parametros, usa:

  $vv = 'A%';
  $stmt = $db->PrepareSP("BEGIN list_tabs(:crsr,:tt); END;");
  $db->OutParameter($stmt, $cur, 'crsr', -1, OCI_B_CURSOR);
  $db->OutParameter($stmt, $vv, 'tt', 32); # return varchar(32)
  $arr = $db->GetArray($stmt);
  print_r($arr);
  echo " val = $vv"; ## outputs 'TEST'
esto para el siguiente PL/SQL:
  TYPE TabType IS REF CURSOR RETURN TAB%ROWTYPE;
  PROCEDURE list_tabs(tabcursor IN OUT TabType,tablenames IN OUT VARCHAR) IS
  BEGIN
       OPEN tabcursor FOR SELECT * FROM TAB WHERE tname LIKE tablenames;
       tablenames := 'TEST';
  END list_tabs;

SelectLimit($sql,$numrows=-1,$offset=-1,$inputarr=false)

Si tiene exito regresa un recordset, en caso contrario regresa false. Ejectuta un enunciado select, simulando la clausula "LIMIT $numrows OFFSET $offset" del enunciado SELECT de PostgreSQL.

En PostgreSQL, SELECT * FROM TABLE LIMIT 3 da como resultado los primeros 3 registros unicamente. Lo equivalente es $connection->SelectLimit('SELECT * FROM TABLE',3). Esta funcionalidad se simula para las bases de datos que no poseen esta caracteristica.

SELECT * FROM TABLE LIMIT 3 OFFSET 2 regresara los registros 3, 4 y 5 (es decir despues del registro 2, regresa 2 registros). Lo equivalente en ADOdb es $connection->SelectLimit('SELECT * FROM TABLE',3,2).

Observa que es lo contrario de la clausula LIMIT de MySQL. Tambien se puede usar $connection->SelectLimit('SELECT * FROM TABLE',-1,10) para obtener los registros del 11 al ultimo.

El ultimo parametros $inputarr es para aquellas bases de datos que manejan la liga de variables a parametros como Oracle oci8. Esto reduce significativamente la demora por la compilacion de enunaciados SQL. Aqui hay un ejemplo con Oracle :

 $conn->SelectLimit("SELECT * FROM TABLE WHERE COND=:val", 100,-1,array('val'=> $val));
 

El driver oci8po (driver portable de Oracle) usa el metodo mas estandar de definir los parametros para las variables ?:

 $conn->SelectLimit("SELECT * FROM TABLE WHERE COND=?", 100,-1,array($val));

Ron Wilson informa que SelectLimit no funciona con UNIONs.

CacheSelectLimit([$secs2cache,] $sql, $numrows=-1,$offset=-1,$inputarr=false)

Similar a SelectLimit, excepto que el recordset obtenido se almacene en el cache por $secs2cache segundos en el directorio $ADODB_CACHE_DIR.

Desde la version 1.80, $secs2cache es opcional y se puede definir el tiempo de cache en $connection->cacheSecs.

	
   $conn->Connect(...);
   $conn->cacheSecs = 3600*24; // cache de24 horas
   $rs = $conn->CacheSelectLimit('select * from table',10);

CacheFlush($sql=false,$inputarr=false)

Elimina (borra) cualquier recordsets en el cache $ADODB_CACHE_DIR del enunciado SQL en $sql.

Si no se manda ningun parametro, todos los archivos adodb_*.cache son eliminados.

Si se desean borrar todos los archivos de cache en forma manual, hay que ejecutar el siguiente codigo PHP (funciona unicamente en Unix/linux):
  system("rm -f `find ".$ADODB_CACHE_DIR." -name adodb_*.cache`");

Para una limpieza general de los archivos caducos, se recomienda el uso de crontab en Unix, o de at.exe en Windows, y un archivo de comandos similiar al siguiente:

#------------------------------------------------------
# Este ejemplo en particular borra archivos en el
# directorio TMPPATH # con la cadena de caracteres ".cache"
# en el nombre que tengan mas de 7 dias.
#------------------------------------------------------
AGED=7
find ${TMPPATH} -mtime +$AGED | grep "\.cache" | xargs rm -f

MetaError($errno=false)

Regresa un numero de error virtual, en base a la numeracion del DB de PEAR. Se puede necesitar incluir adodb-error.inc.php antes de invocar esta funcion. El parametro $errno es el numero de error nativo que se desea convertir. Si no se manda ningun parametro, MetaError invocara ErrorNo() para convertirlo. Si el numero de error no tiene equivalente virtual, MetaError regresara -1 (DB_ERROR).

MetaErrorMsg($errno)

Recibe el numero de error generado por MetaError() para obtener el equivalente mensaje de error virtual.

ErrorMsg()

Regresa el ultimo mensaje de error. El mensaje de error se cambia despues de cada llamado a la funcion Execute().

Puede regresar un texto aun si no ocurrio un error. No es necesario llamar esta funcion a menos que la funcion ADOdb regrese falso.

Nota: Si esta habiliado debug, los mensajes de error SQL se despliegan cada vez que la funcion Execute es llamada.

ErrorNo()

Regresa el ultimo numero de error. Este numero de error se actualiza despues de cada invocacion de Execute(). Si se obtiene el valor 0, es que no hubo error.

Tenga en cuenta que las versiones antiguas de PHP (antes de 4.0.6) no generan numero de error para conexiones ODBC. En lo general no es necesario invocar esta funcion a menos que la funcion ADOdb regrese el valor falso.

IgnoreErrors($saveErrHandlers)

Te permite ignorar errores para que StartTrans()/CompleteTrans() no se vea afectado, asi como tampoco sea invocado el menajador de erroes 'normal' en caso de ocurra un error. Es util si qiueres verificar si existe un campo o una table sin que se invoque un error si no existe.

Uso:

$saveErrHandlers = $conn->IgnoreErrors();
$rs = $conn->Execute("select campo from alguna_table_que_pueda_no_existir");
$conn->IgnoreErrors($saveErrHandlers);

Advertencia: no invoques StartTrans()/CompleteTrans() dentro de un bloque que usa IgnoreErrors().

SetFetchMode($mode)

Asigna el modo para obtener los resultados para la conexion y lo almacena en $db->fetchMode. Los modos permitidos son ADODB_FETCH_ASSOC y ADODB_FETCH_NUM. Para mas informacion vea $ADODB_FETCH_MODE.

Regresa el metodo anterior, o falso si SetFetchMode( ) no habia sido llamado con anterioridad.

CreateSequence($seqName = 'adodbseq',$startID=1)

Crea una secuencia. La siguiente vez que se invoque GenID( ), el valor que regrese sera $startID. Se agrego en la version 2.60.

DropSequenceD($seqName = 'adodbseq')

Borra una secuencia. Se agrego en la version 2.60.

GenID($seqName = 'adodbseq',$startID=1)

Genera un numero en secuencia. Funciona para interbase, mysql, postgresql, oci8, oci8po, mssql, y los drivers basados en ODBC. Utiliza $seqName como el nombre de la secuencia. GenID() creara automaticamente la secuencia si no existe (con la condicion de que el usuario tenga permiso de crearla). Si no habra que crear la secuencia primero.

Si el driver de su base de datos emula a las secuencias, el nombre de la tabla es el nombre de la secuencia. La tabla tiene una columna, 'id' la cual deberia de ser de tipo entero, o si se necesita algo mayor, numeric(16).

Para ODBC y bases de datos que no manejan secuencias en forma nativa (ej mssql, mysql), se crea la tabla para cada secuencia. Si la secuencia no habia sido definida anteriormente se creara con el valor inicial de $startID.

Nota, el driver de mssql anterior a la version 1.90 generaba GenID() de 16 bytes (GUID).

UpdateBlob($table,$column,$val,$where)

Permite almacenar el valor blob de $val en la columna $column de la tabla $table en el renglon que cumpla el criterio $where.

Uso:

	# para oracle
	$conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, empty_blob())');
	$conn->UpdateBlob('blobtable','blobcol',$blobvalue,'id=1');
	
	# las demas bases de datos (excepto oracle)
	$conn->Execute('INSERT INTO blobtable (id, blobcol) VALUES (1, null)');
	$conn->UpdateBlob('blobtable','blobcol',$blobvalue,'id=1');

Regresa verdadero si tiene existo, faslo en caso contrario. Sirve para MySQL, PostgreSQL, Oci8, Oci8po e Interbase. Otros drivers pueden funcionar, dependiendo del estado de su desarrollo (informix ya funciona).

Nota, cuando se lee un blob de Interbase blob con un SELECT, todavia necesita ser decodificado usando $connection->DecodeBlob($blob); para obtener el valor original en versiones de PHP anteriores a 4.1.0.

Para PostgreSQL, se pueden almacenar blob en campos OID o bytea. Se pueden usar campos bytea pero no OID con UpdateBlob( ). Y UpdateBlobFile( ) maneja OID, pero no bytea.

Si el parametro no es un OID, entonces UpdateBlob() asume que se esta almacenando en un campo bytea.

UpdateClob($table,$column,$val,$where)

Permite almacenar el valor clob en la variable $val en la columna $column de la tabla $table en el renglon que cumpla el criterio $where. Es similar a UpdateBlob anterior, pero para 'Character Large OBjects'.

Uso:

	# para oracle
	$conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, empty_clob())');
	$conn->UpdateBlob('clobtable','clobcol',$clobvalue,'id=1');
	
	# las demas bases de datos (excepto oracle)
	$conn->Execute('INSERT INTO clobtable (id, clobcol) VALUES (1, null)');
	$conn->UpdateBlob('clobtable','clobcol',$clobvalue,'id=1');

UpdateBlobFile($table,$column,$path,$where,$blobtype='BLOB')

Similar a UpdateBlob, excepto que se pasa como parametro el nombre del archivo que contiene el blob.

Para PostgreSQL, si estas usando OID, use esta interfase. Esta interfase no maneja campos bytea.

Regresa verdadero si tiene exito, falso en caso contrario.

BlobEncode($blob)

Agunas bases de datos requieren que los blobs se codifiquen manualmente antes de ser almacenados. Nota, si se usa UpdateBlob( ) o UpdateBlobFile( ) la conversion es automatica y no hay necesidad de llamar esta funcion. Para PostgreSQL, BlobEncode() puede unicamente ser usada en campos bytea.

Regresa el valor del blob codificado.

Nota, hay una propiedad del objeto conexion llamada blobEncodeType el cual tiene 3 valor legales:

false - no hay necesidad de realizar codificacion ni decodificacion.
'I' - Se requiere la codificacion de blobs, y se obtiene un valor numerico (no hay necesidad de encerrar entre comillas).
'C' - Se requiere la codificacion de blobs, y se obtiene un valor alfanumerico (si requiere que se encierre entre comillas).

Esto es solo para efectos de documentacion, para que el programa que maneja varios drivers de bases de datos sepa que es lo correcto cuando procesa blobs.

BlobDecode($blob)

Algunas bases de datos requieren que los blobs sean decodificados manualmente despues de ejecutar el select. Si la base de datos no requiere la decodificacion, esta funcion regresara el blob sin cambio. Actualmente BlobDecode es requerido unicamente para una base de datos, PostgreSQL, y unicamente si se usan campos OID (si se usan campos bytea se decodifican automaticamente). El valor por omision maximo de un blob esta en $connection->maxblobsize, que vale 256K en adodb 4.54.

En ADOdb 4.54 y posterior el valor del blob es el parametro de salida.EN versiones anteriores el valor del blob se mandaba a stdout.

$rs = $db->Execute("select bloboid from postgres_table where id=$key");
$blob = $db->BlobDecode( reset($rs->fields) );

Replace($table, $arrFields, $keyCols,$autoQuote=false)

Intenta hacer un UPDATE al registro, si no encuenta el registro, se genera y ejecuta un INSERT. Regresa 0 si falla, 1 si efectuo el update y 2 si no se encontro el registro y el insert fue con exito. Es diferente al replace de MySQL el cual borra el registro e inserta uno nuevo. Esto tambien significa que no se puede actualizar la llave primaria. La unica excepcion es con Interbase y sus derivados, que si usan delete e insert debido a algunas limitantes del API de Interbase.

Los parametros son el nombre de la tabla ($table), $arrFields que es un arreglo asociativo donde las llaves son los nombres de los campos y $keyCols es el nombre del campo llave primaria o un arreglo de nombres de campos si es una llave compuesta. Si $autoQuote tiene el valor true, entonces Replace() encerrara entre comillas todos los valor que no son numericos, los NULLs no se encomillan. Observe que este encomillado automatico no funcionara si se usan funciones SQL u operadores.

Ejemplos:

# Llave primaria de un solo campo
$ret = $db->Replace('atable', 
	array('id'=>1000,'firstname'=>'Harun','lastname'=>'Al-Rashid'),
	'id',$autoquote = true);	
# genera UPDATE atable SET firstname='Harun',lastname='Al-Rashid' WHERE id=1000
# o INSERT INTO atable (id,firstname,lastname) VALUES (1000,'Harun','Al-Rashid')

# Llave compuesta
$ret = $db->Replace('atable2', 
	array('firstname'=>'Harun','lastname'=>'Al-Rashid', 'age' => 33, 'birthday' => 'null'),
	array('lastname','firstname'),
	$autoquote = true);

# sin el encomillado automatico
$ret = $db->Replace('atable2', 
	array('firstname'=>"'Harun'",'lastname'=>"'Al-Rashid'", 'age' => 'null'),
	array('lastname','firstname'));	

AutoExecute($table, $arrFields, $mode, $where=false, $forceUpdate=true,$magicq=false)

Desde la version 4.56 de ADOdb, puedes genrerar y ejecutar automaticamente INSERTs y UPDATEs en la tabla indicada con esta funcion, la cual encapsula a GetInsertSQL() y GetUpdateSQL().

AutoExecute() inserta o actualiza la tabla $table dado un arreglo de campos ($arrFields), donde la llave es el nombre del campo y el valor del arreglo es el valor del campo a almacenar. Toma en cuenta que hay un costo debido a que la tabla primero es consultada para obtener informacion de las llaves antes de que se genere el SQL. Se genera un INSERT o un UPDATE en base al valor de $mode (ver en seguida).

Valores permitidos de $mode

Tu tienes que definir las constantes DB_AUTOQUERY_UPDATE y DB_AUTOQUERY_INSERT o incluir el archivo adodb-pear.inc.php.

La clausula $where es obligatoria si $mode == 'UPDATE'. Si $forceUpdate=false entonces primero se consulta la base de datos y verificamos si el valor del campo obtenido por la consulta coincide con el valor del arreglo; solo si son diferentes se actualiza el campo.

Regresa true si es correcto, false si hay error.

Un ejemplo de esto es:

$record["firstName"] = "Carol";
$record["lasTname"] = "Smith"; 
$conn->AutoExecute($table,$record,'INSERT');
# executes "INSERT INTO $table (firstName,lasTname) values ('Carol',Smith')";

$record["firstName"] = "Carol";
$record["lasTname"] = "Jones"; 
$conn->AutoExecute($table,$record,'UPDATE', "lastname like 'Sm%'");
# executes "UPDATE $table SET firstName='Carol',lasTname='Jones' WHERE lastname like 'Sm%'";

Nota: Una de las fortalezas del AutoExecute() de ADOdb es que solo los nombres de campo validos de la tabla $table son actualizados. Si $arrFields contiene campos que no son de la tabla, son ignorados. Esto tiene un costo ya que hay que consultar la base de datos para obtener el nombre de los campos, pero ya que tu no estas codificando el SQL, significa que tu probablemente no estas tan interesado en velocidad como en conveniencia.

Desde 4.62, el nombre de la tabla puede ser forzado asignandolo en $rs->tableName antes de invocar AutoExecute(), GetInsertSQL() o GetUpdateSQL().

GetUpdateSQL(&$rs, $arrFields, $forceUpdate=false,$magicq=false)

Genera el enunciado SQL para actualizar una tabla, dandole el recordset $rs, y un arreglo con los campos modificados a comparar con el recordset ($arrFields, el cual debe de ser un arreglo asociativo conteniendo el nombre de la columna y el nuevo valor). Si $forceUpdate vale true, entonces tambien se genera el SQL aun cuando $arrFields sea identico a $rs->fields. Requiere que el recordset sea asociativo. $magicq es utilizado para indicar si se desea encomillado automatico (ver qstr()). El nombre de los campos en el arreglo puede ser con mayusculas o minusculas.

Desde la version 4.52, se permite que pasas el parametro $force, y este tiene precedencia sobre la variable global $ADODB_FORCE_TYPE.

Desde la version 4.62, el nombre de la tabla a usar puede ser modificada usando $rs->tableName antes de llamar a AutoExecute(), GetInsertSQL() o GetUpdateSQL().

GetInsertSQL(&$rs, $arrFields,$magicq=false)

Genera el enunciado SQL para insertar en una tabla, dandole un recordset $rs. Requiere que este en modo asociativo. $magicq se usa para indicar si se desea el encomillado automatico de los valores (ver qstr()). El nombre de los campos en el arreglo puede ser con mayusculas o minusculas.

Desde laversion 2.42, se puede pasar como parametro el nombre de la tabla en lugar del recordset (parametro $rs), y se generara automaticamente el enunciado de INSERT para esa tabla.

Desde la version 4.52, se permite que pasas el parametro $force, y este tiene precedencia sobre la variable global $ADODB_FORCE_TYPE.

Desde la version 4.62, el nombre de la tabla a usar puede ser modificada usando $rs->tableName antes de llamar a AutoExecute(), GetInsertSQL() o GetUpdateSQL().

PageExecute($sql, $nrows, $page, $inputarr=false)

Se usa para procesar un recordset por paginas. La pagina inicial es 1. Vea el Ejemplo 8.

CachePageExecute($secs2cache, $sql, $nrows, $page, $inputarr=false)

Se usa para procesar un recordset por paginas. La pagina inicial es 1. Vea el Ejemplo 8. version con cache del PageExecute.

Close( )

Cierra la conexion a la base de datos. PHP4 orgullosamente nos indica que ya no es necesario hacer la limpieza al final de la conexion por que el mecanismo de conteo de PHP4 lo hara por nosotros.

StartTrans( )

Inicia una transaccion monitoreada. Cada enunciado SQL que se ejectute, ADOdb lo monitoreara buscando errores SQL, y si detecta alguno cuando se invoque CompleteTrans(), se hara un rollback automatico.

Para entender porque StartTrans() es mejor que BeginTrans(), examinemos algunas maneras de usar BeginTrans(). A continuacion la manera incorrecta de usar las transacciones.

$DB->BeginTrans();
$DB->Execute("update table1 set val=$val1 where id=$id");
$DB->Execute("update table2 set val=$val2 where id=$id");
$DB->CommitTrans();

debido a que no se verifica por errores. Es posible que se actualize la tabla table1 y que la actualizacion de la tabla table2 falle. Esta es una manera mejor (o menos peor):

$DB->BeginTrans();
$ok = $DB->Execute("update table1 set val=$val1 where id=$id");
if ($ok) $ok = $DB->Execute("update table2 set val=$val2 where id=$id");
if ($ok) $DB->CommitTrans();
else $DB->RollbackTrans();

Otra manera (con el metodo antiguo) de hacerlo desde la version de 2.0 de ADOdb:

$DB->BeginTrans();
$ok = $DB->Execute("update table1 set val=$val1 where id=$id");
if ($ok) $ok = $DB->Execute("update table2 set val=$val2 where id=$id");
$DB->CommitTrans($ok);

Es muy engorroso monitorear $ok por todo el codigo. StartTrans() es una mejora debido a que monitorea todos los erroers SQL por nosotros. Esto es particularmente util si invocas una funcion de 'caja negra' en el cual se pueden ejecutar varios enunciados SQL. Adicionalmente,todas las llamadas a BeginTrans, CommitTrans o RollbackTrans dentro de un bloque StartTrans seran desabilitadas, por lo cual aunque la 'caja negra' haga un commit, sera ignorado.

$DB->StartTrans();
CallBlackBox();   // Funcion que hace varias cosas
$DB->Execute("update table1 set val=$val1 where id=$id");
$DB->Execute("update table2 set val=$val2 where id=$id");
$DB->CompleteTrans($ok);

Nota los bloques StartTrans son anidables, los bloques interiores son ignorados.

CompleteTrans($autoComplete=true)

Termina una transaccion iniciada con StartTrans(). Esta funcion monitorea por posibles errores SQL, y hara un 'commit' si no ocurrieron errores, en caso de algun error hara el 'rollback'. Regresa verdadero si efectuo el commit y false si llamo el roolback. Si el parametro $autoComplete es true se monitorean los errores y hace commit o rollback segun sea el caso. Con $autoComplete en false se hace rollback aun cuando no se hayan detectado errores.

FailTrans( )

Aborta una transaccion iniciada con StartTrans(). El rollback se hara hasta que se invoque CompleteTrans().

HasFailedTrans( )

Verifica si una transaccion inteligente ha fallado, es decir regresa true si ha habido un error SQL o si se invoco a FailTrans(). Si no esta dentro de una transaccion inteligente regresa falso.

BeginTrans( )

Inicia una transaccion. Desactiva el Commit automatico. Regresa true si se hace con exito. Algunas bases de datos siempre regresan false si no esta habilitado el manejo de transacciones. Cualquier transaccion abierta hara rollback cuando se cierre la conexion. Algunas de las bases de datos que manejan transacciones son: Oracle, PostgreSQL, Interbase, MSSQL, ciertas versiones de MySQL, DB2, Informix, Sybase, etc.

Observe que StartTrans() y CompleteTrans() son un metodo superior para el manejo de transacciones, disponible desde ADOdb 3.40. Para una explicacion vea la documentacion de StartTrans().

Tambien se puede usar el manejador de errores de ADOdb para matar y hacer rollback de la transaccion automaticamente. Algunas extensiones de bases de datos problematicas hacen 'commit' de todas las transacciones pendientes, por lo cual conviene por seguridad invocar manualmente $DB->RollbackTrans() en el manejador de errores.

Detectando Transacciones

Desde la version 2.50 de ADOdb, se puede detectar si se esta dentro de una transaccion. Hay que verificar si $connection->transCnt > 0. Esta variable se incrementa cada vez que se llama a BeginTrans(), y se decrementada cuando se invoca a RollbackTrans() o CommitTrans().

CommitTrans($ok=true)

Termina una transaccion con exito. Regresa true si funciona. Si la base base de datos no maneja transaccion tambien regresara true ya que los datos son siempre almacenados.

Si se manda el parametro $ok=false, invocara un 'rollback'. Vea el ejemplo de BeginTrans().

RollbackTrans( )

Termina la transaccion regresando los cambios ('rollback'). Regresa true si tiene exito. Si la base de datos no maneja transacciones, regresara false ya que los datos no se pueden restaurar.

SetTransactionMode($mode )

SetTransactionMode te permite indicar el modo de trasaccion a usar para todas las transacciones subsecuentes. Nota: si tu tienes conexiones persistentes y usas mssql o mysql, puedes tener que regresar explicitamente el modo de transaccion alprincipio de cada pagina. Actualmente solo esta soportado para postgresql, mssql, mysql con InnoDB y oci8. Por ejemplo:

$db->SetTransactionMode("SERIALIZABLE");
$db->BeginTrans();
$db->Execute(...); $db->Execute(...);
$db->CommiTrans();

$db->SetTransactionMode(""); // lo regreso al valor por omision
$db->StartTrans();
$db->Execute(...); $db->Execute(...);
$db->CompleteTrans();

Valores permitidos son:

Puedes tambiar indicar un valor especifico para tu base de datos como 'SNAPSHOT' para mssql o 'READ ONLY' para oci8/postgres.

Ve la secccion 'transaction levels' para PostgreSQL, Oracle, MySQL, MS SQL Server e Informix.

GetAssoc($sql,$inputarr=false,$force_array=false,$first2cols=false)

Regresa un arreglo asociativo para el enunciado SQL solicitado en $sql, opcionalmente puede tener liga de parametros usando $inputarr. Si el numero de columnas obtenido es mayor a dos, se genera un arreglo bidimensional con la primera columa del recordset como la llave del resto de los campos. Si hay exactamente dos columnas, se obtiene un arreglo de una dimension donde la llave (primera columna) apunta a su valor (segunda columna). A menos que $force_array tenga el valor true, en cuyo caso se crea un arreglo para cada valor.

Ejemplos:

Si tenemos los siguientes datos en el recordset:

renglon1: Manzana, Fruta, Comible
renglon2: Cactus, Planta, Incomible
renglon3: Rosa, Flor, Comible

GetAssoc generara el siguiente arreglo asociativo bidimensional:

Manzana => array[Fruta, Comible]
Cactus => array[Planta, Incomible]
Rosa => array[Flor,Comible]

Si el conjunto de datos es:

renglon1: Manzana, Fruta
renglon2: Cactus, Planta
renglon3: Rosa, Flor

GetAssoc generara el siguiente arreglo asociativo (con $force_array==false):

Manzana => Fruta
Cactus=>Planta
Rosa=>Flor

La funcion regresa el arreglo asociativo, o falso si ocurrio un error.

CacheGetAssoc([$secs2cache,] $sql,$inputarr=false,$force_array=false,$first2cols=false)

La version con cache de la funcion GetAssoc anterior.

GetOne($sql,$inputarr=false)

Ejecuta el enunciado SQL y regresa el primer campo del primer renglon. El recordset y el resto de los renglones son descartados automaticamente. Si hay un error la funcion regresa false.

GetRow($sql,$inputarr=false)

Ejecuta el enunciado SQL y regresa el primer renglon como un arreglo. El recordset y el resto de los renglones son descartados automaticamente. Si hay un error la funcion regresa false.

GetAll($sql)

Ejecuta el enunciado SQL y regresa todos los renglones como un arreglo bidimensional. El recordset es descartado automaticamente. Si hay un error la funcion regresa false.

GetCol($sql,$inputarr=false,$trim=false)

Ejecuta el enunciado SQL y regresa todos los elementos de la primera columna como un arreglo dimencional. El recordset es descartado automaticamente. Si ocurre un error regresa false.

CacheGetOne([$secs2cache,] $sql,$inputarr=false), CacheGetRow([$secs2cache,] $sql,$inputarr=false), CacheGetAll([$secs2cache,] $sql,$inputarr=false), CacheGetCol([$secs2cache,] $sql,$inputarr=false,$trim=false)

Similares a las funciones Get* anteriores, excepto que el recordset es almacenado en el cache indicado en $ADODB_CACHE_DIR por $secs2cache segundos. Es bueno para acelerar preguntas en datos que cambian poco. El parametro $secs2cache es opcional. Si se omite se usa el valor de $connection->cacheSecs (normalmente de 3600 segundos o 1 hora).

Prepare($sql )

Prepara (compila) un enunciado SQL para ejecutarse repetitivamente. Los parametros se representan por ?, excepto para el driver oci8, que emplea el metodo usual de Oracle de :varname.

Regresa un arreglo que contiene el enunciado SQL original como primera posicion, las demas posiciones del arreglo varian para cada driver. Si hubo un error o se esta emulando el Prepare( ), se regresa la cadena $sql original. Esto es porque todo el manejo de errores se hace en el Execute().

Prepare( ) no puede ser usado en funciones que usan la tecnica de modificar el enunciado SQL como PageExecute( ) y SelectLimit( ).

Ejemplo:

$stmt = $conn->Prepare('insert into table (col1,col2) values (?,?)');
for ($i=0; $i < $max; $i++)
    $conn->Execute($stmt,array((string) rand(), $i));

Tambien revisa InParameter(), OutParameter() y PrepareSP(). Solo esta soportado internamente por interbase, oci8 y algunos drivers basados en ODBC, en los demas casos es emulado. No hay ninguna ganancia en el rendimiendo usando Prepare() emulados.

Importante: Debido a las limitaciones o fallas en el PHP, si tienes errores al ejecutar SQLs preparados, pon $ADODB_COUNTRECS = false antes de prepararlos. Esto ha sido observado con ODBC.

IfNull($field, $nullReplacementValue)

Funcion IFNULL compatible (NVL para Oracle). Regresa una cadena de caracteres que representa la funcion que verifica si $field es nulo (NULL), y si lo es, le cambia el valor regresado por $nullReplacementValue. Ej.

$sql = 'SELECT '.$db->IfNull('name', "'- unknown -'"). ' FROM table';

length

No es una funcion sino una propiedad. Algunas bases de datos tiene la funcion "length" y otras "len" para medir la longitud de una cadena. Para usar la propiedad:

  $sql = "SELECT ".$db->length."(field) from table";
  $rs = $db->Execute($sql);

random

Tampoco es una funcion sino una propiedad. Contiene la cadena que representa a la funcion sql que genera un numero aleatorio entre 0.0 y 1.0 inclusive.

substr

Tambien es una propiedad. Algunas bases de datos tienen la funcion "substr" y otras la funcion "substring" para recuperar parte de una cadena. Ejemplo de uso:

  $sql = "SELECT ".$db->substr."(field, $offset, $length) from table";
  $rs = $db->Execute($sql);

Para todas las bases de datos, el primer parametro de substr es el campo, el segundo es el desplazamiento (1 es el principio) para empezar la sub-cadena, y el tercero es el largo.

Param($name)

Genera el caracter para marcar la posicion de los parametros. En la mayoria de las bases de datos el caracter es "?". Sin embargo algunas bases de datos usan marcadores con nombre, Oracle por ejemplo usa ":somevar". Estos nos permite definir enunciados SQL con parametros que sean compatibles.

$sql = 'insert into table (col1,col2) values ('.$conn->Param('a').','.$conn->Param('b').')';
# genera 'insert into table (col1,col2) values (?,?)'
# o      'insert into table (col1,col2) values (:a,:b)'
$stmt = $conn->Prepare($sql);
$stmt = $conn->Execute($stmt,array('one','two'));

PrepareSP($sql, $cursor=false )

Al llamar procedimientos almaceneados (SP) de mssql y oci8 (oracle), PrepareSP() nos permite ligar directamente a un parametro que regresa un valor, o el manejo especial de LOBs.

Regresa el mismo arreglo o cadena $sql como el Prepare( ). Si NO se necesita ligar a un valor de salido, se deberia de usar Prepare().

El segundo parametro, $cursor solo se usa con oci8. Con valor true provoca que se llame a OCINewCursor; esto para el manejo de REF CURSOR.

Para ejemplos del uso de PrepareSP( ), vea InParameter( ) a continuacion.

Nota: en el driver de mssql, preparar procedimientos almacenados requiere que se llame a una funcion especial, mssql_init( ), la cual es invocada por esta funcion. PrepareSP( ) esta disponible en todos los drivers y es emulado invocando a Prepare( ).

InParameter($stmt, $var, $name, $maxLen = 4000, $type = false )

Liga una variable PHP como entrada a una variable del procedimiento almacenado. El parametro $stmt es el valor que regreso PrepareSP(), $var es la variable PHP a ligar, $name es el nombre de la variable del procedimiento almacenado. $maxLen es opcional y es la longitud maxima de los datos a ligar y $type depende de cada base de datos. Consulte la documentacion de mssql_bind y ocibindbyname en php.net para mas informacin de los valores autorizados de $type.

InParameter() es una funcion envolvente que llama Parameter() con $isOutput=false. La ventaja de esta funcion es que es auto descriptiva, debido a que ya no es necesario el parametro $isOutput. Actualmente solo para mssql y oci8.

Un ejemplo usando oci8:

# Para Oracle, Prepare y PrepareSP son identicos
$stmt = $db->PrepareSP(
	"declare RETVAL integer; 
	begin
	:RETVAL := SP_RUNSOMETHING(:myid,:group);
	end;");
$db->InParameter($stmt,$id,'myid');
$db->InParameter($stmt,$group,'group',64);
$db->OutParameter($stmt,$ret,'RETVAL');
$db->Execute($stmt);

Este mismo ejemplo usando mssql:

# @RETVAL = SP_RUNSOMETHING @myid,@group
$stmt = $db->PrepareSP('SP_RUNSOMETHING'); 
# ¡Observa que el nombre de parametro no tiene @ al principio!
$db->InParameter($stmt,$id,'myid');
$db->InParameter($stmt,$group,'group',64);
# El valor de salida en mssql, RETVAL, es un nombre fijo 
$db->OutParameter($stmt,$ret,'RETVAL');
$db->Execute($stmt); 

Tome en cuenta que la unica diferencia entre la implementacion de oci8 y mssql es $sql.

En mssql si el parametro $type tiene valor false, $type se determinara dinamicamente en base al tipo de variable PHP proporcionada. (string => SQLCHAR, boolean =>SQLINT1, integer =>SQLINT4 o float/double=>SQLFLT8).

Para oci8, $type puede ser OCI_B_FILE (Binary-File), OCI_B_CFILE (Character-File), OCI_B_CLOB (Character-LOB), OCI_B_BLOB (Binary-LOB) y OCI_B_ROWID (ROWID). Para pasar NULL hay que usar $db->Parameter($stmt, $null=null, 'param').

OutParameter($stmt, $var, $name, $maxLen = 4000, $type = false )

Liga una variable PHP con la salida de una variable de un procedimiento almacenado. El parametro $stmt es el valor que regreso PrepareSP(), $var es la variable PHP que se se desea ligar, $name es el nombre de la variable del procedimiento almacenado. Opcionalmente, $maxLen es la longitud maxima de datos a ligar, y $type que depende de cada base de datos.

OutParameter() es una funcion envolvente que llamada Parameter() con $isOutput=true. La ventaja de esta funcion es que es auto descriptiva, debido a que ya no es necesario el parametro $isOutput. Actualmente solo para mssql y oci8.

Para un ejemplo vea InParameter.

Parameter($stmt, $var, $name, $isOutput=false, $maxLen = 4000, $type = false )

Observacion: Esta funcion esta descontinuada, debido a las nuevas funciones InParameter() y OutParameter(). Estas son mejores porque son auto descriptivas.

Agrega un parametro adecuado para regresar valores o el manejo especial de datos (ej, LOBs) despues de que el enunciado ha sido preparado con PrepareSP(). Actualmente solo para mssql y oci8. Los parametros son:

$stmt Enunciado regresado por Prepare() o PrepareSP().
$var Variable PHP a ligar. ¡Asegurarse de inicializarla!
$name Nombre de la variable del procedimiento almacenado a ligarse.
[$isOutput] Indica el sentido del parametro, 0/false=Entrada 1=Salida 2= Entrada/Salida. Se ignora en el driver oci8 ya que este auto detecta el sentido.
[$maxLen] Longitud maxima de la variable.
[$type] Consulta mssql_bind y ocibindbyname en php.net para mas informacion de los valores legales de $type.

Por ultimo, para oci8, los parametros pueden ser reusados sin llamar nuevamente a PrepareSP( ) o Parameters. Esto no es posible con mssql. Un ejemplo con oci8:

$id = 0; $i = 0;
$stmt = $db->PrepareSP( "update table set val=:i where id=:id");
$db->Parameter($stmt,$id,'id');
$db->Parameter($stmt,$i, 'i');
for ($cnt=0; $cnt < 1000; $cnt++) {
	$id = $cnt; 
$i = $cnt * $cnt; # ¡Funciona para oci8! $db->Execute($stmt);
}

Bind($stmt, $var, $size=4001, $type=false, $name=false)

Esta es una funcion de bajo nivel manejada unicamente por el driver de oci8. Evite usarla a menos que unicamente desea dar soporte a Oracle. La funcion Parameter( ) es el metodo recomendado para ligar variables.

Bind( ) nos permite ligar variables en el enunciado sql. Liga la variable PHP a un nombre definido en el enunciado SQL de Oracle que fue previamente preparado usando Prepare(). Las variables nombradas de Oracle empiezan con dos puntos (:), y ADOdb necesita que las variables se llamen :0, :1, :2, :3, etc. La primera vez que se invoque Bind() tomara :0, la segunda invocacion tomara :1, etc. El uso de Bind() puede proporcionaar un 100% de incremento de velocidad para enunciados insert, select y update.

Los otros parametros, $size asigna el tamaño de memoria para almacenamiento de datos, $type puede tener los valores OCI_B_FILE (Binary-File), OCI_B_CFILE (Character-File), OCI_B_CLOB (Character-LOB), OCI_B_BLOB (Binary-LOB) y OCI_B_ROWID (ROWID). Por ultimo, en lugar de usar los nombres :0, :1, etc., se pueden definir los nombres a ligar usando $name.

El siguiente ejemplo usa tres variables a ligar: p1, p2 y p3. Estas variables se ligan a :0, :1 y :2.

$stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)");
$DB->Bind($stmt, $p1);
$DB->Bind($stmt, $p2);
$DB->Bind($stmt, $p3);
for ($i = 0; $i < $max; $i++) { 
   $p1 = ?; $p2 = ?; $p3 = ?;
   $DB->Execute($stmt);
}

Tambien se puede usar variables con nombre:

$stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:nombre0, :nombre1, :nombre2)");
$DB->Bind($stmt, $p1, "nombre0");
$DB->Bind($stmt, $p2, "nombre1");
$DB->Bind($stmt, $p3, "nombre2");
for ($i = 0; $i < $max; $i++) { 
   $p1 = ?; $p2 = ?; $p3 = ?;
   $DB->Execute($stmt);
}

LogSQL($enable=true)

Llama este metodo para instalar el sistema de registro y medicion de enunciados SQL (usando fnExecute). Todos los enunciados SQL seran registrados en la tabla adodb_logsql de la base de datos. Si la tabla no existe, ADOdb la creara si tienes los premisos necesarios. Regresa el estado previo de registro (true para habilitado, false para desabilitado). Este un ejemplo del DDL para algunas bases de datos:

		mysql:
		CREATE TABLE adodb_logsql (
		  created datetime NOT NULL,
		  sql0 varchar(250) NOT NULL,
		  sql1 text NOT NULL,
		  params text NOT NULL,
		  tracer text NOT NULL,
		  timer decimal(16,6) NOT NULL
		)
		
		postgres:
		CREATE TABLE adodb_logsql (
		  created timestamp NOT NULL,
		  sql0 varchar(250) NOT NULL,
		  sql1 text NOT NULL,
		  params text NOT NULL,
		  tracer text NOT NULL,
		  timer decimal(16,6) NOT NULL
		)
		
		mssql:
		CREATE TABLE adodb_logsql (
		  created datetime NOT NULL,
		  sql0 varchar(250) NOT NULL,
		  sql1 varchar(4000) NOT NULL,
		  params varchar(3000) NOT NULL,
		  tracer varchar(500) NOT NULL,
		  timer decimal(16,6) NOT NULL
		)
		
		oci8:
		CREATE TABLE adodb_logsql (
		  created date NOT NULL,
		  sql0 varchar(250) NOT NULL,
		  sql1 varchar(4000) NOT NULL,
		  params varchar(4000),
		  tracer varchar(4000),
		  timer decimal(16,6) NOT NULL
		)
Uso:
	$conn->LogSQL(); // Habilita el registro
	  :
	$conn->Execute(...);
	  :
	$conn->LogSQL(false); // deshabilita el registro
	
	# Muestra un resumen de los resultados del registro
	$perf = NewPerfMonitor($conn);
	echo $perf->SuspiciousSQL();
	echo $perf->ExpensiveSQL();

Una limitante del registro es que el 'rollback' de la transaccion tambien impide que el enunciado SQL se registre.

Si deseas otro nombre para la tabla a utilizar para almacenar los SQL, tendras que invocar adodb_perf::table($tablename), donde $tablename es el nuevo nombre de la tabla (tu tendras que crear la tabla manualmente). Un ejemplo:

	include('adodb.inc.php');
	include('adodb-perf.inc.php');
	adodb_perf::table('my_logsql_table');
Tambien ve los manuales Monitor de rendimiento.

Propiedades fnExecute y fnCacheExecute

Estas dos propiedades nos permiten definir funciones de 'cuello de botella' para todos los enunciados SQL procesados por ADOdb. Nos permite realizar estadisticas y reescritura de los enunciados SQL.

Ejemplos de fnExecute

A continuacion un ejemplo del uso de fnExecute para contar todos los queries con cache y sin cache:

# $conn es el objeto de conexion
function CountExecs($conn, $sql, $inputarray)
{
global $EXECS;

if (!is_array(inputarray)) $EXECS++;
# Maneja arreglos bidimensionales
else if (is_array(reset($inputarray))) $EXECS += sizeof($inputarray);
else $EXECS++;
}

# $conn es el objeto de conexion
function CountCachedExecs($conn, $secs2cache, $sql, $inputarray)
{
global $CACHED; $CACHED++; }
$conn = NewADOConnection('mysql'); $conn->Connect(...); $conn->fnExecute = 'CountExecs'; $conn->fnCacheExecute = 'CountCachedExecs'; : :
# Despues de muchos enunciados sql:` printf("<p>Total de queries=%d; total en cache=%d</p>",$EXECS+$CACHED, $CACHED);

La funcion fnExecute se llamada antes del que el sql sea examinado y ejecutado, por eso se puede reescribir el query. Si mandas como parametro un enunciado preparado entonces $sql es un arreglo (ver Prepare). La funcion fnCacheExecute se ejecuta unicamente si el recordset se almacena en cache. Los parametros de la funcion coinciden con las funciones Execute y CacheExecute, excepto que $this (el objeto conexion) se manda como primer parametro.

Desde la version 3.91 de ADOdb 3.91, el comportamiento de fnExecute es diferente dependiendo de si la funcion definida regresa un valor. Si no regresa ningun valor el enunciado $sql se ejecuta como siempre. Esto es util para reescribir querys o para contar ejecuciones.

Tambien puedes desear reemplazar la funcion Execute con una propia. En este caso, que tu funcion regrese un valor. Si se obtiene un valor, el valor se regresa inmediatamente sin ningun procesamiento. Esto lo uso ADodb internamente para implementar LogSQL().


Funciones de auxilio de ADOConnection

BlankRecordSet([$queryid])

Ya no esta disponible, se quito desde laversion 1.99.

Concat($s1,$s2,....)

Genera la cadena de caracteres para concatenar $s1, $s2, etc. Emplea el texto en la propiedad concat_operator para generar la concatenacion. Omita la funcion si no se usa un caracter de concatenacion, como en MySQL.

Regresa la cadena concatenada.

DBDate($date)

Formatea el campo $date en un formato fecha que la base de datos acepte. Se emplea en enunciados INSERT/UPDATE; para enunciados SELECT emplee SQLDate. El parametro $date puede ser un entero con la fecha Unix o una cadena en formato ISO Y-m-d. Emplea la propiedad fmtDate que contiene el formato a emplear. Si le menda como parametro null o false o '', genera un null de SQL.

Regresa la fecha como una cadena encomillada.

    $sql = "select * from atable where created > ".$db->DBDate("$year-$month-$day");
    $db->Execute($sql);

BindDate($date)

Formatea la fecha ($date) en formato que la base de datos acepte para variables posicionales. Normalmente esto significa que la cadena no se entre comilla.

    $sql = "select * from atable where created > ".$db->Param('0');
    // or
    $sql = "select * from atable where created > ?";
    $db->Execute($sql,array($db->BindDate("$year-$month-$day"));

DBTimeStamp($ts)

Formatea el registro de tiempo $ts en un formato que acepte la base de datos, puede ser un entero de Unix o una cadena en el formato ISO Y-m-d H:i:s. Emplea el valor de la propedad fmtTimeStamp, que contiene el formato a emplear. Si le menda como parametro null o false o '', genera un null de SQL.

Regresa el registro de tiempo como una cadena encomillada.

    $sql = "select * from atable where created > ".$db->DBTimeStamp("$year-$month-$day $hr:$min:$secs");
    $db->Execute($sql);

BindTimeStamp($ts)

Formatea el resgistro de tiempo $ts en formato de variable posicional para ser aceptado por la base de datos. Esto casi siempre significa que la cadena no sera encomillada.

    $sql = "select * from atable where created > ".$db->Param('0');
    // or
    $sql = "select * from atable where created > ?";
    $db->Execute($sql,array($db->BindTimeStamp("$year-$month-$day $hr:$min:$secs"));

qstr($s,[$magic_quotes_enabled=false])

Encierra entre comillas una cadena a ser enviada a la base de datos. Puede verse extraño el parametro $magic_quotes_enabled, pero la idea es por si esta encomillando cadenas obtenidas por POST o GET, se puede mandar get_magic_quotes_gpc() como el segundo parametro. Esto nos asegura que la variable no se encomille dos veces, una por qstr y la otra por magic_quotes_gpc.

Ej. $s = $db->qstr(HTTP_GET_VARS['name'],get_magic_quotes_gpc());

Regresa la cadena encomillada.

Quote($s)

Encierra entre comillas la cadena $s, protegiendo el caracter especifico de encomillado de la base de datos. Anteriormente verificaba el estado de 'magic quotes', pero se deshabilito desde la version 3.31 para que sea compatible con el paquete DB de PEAR.

Affected_Rows( )

Regresa el numero de renglones afectados por un enunciado update o delete. Regresa falso si la funcion no esta soportada.

Actualmente no esta soportada para interbase/firebird.

Insert_ID( )

Regresa el ultimo identificador de numeracion automatico insertado (serial). Regresa falso si la funcion no esta soportada.

Unicamente soportado por bases de datos que manejan auto incrementos o identificador de objetos (OID) como PostgreSQL, actualmente MySQL y MS SQL Server. PostgreSQL regresa el OID, que puede cambiar en una recarga de la base de datos.

RowLock($table,$where)

Asegura el renglon de una tabla por la duracion de la transaccion. Por ejemplo, para asegurar el renglon $id de la tabla 'table1':

	$DB->StartTrans();
	$DB->RowLock("table1","rowid=$id");
	$DB->Execute($sql1);
	$DB->Execute($sql2);
	$DB->CompleteTrans();

Funciona en db2, interbase, informix, mssql, oci8, postgres, sybase.

MetaDatabases()

Regresa un arreglo con la lista de bases de datos disponibles en el servidor. Debes de estar conectado al servidor. Solo disponible para ODBC, MySQL y ADO.

MetaTables($ttype = false, $showSchema = false, $mask=false)

Regresa un arreglo de las tablas y vistas de la base de datos actual. El arreglo omitira en lo posible las tablas del sistema. Para unicamente mostar tablas use db->MetaTables('TABLES'). Para unicamente mostar vistas use $db->MetaTables('VIEWS'). Actualmente el parametro $showSchema solo funciona para DB2, y cuando es verdadero, agerga el nombre del esquema a la tabla, ej. "SCHEMA.TABLE".

Se puede definir una mascara de coincidencia. Por ejemplo, con $mask = 'TMP%' solo encontrara las tablas que empiecen con 'TMP'. Por lo pronto solo mssql, oci8, odbc_mssql y postgres* manejan el parametro $mask.

MetaColumns($table,$toupper=true)

Regresa un arreglo de objetos de la clase ADOFieldObject, un objeto por cada columna de la tabla $table. Cada instancia tiene definidos las propiedades (name, type, max_length). Actualmente Sybase no reconoce los tipos de fecha y ADO no puede identificar el tipo adecuado de datos (por lo que se identifican como 'varchar').

El parametro $toupper determina si hay que convertir a mayusculas el nombre de la tabla (requerido por algunas bases de datos).

Para el manejo de esquemas, en el parametro $table mande el valor "$schema.$tablename". Estos solo funciona en algunas bases de datos.

MetaColumnNames($table)

Regresa un arreglo con los nombres de las columnas de la tabla $table. Desde ADOdb 4.22, es un arreglo asociativo con las llaves en mayusculas.

Es decir, array('FIELD1' => 'Field1', 'FIELD2'=>'Field2')

MetaPrimaryKeys($table, $owner=false)

Regresa un arreglo con el nombre de las columnas que forman la llave primaria de la tabla $table. Actualmente manejado por mysql, odbc (including db2, odbc_mssql, etc), mssql, postgres, interbase/firebird, oci8.

Las vistas (y algunas tablas) tienen llave primaria, pero algunas veces esta informacion no esta disponible para la base de datos. Tu puedes definir una funcion ADODB_View_PrimaryKeys($databaseType, $database, $view, $owner) que regrese el arreglo conteniendo los campos que forman la llave primaria. Si esta funcion existe sera invocada cuando MetaPrimaryKeys() no pueda encontrar la llave primaria para tabla o vista.

// En este ejemplo: dbtype = 'oci8', $db = 'mydb', $view = 'dataView', $owner = false 
function ADODB_View_PrimaryKeys($dbtype,$db,$view,$owner)
{
	switch(strtoupper($view)) {
	case 'DATAVIEW': return array('DATAID');
	default: return false;
	}
}

$db = NewADOConnection('oci8');
$db->Connect('localhost','root','','mydb'); 
$db->MetaPrimaryKeys('dataView');

ServerInfo($table)

Regresa un arreglo asociativo con dos elementos 'description' y 'version'. El elemento 'description' contiene una cadena con la descripcion de la base de datos. El elemento 'version' contiene una cadena con el numero de version.

MetaForeignKeys($table, $owner=false, $upper=false)

Regresa un arreglo asociativo con las llaves foraneas (foreign keys) de la tabla. o falso si no esta soportado. Por ejemplo, si la tabla 'empleados' tiene una llave foranea 'empleados.empl_dept' apunta a 'departamentos.dept_clav', y empleados.empl_puesto=organigrama.orga_puesto y empleados.empl_cat=organigrama.orga_cat, entonces $conn->MetaForeignKeys('empleados') obtendra como resultado:

	array(
		'departamentos' => array('empl_dept=dept_clav'),
		'organigrama' => array('empl_puesto=orga_puesto','empl_cat=orga_cat')
	)

Opcionalmente el dueño de la tabla o vista se puede definir en $owner. Si $upper es verdadero entonces el nombre de las tables (las llaves del arreglo) se convierten a mayusculas.


ADORecordSet

Cuando se ejectuta satisfactoriamente un enunciado SQL con el metodo ADOConnection->Execute($sql), se obtiene un objeto ADORecordSet. Este objeto contiene: un cursor virtual para podernos mover de renglon en renglon, funciones para obtener informacion acerca de las columnas y sus tipos de datos, y funciones auxiliares para el formateo de los resultados para ser mostrados al usuario.

Campos/propiedades de ADORecordSet

fields: Arreglo que contiene el renglon actual. No es asociativo, sino un arreglo indexado del 0 al (columnas - 1). Vea tambien la funcion Fields, que se comprota como un arreglo asociativo.

dataProvider: El mecanismo subyacente empleado para conectarse a la base de datos. Normalmete vale native, a menos que sea odbc o ado.

blobSize: Tamaño maximo de un objeto char, string o varchar antes de que se considere como un Blob (Los Blobs se deberan mostar en textareas). Vea la funcion MetaType function.

sql: Contiene el enunciado sql empleado para generar este conjunto de datos.

canSeek: Con valor verdadero si la funcion Move( ) funciona..

EOF: Verdadero si se ha navegado el cursor despues del ultimo registro.

Funciones/metodos de ADORecordSet

ADORecordSet( )

Constructor. Normalmente nunca hay que llamar a esta funcion.

GetAssoc([$force_array])

Genera un arreglo asociativo del recordset. Observe que esta funcion tambien esta disponible en el objeto de conexion. Mas detalles se pueden encontar ahi.

GetArray([$number_of_rows])

Genera un arreglo bidimensional de registros desde la position actual del cursor, indexado desde 0 a ($number_of_rows - 1). Si no se define $number_of_rows, se indexa hasta el final de recordset (EOF).

GetRows([$number_of_rows])

Genera un arreglo bidimensional de registros desde la posicion actual del cursor, Sinomimo de GetArray() para tener compatibilidad con Microsoft ADO.

GetMenu($name, [$default_str=''], [$blank1stItem=true], [$multiple_select=false], [$size=0], [$moreAttr=''])

Genera un menu HTML (<select><option><option></select>). La primera columna del recordset (fields[0]) contiene el texto a desplegar en la etiqueta option. Si el recordset tiene mas de 1 columna, la segunda columna (fields[1]) es el valor a enviar al servidor Web. La variable del menu tendra el nombre $name.

Si esta definido $default_str, entonces si $default_str == fields[0], entonces ese campo se selecciona. Si $blank1stItem es verdadero, la primera opcion esta en blanco. Tambien se le puede poner un texto a la primera opcion con $blank1stItem = "$valor:$texto".

$Default_str puede ser un arreglo para una caja de opcion multiple.

Para obtener una caja, asignele a $size un valor diferente de cero (o mande $default_str como un arreglo). Si $multiple_select es verdadero entonces se generara un caja con $size elementos (o si $size==0, con 5 elementos) visibles, y se regresera un arreglo al servidor. Finalmente emplee $moreAttr para agregar atributos adicionales como javascript o styles.

Ejemplo de Menu 1: GetMenu('menu1','A',true) genera el menu: con los datos (A,1), (B,2), (C,3). Tambien vea el ejemplo 5.

Ejemplo de Menu 2: Con los mismo datos, GetMenu('menu1',array('A','B'),false) generara un menu con A y B seleccionados:

GetMenu2($name, [$default_str=''], [$blank1stItem=true], [$multiple_select=false], [$size=0], [$moreAttr=''])

Es casi indentica a GetMenu, excepto que $default_str se compara contra fields[1] (el valor de la opcion).

Ejemplo de Menu 3: Con el conjunto de datos del ejemplo 1, GetMenu2('menu1',array('1','2'),false) generara un menu con A y B seleccionados como en el ejemplo 2, pero en esta ocasion la seleccion se baso en la segunda columna, que contiene el valor a regresar al servidor Web.

UserDate($str, [$fmt])

Convierte la cadena de caracteres con una fecha $str a otro formato fecha. El formato de fecha es Y-m-d o un timestamp de Unix. El valor por omision de $fmt es Y-m-d.

UserTimeStamp($str, [$fmt])

Convierte la cadena de caracteres con un timestamp $str a otro formato. El formato de timestamp es Y-m-d H:i:s, como en '2002-02-28 23:00:12', o un timestamp de Unix. UserTimeStamp llama a UnixTimeStamp para analizar $str. El valor por omision de $fmt es to Y-m-d H:i:s.

UnixDate($str)

Analiza la cadena $str por una fecha y la regresa en el formato unix para mktime (es decir un numero indicando el numero de segundos desde el 1° de enero de 1970). Supone que la fecha tiene formato Y-m-d H:i:s, excepto para Sybase y Microsoft SQL Server, donde tambien se acepta M d Y (El mes a 3 letras es controlado por un arreglo global que puede necesitar tropicalizacion).

La funcion esta disponible tanto para ADORecordSet y ADOConnection desde 1.91.

UnixTimeStamp($str)

Analiza la cadena $str por un timestap y lo regresa en el formato unix para mktime (es decir un numero indicando el numero de segundos desde el 1° de enero de 1970). Espera la fecha en formato "Y-m-d, H:i:s" (1970-12-24, 00:00:00) o "Y-m-d H:i:s" (1970-12-24 00:00:00) o "YmdHis" (19701225000000), excepto para Sybase y Microsoft SQL Server, donde tambien se acepta "M d Y h:i:sA" (Dec 25 1970 00:00:00AM), (El mes a 3 letras se controla por un arreglo global que puede necesitar tropicalizacion).

La funcion esta disponible tanto para ADORecordSet y ADOConnection desde 1.91.

OffsetDate($dayFraction, $basedate=false)

Regresa una cadena con la funcion SQL nativa para calcular fechas futuras y pasadas en base $basedate. Si $basedate no esta definida entonces se toma la fecha actual (a las 12 de la noche). Regresa la cadena SQL que realiza los calculos cuando se procesa por Execute().

Por ejemplo, en Oracle, para encontrar la fecha que esta 2.5 dias en el futuro:

# obtener fecha una semana en el futuro
$fld = $conn->OffsetDate(7); // Regresa "(trunc(sysdate)+7")
# obtener fecha y hora que esta 60 horas en el futuro
$fld = $conn->OffsetDate(2.5, $conn->sysTimeStamp);	// regresa "(sysdate+2.5)"

Esta funcion esta disponible en los driverrs mysql, mssql, oracle, oci8 y postgresql desde 2.13. Puede funcionar con otros drivers siempre y cuando permitan aritmetica de fechas.

SQLDate($dateFormat, $basedate=false) Regresa una cadena que contiene la funcion SQL nativa para formatear una fecha o el campo fecha $basedate. Es usado en enunciados SELECT. Para enunciados INSERT/UPDATE use DBDate. Emplea un formato con mayusculas/minusculas en $dateFormat, que maneja:

 Y: Año a 4 digitis
 Q: Trimestre (1-4)
 M: Mes (Jan-Dec)
 m: Mes (01-12)
 d: Dia (01-31)
 H: Hora (00-23)
 h: Hora (1-12)
 i: Minuto (00-59)
 s: Segundo (00-60)
 A: Indicador de AM/PM

Todos los demas caracteres se tratan como cadena. Se puede usar \ para escapar caracteres. Disponible en algunas bases de datos, incluyendo mysql, postgresql, mssql, oci8 y DB2.

Es util para escribir enunciados sql portable que hacen GROUP BY por fechas. Por ejemplo para mostrar el costo total de los bienes vendidos por cada trimestre (las fecha estan en el campo llamado postdate):

 $sqlfn = $db->SQLDate('Y-\QQ','postdate'); # obtiene el sql que formatea postdate 
 $sql = "SELECT $sqlfn,SUM(cogs) FROM table GROUP BY $sqlfn ORDER BY 1 desc";
 

MoveNext( )

Mueve el cursor al siguiente renglon. El arreglo $this->fields se actualiza automaticamente. Regresa falso si no lo pudo hacer (normalmente debido a que se encontrol el EOF), en caso contrario regresa verdadero.

Si se alcanzo el EOF, entonces el arreglo $this->fields tiene valor falso (esto funciona consistentemente a partir de ADOdb 3.30). Para tener el comportamiento que habia antes de la version 3.30 en $this->fields (en EOF), ponga la variable global $ADODB_COMPAT_FETCH = true.

Ejemplo:

$rs = $db->Execute($sql);
if ($rs) 
	while (!$rs->EOF) {
 		ProcessArray($rs->fields);	
		$rs->MoveNext();
	} 

Move($to)

Mueve el cursor interno al renglon $to. En numero de renglon empieza en 0, es decir 0 es el primer renglon. El arreglo fields es actualizado automaticamente. Para aquellas bases de datos que no manejan internamente la navegacion, ADOdb simulara la navegacion para adelante. Algunas bases de datos no manejan la navegacion para atras. Si $to esta despues del EOF, $to se movera al final del RecordSet en la mayoria de las bases de datos. Algunas bases de datos poco claras usando odbc pueden no comportarse de esta manera.

Observacion: Esta funcion emplea posicionamiento absoluto , a comparacion de Microsoft's ADO.

Regresa verdadero o falso. Si es falso, el cursor interno no se mueve en la mayoria de las implementaciones, en cuyo caso AbsolutePosition( ) regresara la ultima posicion del cursor antes del Move( ).

MoveFirst()

Internamente invoca Move(0). Algunas bases de datos no manejan esta funcion.

MoveLast()

Internamente llama Move(RecordCount()-1). Algunas bases de datos no manejan esta funcion.

GetRowAssoc($toUpper=true)

Regresa un arreglo asociativo conteniendo el renglon actual. Las llaves del arreglo son los nombres de las columnas. El nombre de las columnas esta en mayusculas para facilitar el acceso. Para obtener el siguiente renglon todavia es necesario invocar MoveNext().

Por ejemplo:
Array ( [ID] => 1 [FIRSTNAME] => Caroline [LASTNAME] => Miranda [CREATED] => 2001-07-05 )

Nota: no use GetRowAssoc() con $ADODB_FETCH_MODE = ADODB_FETCH_ASSOC. debido a que tienen la misma funcionalidad e interfiere uno con el otro.

AbsolutePage($page=-1)

Regresa la pagina indicada. Requiere que se haya llamado PageExecute() o CachePageExecute(). Ver Ejemplo 8.

AtFirstPage($status='')

Regresa verdadero si esta en la primera pagina, (en base a 1). Requiere que se haya llamado a PageExecute() o CachePageExecute(). ver Ejemplo 8.

AtLastPage($status='')

Regresa verdadero si esta en la ultima pagina, (en base a 1). Requiere que se haya llamado a PageExecute() o CachePageExecute(). ver Ejemplo 8.

Fields($colname)

Regresa el valor de la columna $colname. Al nombre de la columna no le afectan las mayusculas.

Esta funcion solo esta por comodidad. Para un mejor rendimiento use $ADODB_FETCH_MODE.

FetchRow()

Regresa un arreglo conteniendo el renglon actual, or falso si es EOF. Internamente FetchRow( ) se mueve al siguiente renglon despues de regresar el renglon actual.

ADVERTENCIA: No mezcle FetchRow() con MoveNext().

Uso:

$rs = $db->Execute($sql);
if ($rs)
	while ($arr = $rs->FetchRow()) {
	     # process $arr	
	}

FetchInto(&$array)

Pone en el arreglo $array el renglon actual. Regresa un objeto PEAR_Error si EOF, 1 si es correcto (la constante DB_OK). Si PEAR no esta definido regresa falso cuando encuentra EOF. Internamente FetchInto() se mueve al siguiente registro despues de regresar el renglon actual.

Es mas facil de usar FetchRow(). Vea arriba.

FetchField($column_number)

Regresa un objeto conteniendo name, type and max_length de el campo solicitado. Si max_length no se pueden determinar con confianza, tendra el valor de -1. El numero de columna esta en base a cero (la primer columna es 0). Ver el ejemplo 2.

FieldCount( )

Regresa el numero de campos (columnas) en el recordset.

RecordCount( )

regresa el numero de renglones en el recordset. Si el numero de registros obtenidos no se puede determinar del API de la base de datos, se leeran todos los renglones para poderse contar. Esta lectura puede ser deshabilitada (por rendimiento) asignandole la variable $ADODB_COUNTRECS = false. Cuando esta deshabilitada, RecordCount( ) regresara -1 en algunas bases de datos. Vea arriba la lista de bases de datos soportadas para mas detalle.

RowCount es un sinonimo de RecordCount.

PO_RecordCount($table, $where)

Regresa el numero de registros en el recordset. Si la base de datos no lo maneja, ejecutara un SELECT COUNT(*) en la tabla $table, con el criterio dado $where, para obtener una estimacion del tamaño del recordset.

$numrows = $rs->PO_RecordCount("articles_table", "group=$group");

NextRecordSet()

Para las bases de datos que permiten que un query regrese varios recordsets, esta funcion permite cambiarse al siguiente recordset. Unicamente soportada para el driver de mssql.

$rs = $db->Execute('execute return_multiple_rs');
$arr1 = $rs->GetArray();
$rs->NextRecordSet();
$arr2 = $rs->GetArray();

FetchObject($toupper=true)

Regresa el renglon actual como un object. Si se manda $toupper = true, entonces los campos de los objetos estaran en mayusculas. Nota. La nueva funcion FetchNextObject() es el metodo recomendado para accesar los renglones como objetos. Vea a continuacion.

FetchNextObject($toupper=true)

Obtiene el renglon actual como un objeto y automaticamente avanza al siguiente renglon. Regresa falso si esta al final del archivo (EOF). Si se manda $toupper = true, entonces los campos del objeto estaran en mayusculas.

$rs = $db->Execute('select firstname,lastname from table');
if ($rs) {
	while ($o = $rs->FetchNextObject()) {
		print "$o->FIRSTNAME, $o->LASTNAME<BR>";
	}
}

Hay una concesion en la velocidad por usar FetchNextObject(). Si el rendimiento es importante, se deben de accesar los renglones con el arreglo fields[].

FetchObj()

Regresa el renglon actual como un objeto. Los nombres de los campos no se convierten a mayusculas al contrario de FetchObject.

FetchNextObj()

Regresa el renglon actual como un objeto y se mueve al siguiente registro. Si hay EOF regresa falso. Los campos no se convierten a mayusculas al contrario de FetchNextObject.

CurrentRow( )

Regresa el numero del renglon actual, Regresa 0 si es el primer renglon.

AbsolutePosition( )

Sinonimo de CurrentRow para compatibilidad con ADO. Regresa el numero del renglon actual. 0 si es el primer renglon.

MetaType($nativeDBType[,$field_max_length],[$fieldobj])

Determina el meta tipo generic del tipo de campo nativo $nativeDBType de la base de datos, y la longitud del campo $field_max_length. Toma en cuenta que field_max_length puede ser -1 si no es conocido. El objeto del campo regresado por FetchField() puede ser pasado a $fieldobj o como el primer parametro $nativeDBType. Es util para bases de datos como mysql que tienen propiedades adicionales en el objeto de campo como primary_key.

Emplea el campo blobSize y lo compara con $field_max_length para determinar si campo caracter es realmente un blob. Por ejemplo, $db->MetaType('char') will return 'C'.

Regresa:

Desde ADOdb 3.0, MetaType acepta $fieldobj como el primer parametro, en lugar de $nativeDBType.

Close( )

Cierra el recordset, limpia toda la memoria y recursos asociados con el recordset.

Si no se esta usando la administracion de memoria, no hay necesidad de llamar a esta funcion ya que los recordset son cerrados por PHP al final del script. Los enunciados SQL como INSERT/UPDATE/DELETE no regresan realmente un recordset, por lo que no hay que llamar a Close() para esos enunciados SQL.


function rs2html($adorecordset,[$tableheader_attributes], [$col_titles])

Esta es una funcion independiente (rs2html = recordset a html) que es similar a la funcion PHP odbc_result_all, imprime un ADORecordSet, $adorecordset como una tabla HTML. El parametro $tableheader_attributes nos permite controlar los atributos de la tabla (cellpadding, cellspacing y border). Finalmente se puede reemplazar el nombre de las columnas de la base de datos con nuestros propios titulos con el arreglo $col_titles. Esta diseñado mas como un mecanismo rapido de depuracion, no como un visor de recordsets en un sistema en produccion.

Se necesita incluir el archivo tohtml.inc.php.

Ejemplo de rs2html:

<?
include('adodb/tohtml.inc.php'); # Carga el codigo de ADOdb
include('adodb/adodb.inc.php'); # Carga el codigo de ADOdb
$conn = &ADONewConnection('mysql');   # crea la conexion 
$conn->PConnect('localhost','userid','','agora');# se conecta a agora db
$sql = 'select CustomerName, CustomerID from customers'; 
$rs   = $conn->Execute($sql); 
rs2html($rs,'border=2 cellpadding=3',array('Customer Name','Customer ID'));
?>

Diferencias entre la libreria ADOdb y Microsoft ADO

  1. ADOdb unicamente maneja recordsets creados por el objeto conexion. Los recordsets no pueden ser creados independientemente.
  2. Las propiedades de ADO se implementan como funciones en ADOdb. Esto hace mas sencillo de implementar cualquier funcionalidad mejorada de ADO en el futuro.
  3. La funcion ADORecordSet->Move() de ADOdb emplea posicionamiento absoluto, no relativo. Los bookmarks no estan soportados.
  4. ADORecordSet->AbsolutePosition() no puede ser usada para mover el cursor del registro.
  5. Los objetos de parametros de ADO no estan soportados. En su lugar existe la funcion ADOConnection::Parameter( ), la cual proporciona una interfase mas sencilla para nombrar parametros preparados e invocar procedimientos almacenados.
  6. Las propiedades del recordset para paginacion estan disponibles, pero implementados como en el Ejemplo 8.

Guia para crear manejadores de bases de datos

Aqui se describe como crear una clase para conectarse a una nueva base de datos. Para asegurarse que no hay duplicidad de trabajo, por favor mandemelo por correo a jlim#natsoft.com.my si decies crear una de esas clases.

Primero decide en un nombre en minusculas para noombrar al tipo de la base de datos. Digamos que se va a llamar 'xbase'.

Entonces hay que crear dos clases ADODB_xbase y ADORecordSet_xbase en el archivo adodb-xbase.inc.php.

La manera mas sencilla de crear un driver de base de datos es adaptando un driver ODBC existente. Entonces solo tenemos que crear una clase ADODB_xbase extends ADODB_odbc que maneja los formatos de date y timestamp, el operador de concatenacion , true y false. Para la clase ADORecordSet_xbase extends ADORecordSet_odbc se necesita cambiar la funcion MetaType. Para un ejemplo ver adodb-vfp.inc.php.

Los mas complicado es un driver nuevo que se conecta a una extension de PHP nueva. En ese caso necesitaras implementar varias funciones, Afortunadamente, no tienes que modificar la mayoria del codigo comlejo. Unicamente necesitas reescribir algunas funciones prototipo. Ve adodb-mysql.inc.php para un ejemplo.

El formato por default de ADOdb es internamente YYYY-MM-DD (Ansi-92). Todas las fechas se deben de convertir a ese formato cuando se pasen a una funcion ADOdb de fecha. Ve el ejemplo de Oracle que usa ALTER SESSION para cambiar el formato de fecha en _pconnect y _connect.

Funciones en ADOConnection a Sobreescribir

La definicion de un constructor para la funcion ADOConnection derivada es opcional. No hay necesidad de llamar el conctructor de la clase base.

_connect: Implementacion de bajo nivel del Connect. Regresa true o false. Debe de asignar _connectionID.

_pconnect: Implementacion de bajo nivel de PConnect. Regresa true o false. Debe de asignar _connectionID.

_query: Ejecuta un enunciado SQL. Regresa queryID, o false.

_close: Cierra la conexion -- PHP debe de limpiar todos los recordsets.

ErrorMsg: Almacena el mensaje de error en la variable privada _errorMsg.

Campos de ADOConnection a inicializar

_bindInputArray: Con valor true si se permite la liga (binding) de parametros para enunciados SQL de insert y update usando ?.

fmtDate

fmtTimeStamp

true

false

concat_operator

replaceQuote

hasLimit maneja SELECT * FROM TABLE LIMIT 10 de MySQL.

hasTop maneja el estilo de Microsoft SELECT TOP 10 * FROM TABLE.

Funciones de ADORecordSet a sobreescribir

Se necesita crear un constructor de tu clase derivada de ADORecordSet que invoque al constructor de la clase padre.

FetchField: como se documento anteriormente en ADORecordSet

_initrs: inicializacion de bajo nivel del recordset: inicializa los campos _numOfRows y _numOfFields -- invocada por el constructor.

_seek: busca un registro en particular. No carga los datos en el arreglo de campos. Eso lo hace _fetch. Regresa true o false. Observe que algunas implementaciones como Interbase no manejan seek. Poner canSeek a false.

_fetch: Obtiene un renglon usando la funcion de la extension de la base de datos y avanza al siguiente renglon. Carga el arreglo fields. Si el parametro $ignore_fields es true entonces no hay necesidad de cargar el arreglo fields, solo se mueve al siguiente renglon. Regresa true o false.

_close: Cierra el recordset

Fields: es el arreglo regresado por la extension PHP no es un arreglo asociativo, tendras que reescribirlo. Ve adodb-odbc.inc.php para un ejemplo. Para bases de datos como MySQL y MSSQL donde se obtiene un arreglo asociativo, no hay necesidad de reescribir la funcion.

Campos de ADOConnection a inicializar

canSeek: Con valor true si la funcion _seek funciona.

Optimizando PHP

Para informacion para optimizar PHP, lea este articulo acerca de Optimizando PHP.

Bitacora de Cambios (Change Log)

4.92 29 Aug 2006

Added IgnoreErrors() to bypass default error handling.

The _adodb_getcount() function in adodb-lib.inc.php, some ORDER BY bug fixes.

For ibase and firebird, set $sysTimeStamp = "CURRENT_TIMESTAMP".

Fixed postgres connection bug: http://phplens.com/lens/lensforum/msgs.php?id=11057.

Changed CacheSelectLimit() to flush cache when $secs2cache==-1 due to complaints from other users.

Added support for using memcached with CacheExecute/CacheSelectLimit. Requires memcache module PECL extension. Usage:

$db = NewADOConnection($driver);
$db->memCache = true; /// should we use memCache instead of caching in files
$db->memCacheHost = 126.0.1.1; /// memCache host
$db->memCachePort = 11211; /// this is default memCache port
$db->memCacheCompress = false; /// Use 'true' to store the item compressed (uses zlib)

$db->Connect(...);
$db->CacheExecute($sql);

Implemented Transpose() for recordsets. Recordset must be retrieved using ADODB_FETCH_NUM. First column becomes the column name.

$DB = NewADOConnection('mysql');
$DB->Connect(...);
$DB->SetFetchMode(ADODB_FETCH_NUM);
$rs = $DB->Execute('select productname,productid,unitprice from products limit 10');
$rs2 = $DB->Transpose($rs);
rs2html($rs2);

4.91 2 Aug 2006

Major session code rewrite .... See session docs.

PDO bindinputarray was not set properly for MySQL (changed from true to false).

Changed CacheSelectLimit() to re-cache when $secs2cache==0. This is one way to flush the cache when SelectLimit is called.

Added to quotes to mysql and mysqli: "SHOW COLUMNS FROM `%s`";

Removed accidental optgroup handling in GetMenu(). Fixed ibase _BlobDecode for php5 compat, and also mem alloc issues for small blobs, thx salvatori#interia.pl

Mysql driver OffsetDate() speedup, useful for adodb-sessions.

Fix for GetAssoc() PHP5 compat. See http://phplens.com/lens/lensforum/msgs.php?id=15425

Active Record - If inserting a record and the value of a primary key field is null, then we do not insert that field in as we assume it is an auto-increment field. Needed by mssql.

Changed postgres7 MetaForeignKeys() see http://phplens.com/lens/lensforum/msgs.php?id=15531

DB2 will now return db2_conn_errormsg() when it is a connection error.

4.90 8 June 2006

Changed adodb_countrec() in adodb-lib.inc.php to allow LIMIT to be used as a speedup to reduce no of records counted.

Added support for transaction modes for postgres and oci8 with SetTransactionMode(). These transaction modes affect all subsequent transactions of that connection.

Thanks to Halmai Csongor for suggestion.

Removed $off = $fieldOffset - 1 line in db2 driver, FetchField(). Tx Larry Menard.

Added support for PHP5 objects as Execute() bind parameters using __toString (eg. Simple-XML). Thx Carl-Christian Salvesen.

Rounding in tohtml.inc.php did not work properly. Fixed.

MetaIndexes in postgres fails when fields are deleted then added in again because the attnum has gaps in it. See http://sourceforge.net/tracker/index.php?func=detail&aid=1451245&group_id=42718&atid=433976. Fixed.

MetaForeignkeys in mysql and mysqli did not work when fetchMode==ADODB_FETCH_ASSOC used. Fixed.

Reference error in AutoExecute() fixed.

Added macaddr postgres type to MetaType. Maps to 'C'.

Added to _connect() in adodb-ado5.inc.php support for $database and $dataProvider parameters. Thx Larry Menard.

Added support for sequences in adodb-ado_mssql.inc.php. Thx Larry Menard.

Added ADODB_SESSION_READONLY.

Added session expiryref support to crc32 mode, and in LOB code.

Clear _errorMsg in postgres7 driver, so that ErrorMsg() displays properly when no error occurs.

Added BindDate and BindTimeStamp

4.81 3 May 2006

Fixed variable ref errors in adodb-ado5.inc.php in _query().

Mysqli setcharset fix using method_exists().

The adodb-perf.inc.php CreateLogTable() code now works for user-defined table names.

Error in ibase_blob_open() fixed. See http://phplens.com/lens/lensforum/msgs.php?id=14997

4.80 8 Mar 2006

Added activerecord support.

Added mysql $conn->compat323 = true if you want MySQL 3.23 compat enabled. Fixes GetOne() Select-Limit problems.

Added adodb-xmlschema03.inc.php to support XML Schema version 3 and updated adodb-datadict.htm docs.

Better memory management in Execute. Thx Mike Fedyk.

4.72 21 Feb 2006

Added 'new' DSN parameter for NConnect().

Pager now sanitizes $PHP_SELF to protect against XSS. Thx to James Bercegay and others.

ADOConnection::MetaType changed to setup $rs->connection correctly.

New native DB2 driver contributed by Larry Menard, Dan Scott, Andy Staudacher, Bharat Mediratta.

The mssql CreateSequence() did not BEGIN TRANSACTION correctly. Fixed. Thx Sean Lee.

The _adodb_countrecs() function in adodb-lib.inc.php has been revised to handle more ORDER BY variations.

4.71 24 Jan 2006

Fixes postgresql security issue related to binary strings. Thx to Andy Staudacher.

Several DSN bugs found:

1. Fix bugs in DSN connections introduced in 4.70 when underscores are found in the DSN.

2. DSN with _ did not work properly in PHP5 (fine in PHP4). Fixed.

3. Added support for PDO DSN connections in NewADOConnection(), and database parameter in PDO::Connect().

The oci8 datetime flag not correctly implemented in ADORecordSet_array. Fixed.

Added BlobDelete() to postgres, as a counterpoint to UpdateBlobFile().

Fixed GetInsertSQL() to support oci8po.

Fixed qstr() issue with postgresql with \0 in strings.

Fixed some datadict driver loading issues in _adodb_getdriver().

Added register shutdown function session_write_close in adodb-session.inc.php for PHP 5 compat. See http://phplens.com/lens/lensforum/msgs.php?id=14200.

4.70 6 Jan 2006

Many fixes from Danila Ulyanov to ibase, oci8, postgres, mssql, odbc_oracle, odbtp, etc drivers.

Changed usage of binary hint in adodb-session.inc.php for mysql. See http://phplens.com/lens/lensforum/msgs.php?id=14160

Fixed invalid variable reference problem in undomq(), adodb-perf.inc.php.

Fixed http://phplens.com/lens/lensforum/msgs.php?id=14254 in adodb-perf.inc.php, _DBParameter() settings of fetchmode was wrong.

Fixed security issues in server.php and tmssql.php discussed by Andreas Sandblad in a Secunia security advisory. Added $ACCEPTIP = 127.0.0.1 and changed suggested root password to something more secure.

Changed pager to close recordset after RenderLayout().

4.68 25 Nov 2005

PHP 5 compat for mysqli. MetaForeignKeys repeated twice and MYSQLI_BINARY_FLAG missing.

PHP 5.1 support for postgresql bind parameters using ? did not work if >= 10 parameters. Fixed. Thx to Stanislav Shramko.

Lots of PDO improvements.

Spelling error fixed in mysql MetaForeignKeys, $associative parameter.

4.67 16 Nov 2005

Postgresql not_null flag not set to false correctly. Thx Cristian MARIN.

We now check in Replace() if key is in fieldArray. Thx Séstien Vanvelthem.

_file_get_contents() function was missing in xmlschema. fixed.

Added week in year support to SQLDate(), using 'W' flag. Thx Spider.

In sqlite metacolumns was repeated twice, causing PHP 5 problems. Fixed.

Made debug output XHTML compliant.

4.66 28 Sept 2005

ExecuteCursor() in oci8 did not clean up properly on failure. Fixed.

Updated xmlschema.dtd, by "Alec Smecher" asmecher#smecher.bc.ca

Hardened SelectLimit, typecasting nrows and offset to integer.

Fixed misc bugs in AutoExecute() and GetInsertSQL().

Added $conn->database as the property holding the database name. The older $conn->databaseName is retained for backward compat.

Changed _adodb_backtrace() compat check to use function_exists().

Bug in postgresql MetaIndexes fixed. Thx Kevin Jamieson.

Improved OffsetDate for MySQL, reducing rounding error.

Metacolumns added to sqlite. Thx Mark Newnham.

PHP 4.4 compat fixes for GetAssoc().

Added postgresql bind support for php 5.1. Thx Cristiano da Cunha Duarte

OffsetDate() fixes for postgresql, typecasting strings to date or timestamp.

DBTimeStamp formats for mssql, odbc_mssql and postgresql made to conform with other db's.

Changed PDO constants from PDO_ to PDO:: to support latest spec.

4.65 22 July 2005

Reverted 'X' in mssql datadict to 'TEXT' to be compat with mssql driver. However now you can set $datadict->typeX = 'varchar(4000)' or 'TEXT' or 'CLOB' for mssql and oci8 drivers.

Added charset support when using DSN for Oracle.

_adodb_getmenu did not use fieldcount() to get number of fields. Fixed.

MetaForeignKeys() for mysql/mysqli contributed by Juan Carlos Gonzalez.

MetaDatabases() now correctly returns an array for mysqli driver. Thx Cristian MARIN.

CompleteTrans(false) did not return false. Fixed. Thx to JMF.

AutoExecute() did not work with Oracle. Fixed. Thx Joséoreira.

MetaType() added to connection object.

More PHP 4.4 reference return fixes. Thx Ryan C Bonham and others.

4.64 20 June 2005

In datadict, if the default field value is set to '', then it is not applied when the field is created. Fixed by Eugenio.

MetaPrimaryKeys for postgres did not work because of true/false change in 4.63. Fixed.

Tested ocifetchstatement in oci8. Rejected at the end.

Added port to dsn handling. Supported in postgres, mysql, mysqli,ldap.

Added 'w' and 'l' to mysqli SQLDate().

Fixed error handling in ldap _connect() to be more consistent. Also added ErrorMsg() handling to ldap.

Added support for union in _adodb_getcount, adodb-lib.inc.php for postgres and oci8.

rs2html() did not work with null dates properly.

PHP 4.4 reference return fixes.

4.63 18 May 2005

Added $nrows<0 check to mysqli's SelectLimit().

Added OptimizeTable() and OptimizeTables() in adodb-perf.inc.php. By Markus Staab.

PostgreSQL inconsistencies fixed. true and false set to TRUE and FALSE, and boolean type in datadict-postgres.inc.php set to 'L' => 'BOOLEAN'. Thx Kevin Jamieson.

New adodb_session_create_table() function in adodb-session.inc.php. By Markus Staab.

Added null check to UserTimeStamp().

Fixed typo in mysqlt driver in adorecordset. Thx to Andy Staudacher.

GenID() had a bug in the raiseErrorFn handling. Fixed. Thx Marcos Pont.

Datadict name quoting now handles ( ) in index fields correctly - they aren't part of the index field.

Performance monitoring: (1) oci8 Ixora checks moved down; (2) expensive sql changed so that only those sql with count(*)>1 are shown; (3) changed sql1 field to a length+crc32 checksum - this breaks backward compat.

We remap firebird15 to firebird in data dictionary.

4.62 2 Apr 2005

Added 'w' (dow as 0-6 or 1-7) and 'l' (dow as string) for SQLDate for oci8, postgres and mysql.

Rolled back MetaType() changes for mysqli done in prev version.

Datadict change by chris, cblin#tennaxia.com data mappings from:

oci8:  X->varchar(4000) XL->CLOB
mssql: X->XL->TEXT
mysql: X->XL->LONGTEXT
fbird: X->XL->varchar(4000)

to:

oci8:  X->varchar(4000) XL->CLOB
mssql: X->VARCHAR(4000) XL->TEXT
mysql: X->TEXT          XL->LONGTEXT
fbird: X->VARCHAR(4000) XL->VARCHAR(32000)

Added $connection->disableBlobs to postgresql to improve performance when no bytea is used (2-5% improvement).

Removed all HTTP_* vars.

Added $rs->tableName to be set before calling AutoExecute().

Alex Rootoff rootoff#pisem.net contributed ukrainian language file.

Added new mysql_option() support using $conn->optionFlags array.

Added support for ldap_set_option() using the $LDAP_CONNECT_OPTIONS global variable. Contributed by Josh Eldridge.

Added LDAP_* constant definitions to ldap.

Added support for boolean bind variables. We use $conn->false and $conn->true to hold values to set false/true to.

We now do not close the session connection in adodb-session.inc.php as other objects could be using this connection.

We now strip off \0 at end of Ixora SQL strings in $perf->tohtml() for oci8.

4.61 23 Feb 2005

MySQLi added support for mysqli_connect_errno() and mysqli_connect_error().

Massive improvements to alpha PDO driver.

Quote string bind parameters logged by performance monitor for easy type checking. Thx Jason Judge.

Added support for $role when connecting with Interbase/firebird.

Added support for enum recognition in MetaColumns() mysql and mysqli. Thx Amedeo Petrella.

The sybase_ase driver contributed by Interakt Online. Thx Cristian Marin cristic#interaktonline.com.

Removed not_null, has_default, and default_value from ADOFieldObject.

Sessions code, fixed quoting of keys when handling LOBs in session write() function.

Sessions code, added adodb_session_regenerate_id(), to reduce risk of session hijacking by changing session cookie dynamically. Thx Joe Li.

Perf monitor, polling for CPU did not work for PHP 4.3.10 and 5.0.0-5.0.3 due to PHP bugs, so we special case these versions.

Postgresql, UpdateBlob() added code to handle type==CLOB.

4.60 24 Jan 2005

Implemented PEAR DB's autoExecute(). Simplified design because I don't like using constants when strings work fine.

_rs2serialize will now update $rs->sql and $rs->oldProvider.

Added autoExecute().

Added support for postgres8 driver. Currently just remapped to postgres7 driver.

Changed oci8 _query(), so that OCIBindByName() sets the length to -1 if element size is > 4000. This provides better support for LONGs.

Added SetDateLocale() support for netherlands (Nl).

Spelling error in pivot code ($iff should be $iif).

mysql insert_id() did not work with mysql 3.x. Fixed.

"\r\n" not converted to spaces correctly in exporting data. Fixed.

_nconnect() in mysqli did not return value correctly. Fixed.

Arne Eckmann contributed danish language file.

Added clone() support to FetchObject() for PHP5.

Removed SQL_CUR_USE_ODBC from odbc_mssql.

4.55 5 Jan 2005

Found bug in Execute() with bind params for db's that do not support binding natively.

DropSequence() now correctly uses default parameter.

Now Execute() ignores locale for floats, so 1.23 is NEVER converted to 1,23.

SetFetchMode() not properly saved in adodb-perf, suspicious sql and expensive sql. Fixed.

Added INET to postgresql metatypes. Thx motzel.

Allow oracle hints to work when counting with _adodb_getcount in adodb-lib.inc.php. Thx Chris Wrye.

Changed mysql insert_id() to use SELECT LAST_INSERT_ID().

If alter col in datadict does not modify col type/size of actual col, then it is removed from alter col code. By Mark Newham. Not perfect as MetaType() !== ActualType().

Added handling of view fields in metacolumns() for postgresql. Thx Renato De Giovanni.

Added to informix MetaPrimaryKeys and MetaColumns fixes for null bit. Thx to Cecilio Albero.

Removed obsolete connection_timeout() from perf code.

Added support for arrayClass in adodb-csv.inc.php.

RSFilter now accepts methods of the form $array($obj, 'methodname'). Thx to blake#near-time.com.

Changed CacheFlush to $cmd = 'rm -rf '.$ADODB_CACHE_DIR.'/[0-9a-f][0-9a-f]/';

For better cursor concurrency, added code to free ref cursors in oci8 when $rs->Close() is called. Note that CLose() is called internally by the Get* functions too.

Added IIF support for access when pivoting. Thx Volodia Krupach.

Added mssql datadict support for timestamp. Thx Alexios.

Informix pager fix. By Mario Ramirez.

ADODB_TABLE_REGEX now includes ':'. By Mario Ramirez.

Mark Newnham contributed MetaIndexes for oci8 and db2.

4.54 5 Nov 2004

Now you can set $db->charSet = ?? before doing a Connect() in oci8.

Added adodbFetchMode to sqlite.

Perf code, added a string typecast to substr in adodb_log_sql().

Postgres: Changed BlobDecode() to use po_loread, added new $maxblobsize parameter, and now it returns the blob instead of sending it to stdout - make sure to mention that as a compat warning. Also added $db->IsOID($oid) function; uses a heuristic, not guaranteed to work 100%.

Contributed arabic language file by "El-Shamaa, Khaled" k.el-shamaa#cgiar.org

PHP5 exceptions did not handle @ protocol properly. Fixed.

Added ifnull handling for postgresql (using coalesce).

Added metatables() support for Postgresql 8.0 (no longer uses pg_% dictionary tables).

Improved Sybase ErrorMsg() function. By Gaetano Giunta.

Improved oci8 SelectLimit() to use Prepare(). By Cristiano Duarte.

Type-cast $row parameter in ifx_fetch_row() to int. Thx stefan bodgan.

Ralf becker contributed improvements in postgresql, sapdb, mysql data dictionary handling:
- MySql and Postgres MetaType was reporting every int column which was part of a primary key and unique as serial
- Postgres was not reporting the scale of decimal types
- MaxDB was padding the defaults of none-string types with spaces
- MySql now correctly converts enum columns to varchar

Ralf also changed Postgresql datadict:
- you cant add NOT NULL columns in postgres in one go, they need to be added as NULL and then altered to NOT NULL
- AlterColumnSQL could not change a varchar column with numbers into an integer column, postgres need an explicit conversation
- a re-created sequence was not set to the correct value, if the name was the old name (no implicit sequence), now always the new name of the implicit sequence is used

Sergio Strampelli added extra $intoken check to Lens_ParseArgs() in datadict code.

4.53 28 Sept 2004

FetchMode cached in recordset is sometimes mapped to native db fetchMode. Normally this does not matter, but when using cached recordsets, we need to switch back to using adodb fetchmode. So we cache this in $rs->adodbFetchMode if it differs from the db's fetchMode.

For informix we now set canSeek = false driver because stefan bodgan tells me that seeking doesn't work.

SetDateLocale() never worked till now ;-) Thx david#tomato.it

Set $_bindInputArray = true in sapdb driver. Required for clob support.

Fixed some PEAR::DB emulation issues with isError() and isWarning. Thx to Gert-Rainer Bitterlich.

Empty() used in getupdatesql without strlen() check. Fixed.

Added unsigned detection to mysql and mysqli drivers. Thx to dan cech.

Added hungarian language file. Thx to Halászvári Gábor.

Improved fieldname-type formatting of datadict SQL generated (adding $widespacing parameter to _GenField).

Datadict oci8 DROP CONSTRAINTS misspelt. Fixed. Thx Mark Newnham.

Changed odbtp to dynamically change databaseType based on connection, eg. from 'odbtp' to 'odbtp_mssql' when connecting to mssql database.

In datadict, MySQL I4 was wrongly mapped to MEDIUMINT, which is actually I3. Fixed.

Fixed mysqli MetaType() recognition. Mysqli returns numeric types unlike mysql extension. Thx Francesco Riosa.

VFP odbc driver curmode set wrongly, causing problems with memo fields. Fixed.

Odbc driver did not recognize odbc version 2 driver date types properly. Fixed. Thx Bostjan.

ChangeTableSQL() fixes to datadict-db2.inc.php by Mark Newnham.

Perf monitoring with odbc improved. Now we try in perf code to manually set the sysTimeStamp using date() if sysTimeStamp is empty.

All ADO errors are thrown as exceptions in PHP5. So we added exception handling to ado in PHP5 by creating new adodb-ado5.inc.php driver.

Added IsConnected(). Returns true if connection object connected. By Luca.Gioppo.

"Ralf Becker" RalfBecker#digitalROCK.de contributed new sapdb data-dictionary driver and a large patch that implements field and table renaming for oracle, mssql, postgresql, mysql and sapdb. See the new RenameTableSQL() and RenameColumnSQL() functions.

We now check ExecuteCursor to see if PrepareSP was initially called.

Changed oci8 datadict to use MODIFY for $dd->alterCol. Thx Mark Newnham.

4.52 10 Aug 2004

Bug found in Replace() when performance logging enabled, introduced in ADOdb 4.50. Fixed.

Replace() checks update stmt. If update stmt fails, we now return immediately. Thx to alex.

Added support for $ADODB_FORCE_TYPE in GetUpdateSQL/GetInsertSQL. Thx to niko.

Added ADODB_ASSOC_CASE support to postgres/postgres7 driver.

Support for DECLARE stmt in oci8. Thx Lochbrunner.

4.51 29 July 2004

Added adodb-xmlschema 1.0.2. Thx dan and richard.

Added new adorecordset_ext_* classes. If ADOdb extension installed for mysql, mysqlt and oci8 (but not oci8po), we use the superfast ADOdb extension code for movenext.

Added schema support to mssql and odbc_mssql MetaPrimaryKeys().

Patched MSSQL driver to support PHP NULL and Boolean values while binding the input array parameters in the _query() function. By Stephen Farmer.

Added support for clob's for mssql, UpdateBlob(). Thx to gfran#directa.com.br

Added normalize support for postgresql (true=lowercase table name, or false=case-sensitive table names) to MetaColumns($table, $normalize=true).

PHP5 variant dates in ADO not working. Fixed in adodb-ado.inc.php.

Constant ADODB_FORCE_NULLS was not working properly for many releases (for GetUpdateSQL). Fixed. Also GetUpdateSQL strips off ORDER BY now - thx Elieser Leão.

Perf Monitor for oci8 now dynamically highlights optimizer_* params if too high/low.

Added dsn support to NewADOConnection/ADONewConnection.

Fixed out of page bounds bug in _adodb_pageexecute_all_rows() Thx to "Sergio Strampelli" sergio#rir.it

Speedup of movenext for mysql and oci8 drivers.

Moved debugging code _adodb_debug_execute() to adodb-lib.inc.php.

Fixed postgresql bytea detection bug. See http://phplens.com/lens/lensforum/msgs.php?id=9849.

Fixed ibase datetimestamp typo in PHP5. Thx stefan.

Removed whitespace at end of odbtp drivers.

Added db2 metaprimarykeys fix.

Optimizations to MoveNext() for mysql and oci8. Misc speedups to Get* functions.

4.50 6 July 2004

Bumped it to 4.50 to avoid confusion with PHP 4.3.x series.

Added db2 metatables and metacolumns extensions.

Added alpha PDO driver. Very buggy, only works with odbc.

Tested mysqli. Set poorAffectedRows = true. Cleaned up movenext() and _fetch().

PageExecute does not work properly with php5 (return val not a variable). Reported Dmytro Sychevsky sych#php.com.ua. Fixed.

MetaTables() for mysql, $showschema parameter was not backward compatible with older versions of adodb. Fixed.

Changed mysql GetOne() to work with mysql 3.23 when using with non-select stmts (e.g. SHOW TABLES).

Changed TRIG_ prefix to a variable in datadict-oci8.inc.php. Thx to Luca.Gioppo#csi.it.

New to adodb-time code. We allow you to define your own daylights savings function, adodb_daylight_sv for pre-1970 dates. If the function is defined (somewhere in an include), then you can correct for daylights savings. See http://phplens.com/phpeverywhere/node/view/16#daylightsavings for more info.

New sqlitepo driver. This is because assoc mode does not work like other drivers in sqlite. Namely, when selecting (joining) multiple tables, in assoc mode the table names are included in the assoc keys in the "sqlite" driver. In "sqlitepo" driver, the table names are stripped from the returned column names. When this results in a conflict, the first field get preference. Contributed by Herman Kuiper herman#ozuzo.net

Added $forcenull parameter to GetInsertSQL/GetUpdateSQL. Idea by Marco Aurelio Silva.

More XHTML changes for GetMenu. By Jeremy Evans.

Fixes some ibase date issues. Thx to stefan bogdan.

Improvements to mysqli driver to support $ADODB_COUNTRECS.

Fixed adodb-csvlib.inc.php problem when reading stream from socket. We need to poll stream continiously.

4.23 16 June 2004

New interbase/firebird fixes thx to Lester Caine. Driver fixes a problem with getting field names in the result array, and corrects a couple of data conversions. Also we default to dialect3 for firebird. Also ibase sysDate property was wrong. Changed to cast as timestamp.

The datadict driver is set up to give quoted tables and fields as this was the only way round reserved words being used as field names in TikiWiki. TikiPro is tidying that up, and I hope to be able to produce a build of THAT which uses what I consider proper UPPERCASE field and table names. The conversion of TikiWiki to ADOdb helped in that, but until the database is completely tidied up in TikiPro ...

Modified _gencachename() to include fetchmode in name hash. This means you should clear your cache directory after installing this release as the cache name algorithm has changed.

Now Cache* functions work in safe mode, because we do not create sub-directories in the $ADODB_CACHE_DIR in safe mode. In non-safe mode we still create sub-directories. Done by modifying _gencachename().

Added $gmt parameter (true/false) to UserDate and UserTimeStamp in connection class, to force conversion of input (in local time) to be converted to UTC/GMT.

Mssql datadict did not support INT types properly (no size param allowed). Added _GetSize() to datadict-mssql.inc.php.

For borland_ibase, BeginTrans(), changed:

   $this->_transactionID = $this->_connectionID;
to
   $this->_transactionID = ibase_trans($this->ibasetrans, $this->_connectionID);

Fixed typo in mysqi_field_seek(). Thx to Sh4dow (sh4dow#php.pl).

LogSQL did not work with Firebird/Interbase. Fixed.

Postgres: made errorno() handling more consistent. Thx to Michael Jahn, Michael.Jahn#mailbox.tu-dresden.de.

Added informix patch to better support metatables, metacolumns by "Cecilio Albero" c-albero#eos-i.com

Cyril Malevanov contributed patch to oci8 to support passing of LOB parameters:

   $text = 'test test test';
$sql = "declare rs clob; begin :rs := lobinout(:sa0); end;";
$stmt = $conn -> PrepareSP($sql);
$conn -> InParameter($stmt,$text,'sa0', -1, OCI_B_CLOB);
$rs = '';
$conn -> OutParameter($stmt,$rs,'rs', -1, OCI_B_CLOB);
$conn -> Execute($stmt);
echo "return = ".$rs."<br>";
As he says, the LOBs limitations are:
 - use OCINewDescriptor before binding
- if Param is IN, uses save() before each execute. This is done automatically for you.
- if Param is OUT, uses load() after each execute. This is done automatically for you.
- when we bind $var as LOB, we create new descriptor and return it as a
Bind Result, so if we want to use OUT parameters, we have to store
somewhere &$var to load() data from LOB to it.
- IN OUT params are not working now (should not be a big problem to fix it)
- now mass binding not working too (I've wrote about it before)

Simplified Connect() and PConnect() error handling.

When extension not loaded, Connect() and PConnect() will return null. On connect error, the fns will return false.

CacheGetArray() added to code.

Added Init() to adorecordset_empty().

Changed postgres64 driver, MetaColumns() to not strip off quotes in default value if :: detected (type-casting of default).

Added test: if (!defined('ADODB_DIR')) die(). Useful to prevent hackers from detecting file paths.

Changed metaTablesSQL to ignore Postgres 7.4 information schemas (sql_*).

New polish language file by Grzegorz Pacan

Added support for UNION in _adodb_getcount().

Added security check for ADODB_DIR to limit path disclosure issues. Requested by postnuke team.

Added better error message support to oracle driver. Thx to Gaetano Giunta.

Added showSchema support to mysql.

Bind in oci8 did not handle $name=false properly. Fixed.

If extension not loaded, Connect(), PConnect(), NConnect() will return null.

4.22 15 Apr 2004

Fixed session bug when quoting compressed/encrypted data in Replace().

Netezza Driver and LDAP drivers contributed by Josh Eldridge.

GetMenu now uses rtrim() on values instead of trim().

Changed MetaColumnNames to return an associative array, keys being the field names in uppercase.

Suggested fix to adodb-ado.inc.php affected_rows to support PHP5 variants. Thx to Alexios Fakos.

Contributed bulgarian language file by Valentin Sheiretsky valio#valio.eu.org.

Contributed romanian language file by stefan bogdan.

GetInsertSQL now checks for table name (string) in $rs, and will create a recordset for that table automatically. Contributed by Walt Boring. Also added OCI_B_BLOB in bind on Walt's request - hope it doesn't break anything :-)

Some minor postgres speedups in _initrs().

ChangeTableSQL checks now if MetaColumns returns empty. Thx Jason Judge.

Added ADOConnection::Time(), returns current database time in unix timestamp format, or false.

4.21 20 Mar 2004

We no longer in SelectLimit for VFP driver add SELECT TOP X unless an ORDER BY exists.

Pim Koeman contributed dutch language file adodb-nl.inc.php.

Rick Hickerson added CLOB support to db2 datadict.

Added odbtp driver. Thx to "stefan bogdan" sbogdan#rsb.ro.

Changed PrepareSP() 2nd parameter, $cursor, to default to true (formerly false). Fixes oci8 backward compat problems with OUT params.

Fixed month calculation error in adodb-time.inc.php. 2102-June-01 appeared as 2102-May-32.

Updated PHP5 RC1 iterator support. API changed, hasMore() renamed to valid().

Changed internal format of serialized cache recordsets. As we store a version number, this should be backward compatible.

Error handling when driver file not found was flawed in ADOLoadCode(). Fixed.

4.20 27 Feb 2004

Updated to AXMLS 1.01.

MetaForeignKeys for postgres7 modified by Edward Jaramilla, works on pg 7.4.

Now numbers accepts function calls or sequences for GetInsertSQL/GetUpdateSQL numeric fields.

Changed quotes of 'delete from $perf_table' to "". Thx Kehui (webmaster#kehui.net)

Added ServerInfo() for ifx, and putenv trim fix. Thx Fernando Ortiz.

Added addq(), which is analogous to addslashes().

Tested with php5b4. Fix some php5 compat problems with exceptions and sybase.

Carl-Christian Salvesen added patch to mssql _query to support binds greater than 4000 chars.

Mike suggested patch to PHP5 exception handler. $errno must be numeric.

Added double quotes (") to ADODB_TABLE_REGEX.

For oci8, Prepare(...,$cursor), $cursor's meaning was accidentally inverted in 4.11. This causes problems with ExecuteCursor() too, which calls Prepare() internally. Thx to William Lovaton.

Now dateHasTime property in connection object renamed to datetime for consistency. This could break bc.

Csongor Halmai reports that db2 SelectLimit with input array is not working. Fixed..

4.11 27 Jan 2004

Csongor Halmai reports db2 binding not working. Reverted back to emulated binding.

Dan Cech modifies datadict code. Adds support for DropIndex. Minor cleanups.

Table misspelt in perf-oci8.inc.php. Changed v$conn_cache_advice to v$db_cache_advice. Reported by Steve W.

UserTimeStamp and DBTimeStamp did not handle YYYYMMDDHHMMSS format properly. Reported by Mike Muir. Fixed.

Changed oci8 Prepare(). Does not auto-allocate OCINewCursor automatically, unless 2nd param is set to true. This will break backward compat, if Prepare/Execute is used instead of ExecuteCursor. Reported by Chris Jones.

Added InParameter() and OutParameter(). Wrapper functions to Parameter(), but nicer because they are self-documenting.

Added 'R' handling in ActualType() to datadict-mysql.inc.php

Added ADOConnection::SerializableRS($rs). Returns a recordset that can be serialized in a session.

Added "Run SQL" to performance UI().

Misc spelling corrections in adodb-mysqli.inc.php, adodb-oci8.inc.php and datadict-oci8.inc.php, from Heinz Hombergs.

MetaIndexes() for ibase contributed by Heinz Hombergs.

4.10 12 Jan 2004

Dan Cech contributed extensive changes to data dictionary to support name quoting (with `), and drop table/index.

Informix added cursorType property. Default remains IFX_SCROLL, but you can change to 0 (non-scrollable cursor) for performance.

Added ADODB_View_PrimaryKeys() for returning view primary keys to MetaPrimaryKeys().

Simplified chinese file, adodb-cn.inc.php from cysoft.

Added check for ctype_alnum in adodb-datadict.inc.php. Thx to Jason Judge.

Added connection parameter to ibase Prepare(). Fix by Daniel Hassan.

Added nameQuote for quoting identifiers and names to connection obj. Requested by Jason Judge. Also the data dictionary parser now detects `field name` and generates column names with spaces correctly.

BOOL type not recognised correctly as L. Fixed.

Fixed paths in ADODB_DIR for session files, and back-ported it to 4.05 (15 Dec 2003)

Added Schema to postgresql MetaTables. Thx to col#gear.hu

Empty postgresql recordsets that had blob fields did not set EOF properly. Fixed.

CacheSelectLimit internal parameters to SelectLimit were wrong. Thx to Nio.

Modified adodb_pr() and adodb_backtrace() to support command-line usage (eg. no html).

Fixed some fr and it lang errors. Thx to Gaetano G.

Added contrib directory, with adodb rs to xmlrpc convertor by Gaetano G.

Fixed array recordset bugs when _skiprow1 is true. Thx to Gaetano G.

Fixed pivot table code when count is false.

4.05 13 Dec 2003

Added MetaIndexes - thx to Dan Cech.

Rewritten session code by Ross Smith. Moved code to adodb/session directory.

Added function exists check on connecting to most drivers, so we don't crash with the unknown function error.

Smart Transactions failed with GenID() when it no seq table has been created because the sql statement fails. Fix by Mark Newnham.

Added $db->length, which holds name of function that returns strlen.

Fixed error handling for bad driver in ADONewConnection - passed too few params to error-handler.

Datadict did not handle types like 16.0 properly in _GetSize. Fixed.

Oci8 driver SelectLimit() bug &= instead of =& used. Thx to Swen Thümmler.

Jesse Mullan suggested not flushing outp when output buffering enabled. Due to Apache 2.0 bug. Added.

MetaTables/MetaColumns return ref bug with PHP5 fixed in adodb-datadict.inc.php.

New mysqli driver contributed by Arjen de Rijke. Based on adodb 3.40 driver. Then jlim added BeginTrans, CommitTrans, RollbackTrans, IfNull, SQLDate. Also fixed return ref bug.

$ADODB_FLUSH added, if true then force flush in debugging outp. Default is false. In earlier versions, outp defaulted to flush, which is not compat with apache 2.0.

Mysql driver's GenID() function did not work when when sql logging is on. Fixed.

$ADODB_SESSION_TBL not declared as global var. Not available if adodb-session.inc.php included in function. Fixed.

The input array not passed to Execute() in _adodb_getcount(). Fixed.

4.04 13 Nov 2003

Switched back to foreach - faster than list-each.

Fixed bug in ado driver - wiping out $this->fields with date fields.

Performance Monitor, View SQL, Explain Plan did not work if strlen($SQL)>max($_GET length). Fixed.

Performance monitor, oci8 driver added memory sort ratio.

Added random property, returns SQL to generate a floating point number between 0 and 1;

4.03 6 Nov 2003

The path to adodb-php4.inc.php and adodb-iterators.inc.php was not setup properly.

Patched SQLDate in interbase to support hours/mins/secs. Thx to ari kuorikoski.

Force autorollback for pgsql persistent connections - apparently pgsql did not autorollback properly before 4.3.4. See http://bugs.php.net/bug.php?id=25404

4.02 5 Nov 2003

Some errors in adodb_error_pg() fixed. Thx to Styve.

Spurious Insert_ID() error was generated by LogSQL(). Fixed.

Insert_ID was interfering with Affected_Rows() and Replace() when LogSQL() enabled. Fixed.

More foreach loops optimized with list/each.

Null dates not handled properly in ADO driver (it becomes 31 Dec 1969!).

Heinz Hombergs contributed patches for mysql MetaColumns - adding scale, made interbase MetaColumns work with firebird/interbase, and added lang/adodb-de.inc.php.

Added INFORMIXSERVER environment variable.

Added $ADODB_ANSI_PADDING_OFF for interbase/firebird.

PHP 5 beta 2 compat check. Foreach (Iterator) support. Exceptions support.

4.01 23 Oct 2003

Fixed bug in rs2html(), tohtml.inc.php, that generated blank table cells.

Fixed insert_id() incorrectly generated when logsql() enabled.

Modified PostgreSQL _fixblobs to use list/each instead of foreach.

Informix ErrorNo() implemented correctly.

Modified several places to use list/each, including GetRowAssoc().

Added UserTimeStamp() to connection class.

Added $ADODB_ANSI_PADDING_OFF for oci8po.

4.00 20 Oct 2003

Upgraded adodb-xmlschema to 1 Oct 2003 snapshot.

Fix to rs2html warning message. Thx to Filo.

Fix for odbc_mssql/mssql SQLDate(), hours was wrong.

Added MetaColumns and MetaPrimaryKeys for sybase. Thx to Chris Phillipson.

Added autoquoting to datadict for MySQL and PostgreSQL. Suggestion by Karsten Dambekalns

3.94 11 Oct 2003

Create trigger in datadict-oci8.inc.php did not work, because all cr/lf's must be removed.

ErrorMsg()/ErrorNo() did not work for many databases when logging enabled. Fixed.

Removed global variable $ADODB_LOGSQL as it does not work properly with multiple connections.

Added SQLDate support for sybase. Thx to Chris Phillipson

Postgresql checking of pgsql resultset resource was incorrect. Fix by Bharat Mediratta bharat#menalto.com. Same patch applied to _insertid and _affectedrows for adodb-postgres64.inc.php.

Added support for NConnect for postgresql.

Added Sybase data dict support. Thx to Chris Phillipson

Extensive improvements in $perf->UI(), eg. Explain now opens in new window, we show scripts which call sql, etc.

Perf Monitor UI works with magic quotes enabled.

rsPrefix was declared twice. Removed.

Oci8 stored procedure support, eg. "begin func(); end;" was incorrect in _query. Fixed.

Tiraboschi Massimiliano contributed italian language file.

Fernando Ortiz, fortiz#lacorona.com.mx, contributed informix performance monitor.

Added _varchar (varchar arrays) support for postgresql. Reported by PREVOT Stéphane.

3.92 22 Sept 2003

Added GetAssoc and CacheGetAssoc to connection object.

Removed TextMax and CharMax functions from adodb.inc.php.

HasFailedTrans() returned false when trans failed. Fixed.

Moved perf driver classes into adodb/perf/*.php.

Misc improvements to performance monitoring, including UI().

RETVAL in mssql Parameter(), we do not append @ now.

Added Param($name) to connection class, returns '?' or ":$name", for defining bind parameters portably.

LogSQL traps affected_rows() and saves its value properly now. Also fixed oci8 _stmt and _affectedrows() bugs.

Session code timestamp check for oci8 works now. Formerly default NLS_DATE_FORMAT stripped off time portion. Thx to Tony Blair (tonanbarbarian#hotmail.com). Also added new $conn->datetime field to oci8, controls whether MetaType() returns 'D' ($this->datetime==false) or 'T' ($this->datetime == true) for DATE type.

Fixed bugs in adodb-cryptsession.inc.php and adodb-session-clob.inc.php.

Fixed misc bugs in adodb_key_exists, GetInsertSQL() and GetUpdateSQL().

Tuned include_once handling to reduce file-system checking overhead.

3.91 9 Sept 2003

Only released to InterAkt

Added LogSQL() for sql logging and $ADODB_NEWCONNECTION to override factory for driver instantiation.

Added IfNull($field,$ifNull) function, thx to johnwilk#juno.com

Added portable substr support.

Now rs2html() has new parameter, $echo. Set to false to return $html instead of echoing it.

3.90 5 Sept 2003

First beta of performance monitoring released.

MySQL supports MetaTable() masking.

Fixed key_exists() bug in adodb-lib.inc.php

Added sp_executesql Prepare() support to mssql.

Added bind support to db2.

Added swedish language file - Christian Tiberg" christian#commsoft.nu

Bug in drop index for mssql data dict fixed. Thx to Gert-Rainer Bitterlich.

Left join setting for oci8 was wrong. Thx to johnwilk#juno.com

3.80 27 Aug 2003

Patch for PHP 4.3.3 cached recordset csv2rs() fread loop incompatibility.

Added matching mask for MetaTables. Only for oci8, mssql and postgres currently.

Rewrite of "oracle" driver connection code, merging with "oci8", by Gaetano.

Added better debugging for Smart Transactions.

Postgres DBTimeStamp() was wrongly using TO_DATE. Changed to TO_TIMESTAMP.

ADODB_FETCH_CASE check pushed to ADONewConnection to allow people to define it after including adodb.inc.php.

Added portugese (brazilian) to languages. Thx to "Levi Fukumori".

Removed arg3 parameter from Execute/SelectLimit/Cache* functions.

Execute() now accepts 2-d array as $inputarray. Also changed docs of fnExecute() to note change in sql query counting with 2-d arrays.

Added MONEY to MetaType in PostgreSQL.

Added more debugging output to CacheFlush().

3.72 9 Aug 2003

Added qmagic($str), which is a qstr($str) that auto-checks for magic quotes and does the right thing...

Fixed CacheFlush() bug - Thx to martin#gmx.de

Walt Boring contributed MetaForeignKeys for postgres7.

_fetch() called _BlobDecode() wrongly in interbase. Fixed.

adodb_time bug fixed with dates after 2038 fixed by Jason Pell. http://phplens.com/lens/lensforum/msgs.php?id=6980

3.71 4 Aug 2003

The oci8 driver, MetaPrimaryKeys() did not check the owner correctly when $owner == false.

Russian language file contributed by "Cyrill Malevanov" cyrill#malevanov.spb.ru.

Spanish language file contributed by "Horacio Degiorgi" horaciod#codigophp.com.

Error handling in oci8 bugfix - if there was an error in Execute(), then when calling ErrorNo() and/or ErrorMsg(), the 1st call would return the error, but the 2nd call would return no error.

Error handling in odbc bugfix. ODBC would always return the last error, even if it happened 5 queries ago. Now we reset the errormsg to '' and errorno to 0 everytime before CacheExecute() and Execute().

3.70 29 July 2003

Added new SQLite driver. Tested on PHP 4.3 and PHP 5.

Added limited "sapdb" driver support - mainly date support.

The oci8 driver did not identify NUMBER with no defined precision correctly.

Added ADODB_FORCE_NULLS, if set, then PHP nulls are converted to SQL nulls in GetInsertSQL/GetUpdateSQL.

DBDate() and DBTimeStamp() format for postgresql had problems. Fixed.

Added tableoptions to ChangeTableSQL(). Thx to Mike Benoit.

Added charset support to postgresql. Thx to Julian Tarkhanov.

Changed OS check for MS-Windows to prevent confusion with darWIN (MacOS)

Timestamp format for db2 was wrong. Changed to yyyy-mm-dd-hh.mm.ss.nnnnnn.

adodb-cryptsession.php includes wrong. Fixed.

Added MetaForeignKeys(). Supported by mssql, odbc_mssql and oci8.

Fixed some oci8 MetaColumns/MetaPrimaryKeys bugs. Thx to Walt Boring.

adodb_getcount() did not init qryRecs to 0. Missing "WHERE" clause checking in GetUpdateSQL fixed. Thx to Sebastiaan van Stijn.

Added support for unicamente 'VIEWS' and "TABLES" in MetaTables. From Walt Boring.

Upgraded to adodb-xmlschema.inc.php 0.0.2.

NConnect for mysql now returns value. Thx to Dennis Verspuij.

ADODB_FETCH_BOTH support added to interbase/firebird.

Czech language file contributed by Kamil Jakubovic jake#host.sk.

PostgreSQL BlobDecode did not use _connectionID properly. Thx to Juraj Chlebec.

Added some new initialization stuff for Informix. Thx to "Andrea Pinnisi" pinnisi#sysnet.it

ADODB_ASSOC_CASE constant wrong in sybase _fetch(). Fixed.

3.60 16 June 2003

We now SET CONCAT_NULL_YIELDS_NULL OFF for odbc_mssql driver to be compat with mssql driver.

The property $emptyDate missing from connection class. Also changed 1903 to constant (TIMESTAMP_FIRST_YEAR=100). Thx to Sebastiaan van Stijn.

ADOdb speedup optimization - we now return all arrays by reference.

Now DBDate() and DBTimeStamp() now accepts the string 'null' as a parameter. Suggested by vincent.

Added GetArray() to connection class.

Added not_null check in informix metacolumns().

Connection parameters for postgresql did not work correctly when port was defined.

DB2 is now a tested driver, making adodb 100% compatible. Extensive changes to odbc driver for DB2, including implementing serverinfo() and SQLDate(), switching to SQL_CUR_USE_ODBC as the cursor mode, and lastAffectedRows and SelectLimit() fixes.

The odbc driver's FetchField() field names did not obey ADODB_ASSOC_CASE. Fixed.

Some bugs in adodb_backtrace() fixed.

Added "INT IDENTITY" type to adorecordset::MetaType() to support odbc_mssql properly.

MetaColumns() for oci8, mssql, odbc revised to support scale. Also minor revisions to odbc MetaColumns() for vfp and db2 compat.

Added unsigned support to mysql datadict class. Thx to iamsure.

Infinite loop in mssql MoveNext() fixed when ADODB_FETCH_ASSOC used. Thx to Josh R, Night_Wulfe#hotmail.com.

ChangeTableSQL contributed by Florian Buzin.

The odbc_mssql driver now sets CONCAT_NULL_YIELDS_NULL OFF for compat with mssql driver.


0.10 Sept 9 2000 First release

Old changelog history moved to old-changelog.htm.