Page 1 of 1

Expertos en ADS, como mejorar obtencion del CURSOR

PostPosted: Tue Jul 28, 2015 6:35 pm
by RSalazarU
Amigos del foro:

Necesito mejora la velocidad al obtener un cursor en ADS.

En la ayuda de ADVANTAGE DATABASE SERVER se tiene la siguiente secuencia de instrucciones:
Code: Select all  Expand view

DoSQL( void )

AdsCreateSQLStatement( hConnect, &hSQL ); //Prepara el AREA

AdsStmtSetTableType( hSQL, ADS_ADT );                                        

AdsStmtSetTableRights( hSQL, ADS_IGNORERIGHTS );   //Establece algunas propiedades
AdsStmtSetTableLockType( hSQL, ADS_PROPRIETARY_LOCKING );
AdsStmtSetTableCharType( hSQL, ADS_ANSI );
AdsStmtConstrainUpdates( hSQL, ADS_CONSTRAIN );
AdsStmtSetTableReadOnly( hSQL, ADS_CURSOR_READWRITE );

AdsPrepareSQL( hSQL, "SELECT * FROM plane WHERE arrival = :ArrivalParam" ); //Prepara el SQL
AdsSetTimeStamp( hStatement, "ArrivalParam", "04/18/1999 7:00 AM",
AdsExecuteSQL( hSQL, &hCursor ); //CREA el cursor
AdsCloseTable( hCursor ); //CIERRA el cursor  

AdsClearSQLParams( hSQL );

AdsPrepareSQL( hSQL, "SELECT * FROM plane WHERE arrival = ?" ); //CREA otro cursor, sin cerrar el AREA
AdsSetTimeStamp( hStatement, ADSFIELD( 1 ), "04/18/1999 7:00 AM", //CIERRA el cursor  
AdsExecuteSQL( hSQL, &hCursor );
AdsCloseTable( hCursor );

AdsClearSQLParams( hSQL );

AdsExecuteSQLDirect( hSQL, "Select lastname from Demo10", &hCursor ); //CREA otro cursor, sin cerrar el AREA
AdsGotoTop( hCursor );                                    
AdsSkip( hCursor, 1 );
AdsGetString( hCursor, "Lastname", aucFieldVal, &ulLength, ADS_NONE );
AdsSetString( hCursor, "Lastname", "Johnson", strlen( "Johnson" ) );
AdsCloseTable( hCursor ); //CIERRA el cursor                    

AdsCloseSQLStatement ( hSQL ); //Cierra el area

AdsDisconnect( hConnect );  //Cierra la CONEXION
 


Quiero hacer lo mismo en FWH/xharbour:
1. Preparar AREA
2. Abrir cursor
3. Cerrar cursor
.
.
100. Abrir cursor
101. Cerrar cursor
102. Cerrar AREA

Tengo la siguiente secuencia de instrucciones que funcionan con algo similar
Code: Select all  Expand view

AdsCreateSqlStatement( "Empleado", ADS_CDX, nConnection ) //Prepara el AREA
ADSExecuteSQLDirect("SELECT TOP 0 * FROM Empleados;") //CREA el cursor  
.
.
DBSelectArea( "Empleado" )  //Selecciono el AREA
DbCloseArea()               //Necesariamente TENGO que cerrar el AREA
                            //que ejecuta AdsCloseSQLStatement() y otras cosas mas

AdsCreateSqlStatement( "Empleado", ADS_CDX, nConnection ) //Nuevamente Prepara el AREA  
ADSExecuteSQLDirect("SELECT TOP 1 * FROM Empleados WHERE Upper([NAME])='Juan';") //Nuevamente CREA el cursor  

Msginfo(Empleado->NOMBRE) //Muestra el nombre
.
.
DbCloseArea()  //Cierra el area que ejecuta AdsCloseSQLStatement() y otras cosas mas
 



Lo cambie por esto:
Code: Select all  Expand view

AdsCreateSqlStatement( "Empleado", ADS_CDX, nConnection ) //Prepara el AREA
ADSExecuteSQLDirect("SELECT TOP 0 * FROM Empleados;")     //CREA el cursor  
.
.
DBSelectArea( "Empleado" )  //Selecciono el AREA

//esto SOLO deberia cerrar el CURSOR
AdsCloseCursor() //ESTA ES LA NUEVA FUNCION implementada en adsfunc.c

//esto seria como recargar el CURSOR
//pero provoca error, el programa falla
//no muestra ningun mensaje
//Solo Windows indica que el progrma fallo
ADSExecuteSQLDirect("SELECT TOP 1 * FROM Empleados WHERE Upper([NAME])='Juan';")

Msginfo(Empleado->NOMBRE) //Muestra el nombre
.
.
DbCloseArea() //Cierra el area que ejecuta AdsCloseSQLStatement() y otras cosas mas
 


Previamente añadi la funcion AdsCloseCursor() a adsfunc.c. Compile y cree la LIB en forma correcta.
Code: Select all  Expand view

HB_FUNC( ADSCLOSECURSOR )
{
   ADSAREAP pArea = hb_adsGetWorkAreaPointer();

   if( /* hb_ads_hConnect && */ pArea && pArea->hStatement )
   {
      if( pArea->hTable )
      {

         UNSIGNED32 ulRetVal = AdsCloseTable( pArea->hTable );

     if( ulRetVal == AE_SUCCESS )
     {
            pArea->hOrdCurrent = 0;
            pArea->hTable = 0;


            /* Free field offset array */
            /*if( pArea->pFieldOffset )
            {
               hb_xfree( pArea->pFieldOffset );
               pArea->pFieldOffset = NULL;
            }*/


            /* Free buffer */
            if( pArea->pRecord )
            {
               hb_xfree( pArea->pRecord );
               pArea->pRecord = NULL;
            }

            /* Free all filenames */
            if( pArea->szDataFileName )
            {
               hb_xfree( pArea->szDataFileName );
               pArea->szDataFileName = NULL;
            }

            hb_retl( TRUE );
         }
         else
         {
            HB_TRACE(HB_TR_DEBUG, ("adsCloseTable() error"));
            hb_retl( FALSE );
         }
      }
      else
         hb_retl( FALSE );
   }
   else
      hb_retl( FALSE );
}
 


La funcion AdsCloseCursor() devuelve .T., lo cual indica que cerro bien el cursor,
pero cuando ejecuto la siguiente instruccion ADSExecuteSQLDirect() el programa deja de funcionar

Que mas habria que añadir a la funcion AdsCloseCursor() para que ADSExecuteSQLDirect() se ejecute en forma correcta?

De antemano GRACIAS POR LA AYUDA.

Rolando
Cochabamba, Bolivia

Re: Expertos en ADS, como mejorar obtencion del CURSOR

PostPosted: Wed Jul 29, 2015 6:51 pm
by Patricio Avalos Aguirre
Hola yo cree esta funcion no se si es lo que que buscas

y lo utilizo asi
Code: Select all  Expand view

SELE 0 ; USE REPUESTOS NEW

SqlEjecute( "pasoSQL", "SELECT * FROM ARTICU" )
pasoSQL->( browse() )
repuestos->( browse() )
BLA
BLA
PasoSQL->( dbCloseArea() )
Repuestos->( dbCloseArea() )
return...
//-----------------------------------------------------------------

nota:hconnection es la conexion de diccionario, lo utilizo cuando hay mas de un (1 ) diccionario de datos
#include "ads.ch"
function SqlEjecute( cNewAlias, cSql, hConnection, nCache )
local cAlias := ALIAS(), lReturn := .t.

DEFAULT hConnection := ViewUsu():hConnection, nCache := 0

Select 0

if !AdsCreateSqlStatement( (cNewAlias), ADS_CDX, hConnection )
    MsgInfo("error AdsCreateSqlStatement()" + CRLF + "Error:"+cValtochar( AdsGetLastError() ) )
    lReturn :=  .f.
endif

if lReturn .and. !AdsExecuteSqlDirect(cSql)
    (cNewAlias)->( dbCloseArea() )
    lReturn :=  .f.
    MsgInfo("error AdsExecuteSqlDirect(cSql)" + CRLF + "Error:"+cValtochar( AdsGetLastError() ) )
    if file( "c:\SqlError.txt" )
        ferase( "c:\SqlError.txt" )
    endif
    Logfile( "c:\sqlError.txt", { cSql } )
endif

if Select( (cNewAlias) ) > 0
    if lReturn .and. nCache > 0
        (cNewAlias)->(AdsCacheRecords(nCache))
    endif
    (cNewAlias)->( dbGotop() )
endif

if !empty( cAlias )
    select (cAlias)
endif
hConnection := NIL

return( lReturn )
//---------------------------------------------------------------------------------------
 

Re: Expertos en ADS, como mejorar obtencion del CURSOR

PostPosted: Thu Jul 30, 2015 5:53 pm
by VitalJavier
Yo lo tengo asi, con tablas libres

Code: Select all  Expand view

    Select 0
    ADSCreateSQLStatement("MIALIAS",3)
    cSQL := "SELECT {static} * from ARTICULOS"
    ADSExecuteSQLDirect(cSQL)
    SELECT MIALIAS

    ...............

    SELECT MIALIAS
    DbCloseArea()
 


y me funciona muy bien
Espero y te ayude

Saludos.

Re: Expertos en ADS, como mejorar obtencion del CURSOR

PostPosted: Thu Jul 30, 2015 7:16 pm
by RSalazarU
Rinaldo, Javier:
Gracias por responder

Lo que quiero es "ANIDAR" el ADSExecuteSQLDirect()

En el ejempo que pone Javier, lo que quiero hacer es:
Code: Select all  Expand view

    Select 0
    ADSCreateSQLStatement("MIALIAS",3)

    cSQL := "SELECT {static} * from ARTICULOS WHERE Codigo='0001'; "
    ADSExecuteSQLDirect(cSQL)
    SELECT MIALIAS
    MsgInfo(FIELD->NOMBRE)
    ADSCloseCursor() //OJO Cierra el cursor

    cSQL := "SELECT {static} * from ARTICULOS WHERE Codigo='0020'; "
    ADSExecuteSQLDirect(cSQL)
    SELECT MIALIAS
    MsgInfo(FIELD->NOMBRE)
    ADSCloseCursor() //OJO Cierra el cursor

    cSQL := "SELECT {static} * from ARTICULOS WHERE Codigo='0300'; "
    ADSExecuteSQLDirect(cSQL)
    SELECT MIALIAS
    MsgInfo(FIELD->NOMBRE)

    ...............

    SELECT MIALIAS
    DbCloseArea() //Cierra el cursor y el AREA

 


Ejecutar solo una vez ADSCreateSQLStatement()

Y hacer DbCloseArea() solo una vez al final del proceso.

En la ayuda de "ADVANTAGE DATABASE SERVER" hay un ejemplo en el que muestra que si se puede hacer.
Ahi mustra como se usa la instruccion ADSCloseCursor()

Bueno, espero que alguien mas tenga algo.

Re: Expertos en ADS, como mejorar obtencion del CURSOR

PostPosted: Thu Jul 30, 2015 7:28 pm
by carlos vargas
Code: Select all  Expand view
FUNCTION ADSRunSQL( cAlias, cSql, aParameters, hConnection, lShow )
   LOCAL nError     := 0
   LOCAL cError     := ""
   LOCAL lCreated   := FALSE
   LOCAL cOldAlias  := Alias()
   LOCAL lOldDelete := AdsSetDeleted( FALSE )
   LOCAL xParameter

   DEFAULT hConnection := hConexion
   DEFAULT lShow       := FALSE

   IF !Empty( cAlias ) .and. !Empty( cSql )  .and. hConnection > 0

      cSql := StrTran( cSql, ";", "" )

      IF SELECT( cAlias ) > 0
         (cAlias)->( DBCloseArea() )
      ENDIF

      DBSelectArea( 0 )

      IF !AdsCreateSqlStatement( cAlias, ADS_CDX, hConnection )
         nError := AdsGetLastError( @cError )
         LogFile( "adssqlerror.log", { nError, cError } )
         MsgAlert( "Error AdsCreateSqlStatement()" + FINL + "Error: " + CStr( cError ) )
      ELSE
         IF HB_IsArray( aParameters )
            FOR EACH xParameter IN aParameters
               cSql  := StrTran( cSql, "%" + AllTrim( Str( HB_EnumIndex() ) ), Var2Str( xParameter ) )
            NEXT
         ENDIF
         IIf( lShow, KDSDebug( cSql ), NIL )
         IF !AdsExecuteSqlDirect2( cSql )
            nError := AdsGetLastError( @cError )
            LogFile( "adssqlerror.log", { nError, cError, cSql } )
            MsgAlert( "Error AdsExecuteSqlDirect()" + FINL + "Error:" + CStr( cError ) + FINL + cSql )
         ELSE
            lCreated := TRUE
         ENDIF
      ENDIF
      IF !lCreated .and. SELECT( cAlias ) > 0
         ( cAlias )->( DBCloseArea() )
      ENDIF
      IF !Empty( cOldAlias )
         DBSelectArea( cOldAlias )
      ENDIF
   ELSE
      MsgAlert( "No definio instrucción SQL, o no se especifico area de trabajo para la consulta." )
   ENDIF

   AdsSetDeleted( lOldDelete )

RETURN lCreated