Page 1 of 1

MySQL: Hagámoslo entre todos

Posted: Mon Dec 06, 2010 1:49 pm
by César E. Lozada
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

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

 
Código de libmysql.ch

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
------------------------------------------------------------*/


 

Re: MySQL: Hagámoslo entre todos

Posted: Mon Dec 06, 2010 1:56 pm
by César E. Lozada
Mil disculpas. Olvidé una función usada en el código. También quitar el ? delante del último MsgInfo(). Gracias.

Code: Select all

 
Function atoc(a)
  Local c:="", i, j
  IF ValType(a)="A"
    for i:=1 to Len(a)
      c+=if(!Empty(c),",","")
      DO CASE
        CASE ValType(a[i])="C"
          if !["]$a[i]
            c+=["]+a[i]+["] 
          elseif ![']$a[i]
            c+=[']+a[i]+[']
          elseif !"["$a[i] .and. !"]"$a[i]
            c+="["+a[i]+"]"
          else
            for j:=1 to Len(a[i])
              c+=if(j>1,"+","")+"CHR("+Str(Asc(a[i][j]),,,.T.)+")"
            next
          endif
        CASE ValType(a[i])="L"; c+=if(a[i],".T.",".F.")
        CASE ValType(a[i])="N"; c+=Str(a[i],,,.T.)
        CASE ValType(a[i])="D"; c+=[stod("]+dtos(a[i])+[")]
        CASE ValType(a[i])="U"; c+="nil"
        CASE ValType(a[i])="B"; c+="{|| .T.}"
        CASE ValType(a[i])="A"; c+=atoc(a[i])
        CASE ValType(a[i])="O"; c+=a[i]:ClassName()+"()"
        OTHERWISE; c+=["Unknown type in atoc()"]   
      ENDCASE
    next
  ENDIF
return "{"+c+"}"

Re: MySQL: Hagámoslo entre todos

Posted: Mon Dec 06, 2010 2:09 pm
by Daniel Garcia-Gil
Cesar

puedes ahorrarte monton de trabajo visita http://tdolphin.blogspot.com/ sitio elaborado por mi, donde encontraras todo funcionando y el codigo totalmente abierto...
disponible para usarse tanto en 32 como 64 bit, y distintos compiladores de C, como borland, microsoft y mingw

aparte dispones de una version SVN para web http://www.sitasoft.net/dolphindevel, alli podras revisar todos _ entre versiones

TODO EL CODIGO ESTA DISPONIBLE Y GRATIS

tambien esta soportado nativamente en fivewin para ser usado con xbrowse

Re: MySQL: Hagámoslo entre todos

Posted: Mon Dec 06, 2010 6:18 pm
by Lautaro
Cesar,

En harbour->contrib->hbmysql tambien esta casi todo hecho y como dice Daniel, tdolphin va un paso mas alla de lo que harbour tiene.


Saludos,

Lautaro Moreira

Posted: Thu Jun 25, 2015 7:47 pm
by jesusdelamora
QUE TAL DANIEL

DOLPHIN FUNCINA CON MYSQL EMBEBIDO ?

SALUDOS

Re: MySQL: Hagámoslo entre todos

Posted: Fri Jun 26, 2015 12:50 am
by cmsoft
Si, funciona!!! (No soy Daniel, pero lo he probado y va barbaro!)

Re: MySQL: Hagámoslo entre todos

Posted: Sat Jun 27, 2015 12:45 am
by joseluisysturiz
cmsoft wrote:Si, funciona!!! (No soy Daniel, pero lo he probado y va barbaro!)
CMSOFT, tendras un sample de como usar la TDolphin con el mysql embebido.? o si puedes me lo mandas a mi privado, gracias, saludos... :shock:

Re: MySQL: Hagámoslo entre todos

Posted: Sat Jun 27, 2015 3:29 pm
by cmsoft

Code: Select all

#include "tdolphin.ch"
#include "fivewin.ch"

FUNCTION Conectar()
LOCAL oServer, cSql
   D_SetCaseSensitive( .T. )
   D_LogicalValue( .T. )
   Set_MyLang( "es_ES")
   
   IF ( oServer := ConnectTo() ) == NIL
      MsgStop("El programa no ha podido establecer la conexion",;
              "Error de conexion")
      QUIT
      ELSE            
      IF !oServer:TableExist( "categorias" ) // Aca verifico que las tablas existan en la carpeta, sino las creo
         MsgWait("Creando tablas.... Espere",,1)         
         oServer:Execute("CREATE TABLE `categorias` ("+;
                  "`id` int(6) NOT NULL,"+;
                  "`nombre` varchar(255) DEFAULT NULL,"+;
                  "PRIMARY KEY (`id`)"+;
                  ") ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8")
         oServer:NextResult()
         // Aca creas todas tus tablas
          oServer:ExecuteScript("protocolo1.sql") //En protocolo1.sql tengo un script con los datos iniciales
         MsgInfo("Tablas creadas!")
      ENDIF   
   ENDIF
   
RETURN oServer


FUNCTION ConnectTo( n )
LOCAL oServer, oErr
   TRY   
   CONNECT EMBEDDED oServer ;
          DATABASE "Sobres" ; //Dentro de la carpeta de la aplicacion hay una carpeta  dbdir\sobres
          OPTIONS "Dolphin_server_embedded",;
                  "--datadir=./dbdir/",;
                  "--language=./sysdir/spanish/",;&&"--skip-innodb",;
                  "--key-buffer-size=64MB",;
                  "--console";
          GROUPS "Dolphin_server_embedded", 
   CATCH oErr 
     RETURN NIL
   END
RETURN oServer
 
Hay que copiar las carpetas que estan en samples de tdolphin, sysdir y dbdir, se debe enlazar la aplicacion con la lib libmysqld.lib, y tener la dll libmysqld.dll en la carpeta donde corre el ejecutable.
Despues, lo trabajas como si no fuera embebido...
Espero te sirva

Re: MySQL: Hagámoslo entre todos

Posted: Sun Jun 28, 2015 1:53 pm
by jesusdelamora
QUE TAL CESAR LOZADA

EL CODIGO DE mysqldll.ch DE DONDE LO OBTIENES ?

SALUDOS

Re: MySQL: Hagámoslo entre todos

Posted: Sun Jun 28, 2015 2:22 pm
by jesusdelamora
QUE TAL CESAR LOZADA

EXCELENTE TU INFORMACION

PARA MYSQL EMBEBIDO TIENES UN EJEMPLO

SALUDOS

Re: MySQL: Hagámoslo entre todos

Posted: Sun Jun 28, 2015 2:50 pm
by cmsoft
Uso la libreria Tdolphin de Daniel. http://tdolphin.blogspot.com.ar/
El ejemplo que puse es para MySql embebido!

Re: MySQL: Hagámoslo entre todos

Posted: Sun Jun 28, 2015 4:21 pm
by jesusdelamora
que tal

tienes los wrapper function para libmysqld.lib y un ejemplo sin dolphin
similar a lo que coloco CESAR LOZADA

Saludos

Re: MySQL: Hagámoslo entre todos

Posted: Sun Jun 28, 2015 7:52 pm
by FranciscoA
jesusdelamora wrote:que tal

tienes los wrapper function para libmysqld.lib y un ejemplo sin dolphin

Saludos
http://fivetechsupport.com/forums/viewt ... 76#p178607

Creo que Cesar Lozada merece una disculpa de nuestra parte, por haber violentado el objetivo original de su post.

Saludos.

Re: MySQL: Hagámoslo entre todos

Posted: Wed Jul 01, 2015 2:12 pm
by jesusdelamora
cmsoft wrote:Uso la libreria Tdolphin de Daniel. http://tdolphin.blogspot.com.ar/
El ejemplo que puse es para MySql embebido!

Tienes razon esta barbaro !!!!!!

Re: MySQL: Hagámoslo entre todos

Posted: Wed Jul 01, 2015 4:09 pm
by Daniel Garcia-Gil
Jesus

me has enviado dos email que te he respondido, asumo que no los has leidos por el segundo email, si no te han llegado me avisas