FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour Expertos en ADS, como mejorar obtencion del CURSOR
Posts: 211
Joined: Wed Jul 16, 2008 12:59 PM
Expertos en ADS, como mejorar obtencion del CURSOR
Posted: Tue Jul 28, 2015 06:35 PM
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 (fw): Select all Collapse
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 (fw): Select all Collapse
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 (fw): Select all Collapse
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 (fw): Select all Collapse
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
Posts: 1074
Joined: Fri Oct 07, 2005 01:56 PM
Re: Expertos en ADS, como mejorar obtencion del CURSOR
Posted: Wed Jul 29, 2015 06:51 PM
Hola yo cree esta funcion no se si es lo que que buscas

y lo utilizo asi
Code (fw): Select all Collapse
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 )
//---------------------------------------------------------------------------------------
Saludos
Patricio

__________________________________________________________________
Version: Harbour 3.2.0dev (r1307082134),Compiler: Borland C++ 5.8.2 (32-bit)
PCode version: 0.3, FWH 13.2
http://www.sialm.cl
Posts: 257
Joined: Mon Jun 10, 2013 06:40 PM
Re: Expertos en ADS, como mejorar obtencion del CURSOR
Posted: Thu Jul 30, 2015 05:53 PM
Yo lo tengo asi, con tablas libres

Code (fw): Select all Collapse
    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.
Posts: 211
Joined: Wed Jul 16, 2008 12:59 PM
Re: Expertos en ADS, como mejorar obtencion del CURSOR
Posted: Thu Jul 30, 2015 07:16 PM
Rinaldo, Javier:
Gracias por responder

Lo que quiero es "ANIDAR" el ADSExecuteSQLDirect()

En el ejempo que pone Javier, lo que quiero hacer es:
Code (fw): Select all Collapse
    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.
Posts: 1789
Joined: Tue Oct 11, 2005 05:01 PM
Re: Expertos en ADS, como mejorar obtencion del CURSOR
Posted: Thu Jul 30, 2015 07:28 PM
Code (fw): Select all Collapse
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
Salu2

Carlos Vargas

Desde Managua, Nicaragua (CA)

Continue the discussion