Page 1 of 1

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

Posted: Mon Mar 01, 2021 5:04 pm
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 );
   }
}
 

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

Posted: Mon Mar 01, 2021 5:08 pm
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 );
   }
}

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

Posted: Mon Mar 01, 2021 9:37 pm
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

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

Posted: Tue Mar 02, 2021 7:53 am
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

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

Posted: Tue Mar 02, 2021 12:28 pm
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.

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

Posted: Tue Mar 02, 2021 4:24 pm
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.

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

Posted: Tue Mar 02, 2021 8:40 pm
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 )

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

Posted: Tue Mar 02, 2021 9:26 pm
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;
                        }