Mysql (Result a Array en C) solicitud de ayuda.

Post Reply
User avatar
carlos vargas
Posts: 1421
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Mysql (Result a Array en C) solicitud de ayuda.

Post by carlos vargas »

Estimados necesito de su gran ayuda. :-)

Siguiendo con mi intento de mejorar TmySQL, he notado que al pasar a array una consulta, todos los datos vienen como cadena de caracteres, por lo que he intentado modificar este comportamiento.
mi idea es que previo a pasar los datos del result, obtener el tipo de dato de la columna, para eso uso un ciclo for y la funcion SQL2ClipType que retornara un caracter segun sea el caso si la columna es de tipo [C]har, [N]um, [D]ate, [M]emo, [L]ogic, la idea es agregar ese dato a un arreglo char para por ejemplo si la tabla tiene las siguiente columnas: CHAR, NUMERIC, DATE, LOGICAL, MEMO, tendria en la variable szTypeFields el contenido "CNDLM", esto para ser usado luego

Cade señalar que este funcion proviene de dolphin. solo intento mejorarla.

Code: Select all

HB_FUNC( MYSQL_QUERY2ARRAY )
{
   MYSQL *mysql = (MYSQL *) hb_MYSQL_par( 1 );

   if( mysql )
   {
      PHB_ITEM itemReturn = hb_itemArrayNew( 0 );

      if( mysql_real_query( mysql, (const char *) hb_parc( 2 ), (unsigned long) hb_parclen( 2 ) ) == MYSQL_QUERY_SUCCESS )
      {
         MYSQL_RES *mresult = mysql_store_result( mysql );

         if( mresult )
         {
            PHB_ITEM pBlock = hb_param( 3, HB_IT_BLOCK ) ? hb_param( 3, HB_IT_BLOCK ) : NULL;
            PHB_ITEM itemRow = hb_itemNew( NULL );
            PHB_ITEM Count = hb_itemNew( NULL );
            PHB_ITEM Rec = hb_itemNew( NULL );
            unsigned int uiNumFields, uiX;
            HB_LONGLONG llNumRows, llRec;
            MYSQL_FIELD *mField;
            MYSQL_ROW mrow;

            const char *szTypeField;
            char szTypeFields[]="";
            char letra;

            uiNumFields = mysql_num_fields( mresult );

            for( uiX = 0; uiX < uiNumFields; uiX++ ) //aca obtengo los tip
            {
               mField = mysql_fetch_field_direct( mresult, uiX );
               szTypeField = SQL2ClipType( ( long ) mField->type ); //aca obtengo que tipo de datos xbase es c/columna

               hb_xstrcat( szTypeFields, szTypeField, 0); //aca lo acumulo en un arrelo char
            }

            //OutStr( szTypeFields ); //CNDLM example

            llRec     = 0;
            llNumRows = mysql_num_rows( mresult );

            mysql_data_seek( mresult, 0 );

            while( ( mrow = mysql_fetch_row( mresult ) ) != NULL ) //aca el ciclo para pasar el result a array
            {
               if( mrow )
               {
                  hb_arrayNew( itemRow, uiNumFields );

                  for( uiX = 0; uiX < uiNumFields; uiX++ ) // ciclo para recorrer cada columna del result
                  {
                     //mi idea es obtener el tipo de dato xbase acumulado anteriormente
                     //y convertir el dato segun el tipo
                     //pero me falto conocimiento. :-)
                     /*
                     letra = szTypeFields[ uiX + 1 ];

                     switch ( letra )
                     {
                        case 'C':
                           //hb_arraySetC( itemRow, uiX + 1, mrow[ uiX ] );
                           break;
                        case 'N':
                           //hb_arraySetNI( itemRow, uiX + 1, mrow[ uiX ] );
                           break;
                        case 'D':
                           //hb_arraySetDS( itemRow, uiX + 1, mrow[ uiX ] );
                           break;
                        case 'L':
                           //hb_arraySetL( itemRow, uiX + 1, mrow[ uiX ] );
                           break;
                     }
                    */
                    //este es el codigo que pasa el valor al array (ver que todo lo pasa como cadena de caracteres)
                     if( mrow[ uiX ] == NULL )
                     {
                        hb_arraySetC( itemRow, uiX + 1, NULL );
                     }
                     else
                     {
                        hb_arraySetC( itemRow, uiX + 1, mrow[ uiX ] );
                     }
            
                  } //end for

                  hb_arrayAddForward( itemReturn, itemRow );

                  hb_itemPutNLL( Rec, llRec++ );
                  hb_itemPutNLL( Count, llNumRows );

                  if( pBlock )
                  {
                     hb_evalBlock( pBlock, itemRow, Rec, Count, NULL  );
                  }
               }
            } //end while

            mysql_free_result( mresult );

            hb_itemRelease( itemRow );
            hb_itemRelease( Count );
            hb_itemRelease( Rec );
         }
      }
      hb_itemReturnRelease( itemReturn );
   }
   else
   {
      hb_errRT_BASE( EG_ARG, 2020, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
   }
}
 
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
Posts: 1421
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Mysql (Result a Array en C) solicitud de ayuda.

Post by carlos vargas »

casi en forma similar, tengo la funcion que pasa a tabla, usando el api de harbour,
ya me crea la tabla con las respectivas columnas, y agrego los registos, pero igual que el caso anterior
deseo saber como pasar los datos segun su tipo a un PHB_ITEM para poder usar la funcion SELF_PUTVALUE( pArea, uiX, pItem );

se agradece cualquier o indicacion que me puedan brindar.

Code: Select all

HB_FUNC( MYSQL_QUERY2TABLE )
{
   MYSQL *mysql = (MYSQL *) hb_MYSQL_par( 1 );

   if( mysql )
   {
      HB_BOOL bCreated = HB_FALSE;

      if( mysql_real_query( mysql, (const char *) hb_parc( 2 ), (unsigned long) hb_parclen( 2 ) ) == MYSQL_QUERY_SUCCESS )
      {
         MYSQL_RES *mresult = mysql_store_result( mysql );

         if( mresult )
         {
            const char *szFileName = (const char *) hb_parc( 3 );
            const char *szAlias = (const char *) hb_parc( 4 );

            PHB_ITEM pStruct = hb_itemArrayNew( 0 );
            PHB_ITEM itemField = hb_itemNew( NULL );
            unsigned int uiNumFields, uiX;
            MYSQL_FIELD *mField;
            HB_ERRCODE errCode;
            char typefields[] = "";

            uiNumFields = mysql_num_fields( mresult );

            for( uiX = 0; uiX < uiNumFields; uiX++ )
            {
               mField = mysql_fetch_field_direct( mresult, uiX );

               hb_arrayNew( itemField, 4 );
               hb_arraySetC( itemField,  1, hb_strLower( mField->name, strlen( mField->name ) ) );
               hb_arraySetC( itemField,  2, SQL2ClipType( ( long ) mField->type ) );
               hb_arraySetNL( itemField, 3, (long) mField->length );
               hb_arraySetNI( itemField, 4, (int) mField->decimals );

               strncat( typefields, SQL2ClipType( ( long ) mField->type ), 1);

               hb_arrayAddForward( pStruct, itemField );
            }

            hb_itemRelease( itemField );

            errCode = hb_rddCreateTable( szFileName, NULL,
                                           0, szAlias,
                                           HB_TRUE,
                                           NULL, NULL,
                                           pStruct, NULL );

            if( errCode == HB_SUCCESS )
            {
               AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer();
               PHB_ITEM pItem;
               HB_LONGLONG llNumRows = mysql_num_rows( mresult );
               MYSQL_ROW mrow;
               bCreated = HB_TRUE;

               mysql_data_seek( mresult, 0 );

               while( ( mrow = mysql_fetch_row( mresult ) ) != NULL )
               {
                  if( mrow )
                  {
                     if( pArea )
                     {
                        hb_rddSetNetErr( FALSE );
                        if( SELF_APPEND( pArea, HB_FALSE ) == HB_SUCCESS )
                        {
                           for( uiX = 0; uiX < uiNumFields; uiX++ )
                           {
                              if( mrow[ uiX ] )
                              {
                                 //pItem = mrow[ uiX ];
                                 switch( typefields[ uiX ] )
                                 {
                                    case 'C':
                                       break;
                                    case 'N':
                                       hb_itemPutNI( pItem, (int) uiX );
                                       break;
                                    case 'D':
                                       break;
                                    case 'M':
                                       break;
                                    case 'L':
                                       break;
                                 }
                                 SELF_PUTVALUE( pArea, uiX, pItem );
                              }
                           }
                        }
                     }
                  }
               }

               hb_itemRelease( pItem );

               if( pArea )
               {
                  SELF_FLUSH( pArea );
               }

               HB_SYMBOL_UNUSED( llNumRows );
            }

            hb_itemRelease( pStruct );

            mysql_free_result( mresult );

            HB_SYMBOL_UNUSED( bCreated );
            HB_SYMBOL_UNUSED( szFileName );
            HB_SYMBOL_UNUSED( szAlias );
         }

      }
      hb_retl( bCreated );
   }
   else
   {
      hb_errRT_BASE( EG_ARG, 2020, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
   }
}
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
Posts: 1421
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Mysql (Result a Array en C) solicitud de ayuda.

Post by carlos vargas »

Ya he caminado unos cuantos pasos mas, ya funcionan las columnas tipo caracter (me falta hacer pad a su tamaño maximo), fecha y logico, me faltan los memos, numericos (entero y decimal)

Code: Select all

HB_FUNC( MYSQL_QUERY2ARRAY )
{
   MYSQL *mysql = (MYSQL *) hb_MYSQL_par( 1 );

   if( mysql )
   {
      PHB_ITEM itemReturn = hb_itemArrayNew( 0 );

      if( mysql_real_query( mysql, (const char *) hb_parc( 2 ), (unsigned long) hb_parclen( 2 ) ) == MYSQL_QUERY_SUCCESS )
      {
         MYSQL_RES *mresult = mysql_store_result( mysql );

         if( mresult )
         {
            PHB_ITEM pBlock = hb_param( 3, HB_IT_BLOCK ) ? hb_param( 3, HB_IT_BLOCK ) : NULL;
            PHB_ITEM itemRow = hb_itemNew( NULL );
            PHB_ITEM Count = hb_itemNew( NULL );
            PHB_ITEM Rec = hb_itemNew( NULL );
            unsigned int uiNumFields, uiX;
            HB_LONGLONG llNumRows, llRec;
            MYSQL_FIELD *mField;
            MYSQL_ROW mrow;

            const char *szType;
            char szTypeFields[ 255 ];
            char letra;

            uiNumFields = mysql_num_fields( mresult );

            for( uiX = 0; uiX < uiNumFields; uiX++ )
            {
               mField = mysql_fetch_field_direct( mresult, uiX );
               szType= SQL2ClipType( ( long ) mField->type );

               hb_strncat( szTypeFields, szType, sizeof( szTypeFields )-1 );
            }

            llRec     = 0;
            llNumRows = mysql_num_rows( mresult );

            mysql_data_seek( mresult, 0 );

            while( ( mrow = mysql_fetch_row( mresult ) ) != NULL )
            {
               if( mrow )
               {
                  hb_arrayNew( itemRow, uiNumFields );

                  for( uiX = 0; uiX < uiNumFields; uiX++ )
                  {

                     letra = szTypeFields[ uiX ];

                     switch ( letra )
                     {
                        case 'C':
                           hb_arraySetC( itemRow, uiX + 1, mrow[ uiX ] );
                           break;
                        case 'N':
                           break;
                        case 'D':
                        {
                           char * szTemp = mrow[ uiX ];
                           char szDate[9];

                           memcpy( szDate  , szTemp  , 4 );
                           memcpy( szDate+4, szTemp+5, 2 );
                           memcpy( szDate+6, szTemp+8, 2 );
                           szDate[8] = '\0';
                           hb_arraySetDS( itemRow, uiX + 1, szDate );
                           break;
                        }
                        case 'M':
                        {
                           //hb_arraySetCL( itemRow, uiX + 1, );
                           break;
                        }                       
                        case 'L':
                        {
                           BOOL bVal = HB_FALSE;
                           if( strcmp( mrow[ uiX ], "1" ) == 0 )
                           {
                              bVal = HB_TRUE;
                           }
                           hb_arraySetL( itemRow, uiX + 1, bVal );
                           break;
                        }
                     }
                  } //end for

                  hb_arrayAddForward( itemReturn, itemRow );

                  hb_itemPutNLL( Rec, llRec++ );
                  hb_itemPutNLL( Count, llNumRows );

                  if( pBlock )
                  {
                     hb_evalBlock( pBlock, itemRow, Rec, Count, NULL  );
                  }
               }
            } //end while

            mysql_free_result( mresult );

            hb_itemRelease( itemRow );
            hb_itemRelease( Count );
            hb_itemRelease( Rec );
         }
      }
      hb_itemReturnRelease( itemReturn );
   }
   else
   {
      hb_errRT_BASE( EG_ARG, 2020, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
   }
}
 
Me parece que en lugar de un array de char para guardar la info del tipo de columna, debo usar una structura para tambien guardar el tamaño, el tipo y si es numerico, guardar el decimal, y asi usarla mas adelante en el ciclo de pasar los datos al arreglo.

algo asi como

Code: Select all

struct _my_info {
   char     _mytype;
   ULONG _mysize;
   UINT    _mydec;
};
 
cualquier ayuda sera apreciada. :-)

gracias
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: Mysql (Result a Array en C) solicitud de ayuda.

Post by Antonio Linares »

Carlos,

revisa el código de FWH\source\function\msgs.c por si puede servirte de ayuda.

También puede ayudar el código de harbour\contrib\hbwin\olecore.c
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: Mysql (Result a Array en C) solicitud de ayuda.

Post by nageswaragunupudi »

I know Mr Carlos does not want to use FWH library, but all this functionality was built into FWH MariaDB library some years back.
Regards

G. N. Rao.
Hyderabad, India
User avatar
carlos vargas
Posts: 1421
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Mysql (Result a Array en C) solicitud de ayuda.

Post by carlos vargas »

Thank you, antonio.

Yes, Rao, the point is that I want to learn how to use the harbor api, it has always seemed a challenge to me.
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
Posts: 1421
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Mysql (Result a Array en C) solicitud de ayuda.

Post by carlos vargas »

Antonio,

que direfencia hay entre estas dos funciones?
extern HB_EXPORT HB_BOOL hb_arraySetC( PHB_ITEM pArray, HB_SIZE nIndex, const char * szText );
extern HB_EXPORT HB_BOOL hb_arraySetCL( PHB_ITEM pArray, HB_SIZE nIndex, const char * szText, HB_SIZE nLen );
asi esta quedando la funcion, ya en el ejemplo funciona bien, que te parece la implementacion?
no se como tratar a la cadena, y los memo.

me parece que la cadena deberia tener el tamaño que obtengo en mytest[ uiX ]->length, para ello deberia hacer un padLeft con espacios en blanco, alguna idea?

Code: Select all

typedef struct {
   const char *name;
   const char *type1;
   unsigned int type2;
   long length;
   long max_length;
   int decimal;
} MY_FIELD_INFO, *PMY_FIELD_INFO;
...

#define MY_FIELD_MAX          255

...

PMY_FIELD_INFO mytest[ MY_FIELD_MAX ];

            for( uiX = 0; uiX < uiNumFields; uiX++ )
            {
               mField = mysql_fetch_field_direct( mresult, uiX );

               mytest[ uiX ] = hb_xgrab( sizeof ( MY_FIELD_INFO ) );
               mytest[ uiX ]->name       = mField->name;
               mytest[ uiX ]->type1      = SQL2ClipType( ( long ) mField->type ); //aca obtengo C, N, D, M, L
               mytest[ uiX ]->type2      = SQL2ClipTypeN( ( long ) mField->type ); //aca obtengo un valor numerico
               mytest[ uiX ]->length     = mField->length;
               mytest[ uiX ]->max_length = mField->max_length;
               mytest[ uiX ]->decimal    = mField->decimals;
            }

...

                 for( uiX = 0; uiX < uiNumFields; uiX++ )
                  {
                     switch ( mytest[ uiX]->type2 )
                     {
                        case MY_FT_STRING:
                        case MY_FT_TIME:
                        case MY_FT_TIMESTAMP:
                        case MY_FT_DATETIME:
                        {
                           const char *szValue = "";
                           if( mrow[ uiX ] )
                           {
                              szValue = mrow[ uiX ];
                           }
                           hb_arraySetC( itemRow, uiX + 1, szValue );
                           break;
                        }
                        case MY_FT_INTEGER:
                        {
                           int iValue = 0;
                           if( mrow[ uiX ] )
                           {
                              iValue = atoi( mrow[ uiX ] );
                           }
                           hb_arraySetNI( itemRow, uiX + 1, iValue );
                           break;
                        }
                        case MY_FT_LONG:
                        {
                           long lValue = 0;
                           if( mrow[ uiX ] )
                           {
                              lValue = atol( mrow[ uiX ] );
                           }
                           hb_arraySetNL( itemRow, uiX + 1, lValue );
                           break;
                        }
                        case MY_FT_FLOAT:
                        {
                           float fValue = 0.00;
                           if( mrow[ uiX ] )
                           {
                              fValue = atof( mrow[ uiX ] );
                           }
                           hb_arraySetND( itemRow, uiX + 1, (double) fValue );
                           break;
                        }
                        case MY_FT_DATE:
                        {
                           char * szTemp = mrow[ uiX ];
                           char szDate[9];

                           memcpy( szDate  , szTemp  , 4 );
                           memcpy( szDate+4, szTemp+5, 2 );
                           memcpy( szDate+6, szTemp+8, 2 );
                           szDate[8] = '\0';

                           hb_arraySetDS( itemRow, uiX + 1, szDate );
                           break;
                        }
                        case MY_FT_MEMO:
                        {
                           hb_arraySetC( itemRow, uiX + 1, mrow[ uiX ] );
                           break;
                        }
                        case MY_FT_LOGICAL:
                        {
                           HB_BOOL bValue = FALSE;
                           if( mrow[ uiX ] )
                           {
                              bValue = strcmp( mrow[ uiX ], "1" ) == 0 ? HB_TRUE : HB_FALSE;
                           }
                           hb_arraySetL( itemRow, uiX + 1, bValue );
                           break;
                        }
                     }
                     /* implementacion anterior. (solo string)
                     if( mrow[ uiX ] == NULL )
                     {
                        hb_arraySetC( itemRow, uiX + 1, NULL );
                     }
                     else
                     {
                        hb_arraySetC( itemRow, uiX + 1, mrow[ uiX ] );
                     }
                     */
                  } //end for
 
esta funcion como funciona?
HB_BOOL hb_strToNum( const char * szNum, HB_MAXINT * plVal, double * pdVal )
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
User avatar
carlos vargas
Posts: 1421
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Mysql (Result a Array en C) solicitud de ayuda.

Post by carlos vargas »

bueno encontre una funcion de conversion de string a numero en el api de harbour.
creo es mejor usarla. :-)

Code: Select all

                        case MY_FT_INTEGER:
                        case MY_FT_LONG:
                        {
                           HB_SIZE nValue = 0;
                           if( mrow[ uiX ] )
                           {
                              UINT uiLen = strlen( mrow[ uiX ] );
                              nValue = (HB_SIZE) hb_strVal( mrow[ uiX ], uiLen );
                           }
                           hb_arraySetNL( itemRow, uiX + 1, (long) nValue );
                           break;
                        }
                        case MY_FT_FLOAT:
                        {
                           double dValue = 0.00;
                           if( mrow[ uiX ] )
                           {
                              UINT uiLen = strlen( mrow[ uiX ] );
                              dValue = hb_strVal( mrow[ uiX ], uiLen );
                           }
                           hb_arraySetND( itemRow, uiX + 1, dValue );
                           break;
                        }
 
Salu2
Carlos Vargas
Desde Managua, Nicaragua (CA)
Post Reply