MySQL: Hagámoslo entre todos
Posted: Mon Dec 06, 2010 1:49 pm
Propongo al grupo la creación, en código abierto, de las librerías necesarias para trabajar con MySql, para lo cual comienzo agregando el siguiente código, probado con FWH1008+xHb1.21+BCC55 en Windows XP SP3.
Para compilar este código haga lo siguiente:
1) Descargue de http://www.mysql.com/downloads/connector/c/ el siguiente paquete:
Windows (x86, 32-bit), ZIP Archive (mysql-connector-c-noinstall-6.0.2-win32-vs2005.zip)
2) Descomprímalo y arrastre la carpeta include y la lib dinámica libmysql.dll a su carpeta de trabajo
3) Cree la lib estática libmysql.lib mediante: <<implib libmysql.lib libmysql.dll>> (implib está en BCCxx/bin)
4) Enlace libmysql.lib a su ejecutable y mantenga libmysql.dll en la carpeta del ejecutable.
Creo que las funciones se explican por sí solas. La secuencia es:
mysql_init() // initializes a MYSQL object suitable for mysql_real_connect()
mysql_real_connect(cHost,cUser,cPassword,[nPort],[unix_socket],[client_flag])
//attempts to establish a connection to a MySQL database engine
mysql_query([USE testdb]) // selecciona la base de datos
:
mysql_query(.....) //cualquier query válido
:
aRes:=mysql_fetch_array(cQuery,[lColsInfo]) //Matriz con resultados del query o 0 si hay error.
:
mysql_close() //Closes a previously opened connection
La función mysql_fetch_array(cQuery,[lColsInfo]) devuelve 0 si hay error en cQuery o una matriz con los datos obtenidos. Si lColsInfo es .T. (por defecto es .F.) la primera fila de la matriz devuelta contiene información de los campos en la primera fila (vea mysqldll.ch para detalles). Agregué esta característica por mi gusto personal a cómo php devuelve un array de hashes tras un query.
Para más información de las funciones en libmysql.dll, consulte
http://dev.mysql.com/doc/refman/5.0/es/ ... tions.html
Código de libmysql.ch
Para compilar este código haga lo siguiente:
1) Descargue de http://www.mysql.com/downloads/connector/c/ el siguiente paquete:
Windows (x86, 32-bit), ZIP Archive (mysql-connector-c-noinstall-6.0.2-win32-vs2005.zip)
2) Descomprímalo y arrastre la carpeta include y la lib dinámica libmysql.dll a su carpeta de trabajo
3) Cree la lib estática libmysql.lib mediante: <<implib libmysql.lib libmysql.dll>> (implib está en BCCxx/bin)
4) Enlace libmysql.lib a su ejecutable y mantenga libmysql.dll en la carpeta del ejecutable.
Creo que las funciones se explican por sí solas. La secuencia es:
mysql_init() // initializes a MYSQL object suitable for mysql_real_connect()
mysql_real_connect(cHost,cUser,cPassword,[nPort],[unix_socket],[client_flag])
//attempts to establish a connection to a MySQL database engine
mysql_query([USE testdb]) // selecciona la base de datos
:
mysql_query(.....) //cualquier query válido
:
aRes:=mysql_fetch_array(cQuery,[lColsInfo]) //Matriz con resultados del query o 0 si hay error.
:
mysql_close() //Closes a previously opened connection
La función mysql_fetch_array(cQuery,[lColsInfo]) devuelve 0 si hay error en cQuery o una matriz con los datos obtenidos. Si lColsInfo es .T. (por defecto es .F.) la primera fila de la matriz devuelta contiene información de los campos en la primera fila (vea mysqldll.ch para detalles). Agregué esta característica por mi gusto personal a cómo php devuelve un array de hashes tras un query.
Para más información de las funciones en libmysql.dll, consulte
http://dev.mysql.com/doc/refman/5.0/es/ ... tions.html
Code: Select all | Expand
#include "Fivewin.ch"
#include "mysqldll.ch"
//===============================================
Function Test()
Local cHost:="localhost", cUser:="root", cPass:="mypass", nPort:=0, cUnixSocket:="", nClientFlag:=0
Local res
MsgInfo(mysql_get_client_info(),"Client info");
IF mysql_init()=0
MsgAlert(mysql_error(),"Error en mysql_init()")
ELSEIF mysql_real_connect(cHost,cUser,cPass,nPort)=0
MsgAlert(mysql_error(),"Error en mysql_real_connect()")
ELSEIF mysql_query([CREATE DATABASE IF NOT EXISTS testdb ])<>0
MsgAlert(mysql_error(),"Error en CREATE DATABASE")
ELSEIF mysql_query([USE testdb])<>0
MsgAlert(mysql_error(),"Error en USE testdb")
ELSEIF mysql_query([DROP TABLE IF EXISTS clients])<>0
MsgAlert(mysql_error(),"Error en DROP TABLE")
ELSEIF mysql_query([CREATE TABLE clients ]+;
[(id double(6,0) NOT NULL auto_increment PRIMARY KEY,]+;
[last_name char(20),]+;
[first_name char(20), ]+;
[updated date default NULL) ]+;
[ ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci])<>0
MsgAlert(mysql_error(),"Error en CREATE TABLE")
ELSEIF mysql_query([INSERT INTO clients ]+;
[(last_name,first_name,updated) VALUES ]+;
[('Smith','John','2010-12-01'),]+;
[('Linares','Antonio','2009-12-01'),]+;
[('Lozada','Cosar','2008-12-01'),]+;
[("D\'Santiago",'Josefina','2007-12-01')])<>0
MsgAlert(mysql_error(), "Error en INSERT")
ELSEIF mysql_query([UPDATE clients SET first_name='César' WHERE id=3])<>0
MsgAlert(mysql_error(),"Error en UPDATE")
ELSEIF ValType(res:=mysql_fetch_array([SELECT * FROM clients]))<>"A"
MsgAlert(mysql_error(),"Error en SELECT")
ELSE
? MsgInfo(atoc(res),"Query results")
ENDIF
mysql_close()
return nil
//===============================================
***************************************************************************
* Algunas funciones para el manejo de libmysql.dll
* © César E. Lozada - Dic 1, 2010
* Venezuela
***************************************************************************
#pragma BEGINDUMP
#include "windows.h"
#include "hbapi.h"
#include "hbapiitm.h"
#include "./include/mysql.h"
#define MAX_FIELDS 512
static MYSQL *conn;
/*------------------------------*/
HB_FUNC (MYSQL_INIT)
{
conn = mysql_init(NULL);
hb_retnl( (LONG) conn );
};
/*------------------------------*/
HB_FUNC (MYSQL_CLOSE)
{
if (conn)
{
mysql_close( conn );
conn=0;
};
}
/*------------------------------*/
HB_FUNC (MYSQL_REAL_CONNECT) //(cHost,cUser,cPassword,[nPort],[unix_socket],[client_flag])
{
char *host=hb_parc(1);
char *user=hb_parc(2);
char *passwd=hb_parc(3);
unsigned int port=hb_parni(4);
char *unix_socket=hb_parc(5);
unsigned long client_flag=hb_parnl(6);
hb_retnl( (LONG) mysql_real_connect(conn, host, user, passwd, NULL, port, unix_socket, client_flag) );
}
/*------------------------------*/
HB_FUNC (MYSQL_QUERY) // (cQuery)
{
hb_retni( mysql_query( conn, hb_parc(1) ) );
}
/*------------------------------*/
HB_FUNC (MYSQL_FETCH_ARRAY) // (cQuery,lColsInfo)
{
MYSQL_RES *result;
MYSQL_ROW row;
MYSQL_FIELD *field;
int num_rows, num_fields;
int i,j;
int field_type[MAX_FIELDS], field_flags[MAX_FIELDS],field_decimals[MAX_FIELDS];
char *field_name[MAX_FIELDS];
int bheader = hb_parni(2);
PHB_ITEM pArray, pArrayItm, pArrayItm2;
char *pEnd;
if ( (LONG) mysql_query(conn, hb_parc(1) ) !=0 ) hb_retnl(0);
else
{
result = mysql_store_result(conn);
num_rows=result->row_count;
num_fields = mysql_num_fields(result);
pArray = hb_itemArrayNew( num_rows + (bheader ? 1 : 0) );
if (bheader) {
pArrayItm = hb_arrayGetItemPtr( pArray, 1 );
hb_arrayNew( pArrayItm, num_fields );
};
j=0;
while( field = mysql_fetch_field(result) )
{
field_type[j]=field->type;
field_name[j]=field->name;
field_flags[j]=field->flags;
field_decimals[j]=field->decimals;
if (bheader) {
pArrayItm2 = hb_arrayGetItemPtr( pArrayItm, j+1 );
hb_arrayNew( pArrayItm2, 6 );
hb_arraySetC( pArrayItm2, 1, field->name);
hb_arraySetNI( pArrayItm2, 2, field->type);
hb_arraySetNL( pArrayItm2, 3, (LONG) field->length);
hb_arraySetNI( pArrayItm2, 4, (INT) field->decimals);
hb_arraySetNI( pArrayItm2, 5, (INT) field->flags);
hb_arraySetC( pArrayItm2, 6, field->org_name);
};
j++;
};
i=(bheader ? 1 : 0);
while ( (row = mysql_fetch_row(result)) )
{
i++;
pArrayItm = hb_arrayGetItemPtr( pArray, i );
hb_arrayNew( pArrayItm, num_fields );
for (j=0; j<num_fields; j++)
{
if (! row[j]) hb_arraySetC( pArrayItm, j+1 , "NULL" );
else
{
switch ( field_type[j] )
{
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_YEAR:
if (field_decimals[j]==0) hb_arraySetNL( pArrayItm, j+1, strtol(row[j],&pEnd,10) );
else hb_arraySetND( pArrayItm, j+1, strtod(row[j],&pEnd) );
break;
case MYSQL_TYPE_FLOAT:
hb_arraySetND( pArrayItm, j+1, strtod(row[j],&pEnd) );
break;
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_INT24:
hb_arraySetNLL( pArrayItm, j+1, (INT64) strtod(row[j],&pEnd) );
break;
case MYSQL_TYPE_BIT:
hb_arraySetC( pArrayItm, j+1, row[j]);
break;
/*------------------------------------------------------
Los siguientes tipos no son evaluados aquí porque
sus field_type[j] son iguales a MYSQL_TYPE_STRING
------------------------------------------------------*/
case MYSQL_TYPE_NEWDECIMAL:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
hb_arraySetNI( pArrayItm, j+1, strtol(row[j],&pEnd,10) );
break;
/*------------------------------------------------------
Las fechas están en formato yyyy-mm-dd y son tipo C
------------------------------------------------------*/
case MYSQL_TYPE_DATE: //No encontré cómo usar los '-' de un string
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_TIMESTAMP:
hb_arraySetC( pArrayItm, j+1, row[j] );
break;
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_GEOMETRY: // No estoy seguro...
hb_arraySetC( pArrayItm, j+1, row[j] );
break;
default:
hb_arraySetC( pArrayItm, j+1 ,"NULL" );
break;
};
};
};
};
mysql_free_result(result);
hb_itemReturnRelease( pArray );
};
}
HB_FUNC (MYSQL_ERROR)
{
hb_retc( mysql_error(conn) );
}
/*------------------------------*/
HB_FUNC (MYSQL_GET_CLIENT_INFO)
{
hb_retc(mysql_get_client_info());
}
/*------------------------------*/
#pragma ENDDUMP
Código de libmysql.ch
Code: Select all | Expand
/*------------------------------------------------------------
Información devuelta en primera fila de mysql_fetch_array()
Info returned in first row from mysql_fetch_array()
------------------------------------------------------------*/
#define MYSQL_FIELD_NAME 1 //Nombre (Name)
#define MYSQL_FIELD_TYPE 2 //Tipo (Type)
#define MYSQL_FIELD_LEN 3 //Longitud (Length)
#define MYSQL_FIELD_DECS 4 //Decimales (Decimals)
#define MYSQL_FIELD_FLAGS 5 //Flags
#define MYSQL_FIELD_ORG_NAME 6 //Nombre original(si usa alias)
//Original name(if alias used)
/*------------------------------------------------------------
Tipos de campo / Field types
------------------------------------------------------------*/
#define MYSQL_TYPE_DECIMAL 0
#define MYSQL_TYPE_TINY 1
#define MYSQL_TYPE_SHORT 2
#define MYSQL_TYPE_LONG 3
#define MYSQL_TYPE_FLOAT 4
#define MYSQL_TYPE_DOUBLE 5
#define MYSQL_TYPE_NULL 6
#define MYSQL_TYPE_TIMESTAMP 7
#define MYSQL_TYPE_LONGLONG 8
#define MYSQL_TYPE_INT24 9
#define MYSQL_TYPE_DATE 10
#define MYSQL_TYPE_TIME 11
#define MYSQL_TYPE_DATETIME 12
#define MYSQL_TYPE_YEAR 13
#define MYSQL_TYPE_NEWDATE 14
#define MYSQL_TYPE_VARCHAR 15
#define MYSQL_TYPE_BIT 16
#define MYSQL_TYPE_NEWDECIMAL 246
#define MYSQL_TYPE_ENUM 247
#define MYSQL_TYPE_SET 248
#define MYSQL_TYPE_TINY_BLOB 249
#define MYSQL_TYPE_MEDIUM_BLOB 250
#define MYSQL_TYPE_LONG_BLOB 251
#define MYSQL_TYPE_BLOB 252
#define MYSQL_TYPE_VAR_STRING 253
#define MYSQL_TYPE_STRING 254
#define MYSQL_TYPE_GEOMETRY 255
/*------------------------------------------------------------
Flags
------------------------------------------------------------*/
#define NOT_NULL_FLAG 1 /* Field can't be NULL */
#define PRI_KEY_FLAG 2 /* Field is part of a primary key */
#define UNIQUE_KEY_FLAG 4 /* Field is part of a unique key */
#define MULTIPLE_KEY_FLAG 8 /* Field is part of a key */
#define BLOB_FLAG 16 /* Field is a blob */
#define UNSIGNED_FLAG 32 /* Field is unsigned */
#define ZEROFILL_FLAG 64 /* Field is zerofill */
#define BINARY_FLAG 128 /* Field is binary */
/* The following are only sent to new clients */
#define ENUM_FLAG 256 /* field is an enum */
#define AUTO_INCREMENT_FLAG 512 /* field is a autoincrement field */
#define TIMESTAMP_FLAG 1024 /* Field is a timestamp */
#define SET_FLAG 2048 /* field is a set */
#define NO_DEFAULT_VALUE_FLAG 4096 /* Field doesn't have default value */
#define ON_UPDATE_NOW_FLAG 8192 /* Field is set to NOW on UPDATE */
#define NUM_FLAG 32768 /* Field is num (for clients) */
#define PART_KEY_FLAG 16384 /* Intern; Part of some key */
#define GROUP_FLAG 32768 /* Intern: Group field */
#define UNIQUE_FLAG 65536 /* Intern: Used by sql_yacc */
#define BINCMP_FLAG 131072 /* Intern: Used by sql_yacc */
#define GET_FIXED_FIELDS_FLAG (1 << 18) /* Used to get fields in item tree */
#define FIELD_IN_PART_FUNC_FLAG (1 << 19) /* Field part of partition func */
#define FIELD_IN_ADD_INDEX (1<< 20) /* Intern: Field used in ADD INDEX */
#define FIELD_IS_RENAMED (1<< 21) /* Intern: Field is being renamed */
#define FIELD_STORAGE_FLAGS 22 /* Storage type: bit 22, 23 and 24 */
#define COLUMN_FORMAT_FLAGS 25 /* Column format: bit 25, 26 and 27 */
/*------------------------------------------------------------
Por hacer: Códigos y descripción de errores
(Ver include\errmsg.h, include\mysqld_error.h)
To Do: Errors codes and descriptions
escape and unescape
------------------------------------------------------------*/