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 _ 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 _ 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
#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
Code: Select all
/*------------------------------------------------------------
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
------------------------------------------------------------*/