Expertos en ADS, como mejorar obtencion del CURSOR

Post Reply
RSalazarU
Posts: 177
Joined: Wed Jul 16, 2008 12:59 pm
Location: Cochabamba-Bolivia
Contact:

Expertos en ADS, como mejorar obtencion del CURSOR

Post 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

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

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

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

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
User avatar
Patricio Avalos Aguirre
Posts: 1028
Joined: Fri Oct 07, 2005 1:56 pm
Location: La Serena, Chile
Contact:

Re: Expertos en ADS, como mejorar obtencion del CURSOR

Post by Patricio Avalos Aguirre »

Hola yo cree esta funcion no se si es lo que que buscas

y lo utilizo asi

Code: Select all

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
VitalJavier
Posts: 188
Joined: Mon Jun 10, 2013 6:40 pm

Re: Expertos en ADS, como mejorar obtencion del CURSOR

Post by VitalJavier »

Yo lo tengo asi, con tablas libres

Code: Select all

    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.
RSalazarU
Posts: 177
Joined: Wed Jul 16, 2008 12:59 pm
Location: Cochabamba-Bolivia
Contact:

Re: Expertos en ADS, como mejorar obtencion del CURSOR

Post 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

    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.
User avatar
carlos vargas
Posts: 1421
Joined: Tue Oct 11, 2005 5:01 pm
Location: Nicaragua

Re: Expertos en ADS, como mejorar obtencion del CURSOR

Post by carlos vargas »

Code: Select all

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)
Post Reply