Uso de Diccionario de Datos ADS y tablas libres

Uso de Diccionario de Datos ADS y tablas libres

Postby Yessica » Thu Jan 29, 2015 12:57 am

Compañeros necesito de su pronta ayuda.

Resulta que tengo mi conexión al Diccionario de Datos, donde están todas mis tablas, pero también al mismo tiempo necesito usar tablas libres que obvio, no están dentro del Diccionario (.DD), ¿Cómo puedo hacer para utilizar ambas maneras, Tablas en diccionario y tablas libres.

AdsConnect60(parametros) // conecta a diccionario

use tabla shared alias aTab // aqui abro mi tabla que está en el diccionario.

Pero como abrir la tabla que se encuentra fuera del diccionario??

Espero me puedan apoyar.

Gracias
Yessica
 
Posts: 78
Joined: Thu May 28, 2009 6:58 pm

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby lucasdebeltran » Thu Jan 29, 2015 9:03 am

Hola,

Cuando usas adsconnect60 no puedes usar tablas libres.
Muchas gracias. Many thanks.

Un saludo, Best regards,

Harbour 3.2.0dev, Borland C++ 5.82 y FWH 13.06 [producción]

Implementando MSVC 2010, FWH64 y ADO.

Abandonando uso xHarbour y SQLRDD.
User avatar
lucasdebeltran
 
Posts: 1303
Joined: Tue Jul 21, 2009 8:12 am

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby reinaldocrespo » Thu Jan 29, 2015 2:45 pm

Yessica;

Hola. Hace mucho tiempo no uso tablas libres (free tables), no obstante, entiendo que no existe ninguna ciencia oculta para hacerlo. Es decir, tablas libres es la forma tradicional de usar dbfs. No estoy seguro si lo que Lucas dice es siempre cierto. Yo recuerdo cuando comencé a usar el dd que también usaba tablas libres a la vez. Especialmente para tablas dbfs temporeras.

¿Usas el "remote" server o el "local server"? ¿Tienes el directorio donde residen las tablas libres compartido y existe ruta desde la estación de trabajo a dicho directorio? Te recuerdo que a menos que las tablas residan localmente en el disco c:, para usar tablas libres necesitas un "share"- es decir, compartir el directorio donde residen las tablas libres y desde código necesitas proveer la ruta a la tabla además del nombre de la tabla.

Code: Select all  Expand view  RUN
     Dbusearea( lNew ,cRDD , cFileName, cAlias , lShared , lReadonly )


donde cFileName incluye la ruta (c:\PathToData\customers.dbf). Por favor déjame conocer que tal te funciona .

Reinaldo.
User avatar
reinaldocrespo
 
Posts: 979
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby Yessica » Thu Jan 29, 2015 2:55 pm

lucasdebeltran wrote:Hola,

Cuando usas adsconnect60 no puedes usar tablas libres.


Lucas gracias por contestar, y claro que uso adsconnect60, puesto que uso tablas en el diccionario y a la vez necesito tablas libres.

Por eso mi pregunta de cómo trabajar con tablas libres y tablas en el diccionario al mismo tiempo.
Yessica
 
Posts: 78
Joined: Thu May 28, 2009 6:58 pm

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby Yessica » Thu Jan 29, 2015 3:05 pm

reinaldocrespo wrote:Yessica;

Hola. Hace mucho tiempo no uso tablas libres (free tables), no obstante, entiendo que no existe ninguna ciencia oculta para hacerlo. Es decir, tablas libres es la forma tradicional de usar dbfs. No estoy seguro si lo que Lucas dice es siempre cierto. Yo recuerdo cuando comencé a usar el dd que también usaba tablas libres a la vez. Especialmente para tablas dbfs temporeras.

¿Usas el "remote" server o el "local server"? ¿Tienes el directorio donde residen las tablas libres compartido y existe ruta desde la estación de trabajo a dicho directorio? Te recuerdo que a menos que las tablas residan localmente en el disco c:, para usar tablas libres necesitas un "share"- es decir, compartir el directorio donde residen las tablas libres y desde código necesitas proveer la ruta a la tabla además del nombre de la tabla.

Code: Select all  Expand view  RUN
     Dbusearea( lNew ,cRDD , cFileName, cAlias , lShared , lReadonly )


donde cFileName incluye la ruta (c:\PathToData\customers.dbf). Por favor déjame conocer que tal te funciona .

Reinaldo.



Gracias por contestarme Reinaldo:

Mira te comento que antes usaba el fwh 2.4 con xharbour, aqui yo no tenía ningún problema en usar Tablas dentro del diccionario y tablas libres, es decir podía usar las dos al mismo tiempo.
Ahora que estoy con fwh 14.12 con harbour, me manda un error al intentar abrir la tabla libre.

Uso el AdsSetServerType(7), que se supone que es para Local, Remote e Internet

y Uso ADTs.

la tabla libre la quiero abrir de la siguiente manera:

use c:\carpeta1\carpeta2\nomtabla shared alias AliasTab

Espero tu respuesta gracias Reinaldo.
Yessica
 
Posts: 78
Joined: Thu May 28, 2009 6:58 pm

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby reinaldocrespo » Thu Jan 29, 2015 3:13 pm

¿Puedes citar el error? Tal vez tienes el RDD por default set a ADSADT o algún otro tipo de RDD no compatible con la tabla libre. Te recuerdo que siempre puedes añadir el RDD que se debe usar con la cláusula VIA. Por ejemplo VIA "DBFCDX" ¿Será ese el problema?
User avatar
reinaldocrespo
 
Posts: 979
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby Yessica » Thu Jan 29, 2015 3:19 pm

reinaldocrespo wrote:¿Puedes citar el error? Tal vez tienes el RDD por default set a ADSADT o algún otro tipo de RDD no compatible con la tabla libre. Te recuerdo que siempre puedes añadir el RDD que se debe usar con la cláusula VIA. Por ejemplo VIA "DBFCDX" ¿Será ese el problema?


El error es el guiente:

Error ADSADT/5132 Error 5132: The specified database object name is not valid. "C:\CARPETA\PRESTAMO\ESTADOS" is not a table or view in the data Dictionary.: C:\CARPETA\PRESTAMO\ESTADOS
Yessica
 
Posts: 78
Joined: Thu May 28, 2009 6:58 pm

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby reinaldocrespo » Thu Jan 29, 2015 4:02 pm

Yessica;

Cuando te conectas a un DD, el DD contiene metadata que describe las tablas. Entre otras cosas describe que indices tiene asociados, triggers, que tipo de tabla es, como por ejemplo; si la tabla es dbfcdx, dbfntx, adsadt, etc... Yo pienso que es posible que el problema que confrontas sea que la tabla es dbfcdx y la intentas abrir con adsadt. Intenta usar la cláusula VIA como parte del USE ... ¿Es la tabla DBFNTX, DBFCDX? Usa el RDD correspondiente en tu USE command. ¿Te funciona? Una última cosa, la tabla que llamas "free" es también parte de un DD, entonces esa tabla NO es "free".

Yo uso xHarbour con FW 12_10 y no puedo reproducir el problema. A ver si te puedo crear un -self-contained-reduced sample que puedas probar allá con tu harbour y fw.

Reinaldo.
User avatar
reinaldocrespo
 
Posts: 979
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby Yessica » Thu Jan 29, 2015 4:16 pm

reinaldocrespo wrote:Yessica;

Cuando te conectas a un DD, el DD contiene metadata que describe las tablas. Entre otras cosas describe que indices tiene asociados, triggers, que tipo de tabla es, como por ejemplo; si la tabla es dbfcdx, dbfntx, adsadt, etc... Yo pienso que es posible que el problema que confrontas sea que la tabla es dbfcdx y la intentas abrir con adsadt. Intenta usar la cláusula VIA como parte del USE ... ¿Es la tabla DBFNTX, DBFCDX? Usa el RDD correspondiente en tu USE command. ¿Te funciona? Una última cosa, la tabla que llamas "free" es también parte de un DD, entonces esa tabla NO es "free".

Yo uso xHarbour con FW 12_10 y no puedo reproducir el problema. A ver si te puedo crear un -self-contained-reduced sample que puedas probar allá con tu harbour y fw.

Reinaldo.


Mira la tabla que intento abrir es .ADT, solo que no se encuentra dentro del diccionario. Si la misma tabla la meto al diccionario, obviamente poniendola donde estan las demas que estan en el diccionario, la abre perfectamente, pero como no está en el diccionario osea esta libre, repito uso tablas ADTs con ADIs (Indices). No me permite abrirla.

Antes podia hacerlo muy bien con solo decir:

Use TablaLibre exclusive // Apertura de tabla libre, al mismo tiempo usaba la conexion al DD para tomar las tablas que están dentro del mismo.

La tabla libre que deseo abrir no esta en ningún diccionario, esta totalmente libre.

Es que se me hace tan raro que antes si podia hacerlo y ahora que cambio de versión de Fwh y harbour ya no pueda.
Yessica
 
Posts: 78
Joined: Thu May 28, 2009 6:58 pm

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby reinaldocrespo » Thu Jan 29, 2015 5:00 pm

Abajo te incluyo código que acabo de probar y funciona perfectamente. Crea varias tablas de varios tipos diferentes (DBFNTX, DBFVFP, ADSADT) usando ADS RDD. Luego crea un dd y añade las 3 tablas al DD. Luego se conecta al DD y luego crea una 4ta tabla usando DBFCDX para entonces abrirla como un free table.

He probado usando xharbour de SVN + Borland c 5.82. El código es independiente de GUI, o sea, nada tiene que ver con fw y es código muy sencillo y corto. ¿Te funciona igual a ti?

Code: Select all  Expand view  RUN
//This console mode app shows how to create a few tables of different types.
//How to create an Advantage Data Dictionary and add the newly created
//tables the data dictionary file.
//I'm using various table types using ADS RDDs for DBF/NTX, DBF/VFP, ADT/ADI
//
//After that it atttempts to connect to the dd, create a new table and then
//open the new table as a free table.
//In short- it creates tables and dd, opens dd bound tables and free tables
//at the same time.
//
//The sample code uses pure rdds + some ACE calls.
//No GUI dependency as only a console mode app is being built, which should
//build just the same under Windows as well as under Linux.
//
#include "ads.ch"

#xcommand DEFAULT <uVar1> := <uVal1> ;
                [, <uVarN> := <uValN> ] => ;
                  <uVar1> := iif( <uVar1> == nil, <uVal1>, <uVar1> ) ;;
                [ <uVarN> := iif( <uVarN> == nil, <uValN>, <uVarN> ); ]

REQUEST DBFCDX
REQUEST ADS          //Make sure rddads gets linked to our app.
REQUEST hb_gt_win    //needed for console mode app.

//Static variable cPath will contain the path where tables and DD will be created.
//After connecting to an existing DD, there is no need to use the file path as the
//DD saves the relative path of each table as part of its metadata.
STATIC cPath

*-----------------------------------------------------------------------------------------------------
FUNCTION Main()

   LOCAL afiles

   SetMode(25,80)      //25 lines by 80 columns console

   rddRegister( "ADS", 1 )
   
   rddSetDefault( "ADS" )

   adsSetServerType( ADS_LOCAL_SERVER )

   //NON-compatible locking mode.  If other NON-ADS clients are going to
   //to work on the same tables, then make sure to use compatible locking mode.
   AdsLocking( .t. )  
   AdsRightsCheck( 0 )
   
   //Path for existing .dbf tables maybe sent as a parameter
   //on the command line.  This is just one idea.  It could be saved
   //on a .ini file or hardcoded.
   cPath   := hb_ArgV( 1 )
   
   //in case no path was sent on command line, assume current path.
   DEFAULT cpath := ""  
   
   //sanitize cPath contents.
   //IF !EMPTY( cPath ) .and. RIGHT( cPath, 1 ) != ''    ;cPath += ''  ;ENDIF
   
   //if you need to create some new tables other than existing tables look
   //at function CreateTables().  CreateTables shows how to create
   //adt tables, vfp tables, and dbf-ntx tables.
   //
   //CreateTables() creates an array with table names and structure for each.
   //It then creates the tables.  After being created they will be added to a newly
   //created data dictionary using function CreateDictionary().
   //If your .dbf tables are alreay present, then you won't need to execute
   //CreateTables, instead you could simply execute a Directory() harbour
   //function to retreive existing table names.  By storing the names of these tables
   //into afiles variable, you can then execute CreateDictionary() in exactly the same
   //manner.
   afiles := CreateTables()
   
   IF !EMPTY( afiles )     ;CreateDictionary( afiles )     ;ENDIF

   //now that we have a dd created, we will attempt to connect to it and
   //use the tables as dd bound tables.

    IF !AdsConnect60( cPath + "test_dd.add", ADS_LOCAL_SERVER, "user1", "password1" )
   
       Alert( "Cannot connect to test_dd" + Str( AdsGetLastError() ) )
      QUIT

   ENDIF


   //Now we create a dbfcdx table to be used as a free table.
   CreateAndUseFreeTable()

       
RETURN NIL

//--------------------------------------------------------------------------------------
//function CreateTables() will create three tables using stnd harbour func dbCreate
//Each table structure is saved on an array following the std returned by dbStruct()
//Each element on the array is an array describing the field.  Thus, the array
//for a table with 3 fields would look like this:
//aStructure := { { cFieldName1, cFieldType1, nFldWidth, nDecimals },;
//                { cFieldName2, cFieldType2, nFldWidth, nDecimals },;
//                { cFieldName3, cFieldType3, nFldWidth, nDecimals } }
//
STATIC FUNCTION CreateTables()
   LOCAL cAlias := "MyAlias"
   LOCAL afiles := {}
   LOCAL cFileName, e

    //---------------------- customers.adt --------------------------------------------
   LOCAL aStruc := { { "cust_id"    , "C", 10, 0 },;
                { "Sequence"        , "AutoInc", 07, 0 },;      //ADT extended field type autoincrement
                { "customer_name"   , "C", 25, 0 },;
                { "Start_date"      , "TimeStamp", 01, 0 },;    //ADT extended field type
                { "Notes"           , "M", 10, 0 } }
                       
    AdsSetFileType( ADS_ADT )  

    TRY    
        dbCreate( ( cFileName := cPath + "customers.adt" ), aStruc,, .t., cAlias )

        ( cAlias )->( OrdCreate( cPath + "customers", "cust_id", "cust_id" ) )
        ( cAlias )->( OrdCreate( cPath + "customers", "Start_date", "Start_date" ) )
        ( cAlias )->( dbclosearea() )

        AADD( afiles, { cFileName, "customers.adi" } )

   
    //------------------------ sales.dbf -------------------------------------------------
        aStruc := { { "cust_id" , "C", 10, 0 },;
                { "invoice"     , "C", 15, 0 },;
                { "s_date"      , "TimeStamp", 01, 0 },;    //VFP extended field type
                { "item_id"     , "C", 15, 0 },;
                { "Units"       , "N", 03, 0 },;
                { "Price"       , "Money", 09, 2 },;        //VFP extended field type
                { "Notes"       , "M", 10, 0 } }
                   
        AdsSetFileType( ADS_VFP )

        dbCreate( ( cFileName := cPath + "sales.dbf" ), aStruc,, .t., cAlias )

        ( cAlias )->( OrdCreate( cPath + "sales", "invoice", "invoice" ) )
        ( cAlias )->( OrdCreate( cPath + "sales", "cust_id", "cust_id" ) )
        ( cAlias )->( dbclosearea() )

        aadd( afiles, { cFileName, "sales.cdx" } )



    //------------------------ items.dbf -------------------------------------------------
        aStruc := { { "item_id"     , "C", 15, 0 },;
                { "Desc"    , "C", 25, 0 },;
                { "Price"   , "N", 07, 2 } }
                   
        AdsSetFileType( ADS_NTX )

        dbCreate( ( cFileName := cPath + "items.dbf" ), aStruc,, .t., cAlias )
        ( cAlias )->( OrdCreate( cPath + "itm_id",, "item_id" ) )
        ( cAlias )->( OrdCreate( cPath + "itm_desc",, "Desc" ) )
        ( cAlias )->( dbclosearea() )

        aadd( afiles, { cFileName, "itm_id.ntx;itm_desc.ntx" } )

    CATCH e
   
        ShowError( cFileName, e )
        afiles := {}
       
    END

RETURN afiles

/*--------------------------------------------------------------------------------------------------------
CreateDictionary creates an Advantage Data Dictionary based on already existing tables
--------------------------------------------------------------------------------------------------------*/

STATIC FUNCTION CreateDictionary( afiles )
   LOCAL cExt AS CHARACTER := ""
   LOCAL cDD := cPath + "test_dd.add"

   IF !ADSDDCREATE( cDD,, "Sample data dictinoary" )

      ALERT( "AdsCreate() of " + cDD + " failed. Error:" + Str( AdsGetLastError() ) )
      RETURN NIL

   ENDIF
   
   //Calling ACE function AdsDDSetDatabaseProperty()
   AdsDDSetDatabaseProperty( ADS_DD_ENABLE_INTERNET, .t. )
   AdsDDSetDatabaseProperty( ADS_DD_INTERNET_SECURITY_LEVEL, ADS_DD_LEVEL_2 )
   AdsDDSetDatabaseProperty( ADS_DD_DEFAULT_TABLE_PATH, cPath )
   AdsDDSetDatabaseProperty( ADS_DD_LOG_IN_REQUIRED, .t. )


   //ACE Function ADsDDCreateUser() creates a dd user.
   //When a new dd is created user ADSSYS is auto-created as the dd administrator
   //it is a good idea to create other users to limit access and permissions.
   //
   AdsDDCreateUser( , "user1", "password1", "User named userd1 with password password1" )
   AdsDDCreateUser( , "user2", "password2", "Description of user2" )
   AdsDDCreateUser( , "user3", "password3", "Optional description of user3" )

   //array aFiles contains the names of the tables to be added to the newly created
   //data dictionary.  
   //element 1 on the array is the table name,
   //element 2 on the array is the index file name.
   //Since .dbf tables could be vfp, cdx, or ntx type tables,
   //we are using the extension on the index file name to "guess" the .dbf
   //file type.  If this is already known beforehand, then the code below
   //could be much simpler.  I'm using AEVAL only because I love it albeit it is
   //more cryptic.  The same can be done on a FOR EACH (FOR/REPEAT/WHILE) loop
    AEVAL( aFiles, ;
        { |e| hb_FNameSplit( iif( len( e ) > 1, e[ 2 ], e[ 1 ] ), , , @cExt ), ;
            AdsSetFiletype( iif( lower( cExt ) $ ".adt,.adi", ADS_ADT, ;
                        iif( lower( cExt ) == ".ntx", ADS_NTX, ADS_VFP ) ) ),;
            addfiletoDD( e, cPath ), ;
            SetTableProp( e ), ;
            QOut( "Adding table to DD", ;
                        e[ 1 ], ;
                        AdsSetFileType(), ;
                        cExt, ;
                        ADSGetLastError() ) } )

   //assign the password "password" to the ADSSYS user of the DD.  Just as default.
    AdsDDSetDatabaseProperty( ADS_DD_ADMIN_PASSWORD, "password" )

    Wait

return Nil

//-------------------------------------------------------------------------------------------------------
//This is the code that adds the table to the DD.
STATIC FUNCTION AddFiletoDD( aFile, cPath )
   LOCAL cIndexs := ""

   IF LEN( afile ) > 1 .AND. LEFT( afile[ 2 ], 1 ) <> "."
   
        AEVAL( afile, { |e| cIndexs += e +";" }, 2 )
        cIndexs := LEFT( cIndexs, LEN( cIndexs ) -1 )
       
   ENDIF

RETURN( AdsDDAddTable( left( afile[ 1 ], at(".", afile[1] )-1 ), ;
                cPath + aFile[ 1 ], ;
                cIndexs ) )

//--------------------------------------------------------------------------------------------------------
//You may use this function to assign certain properties to all tables.  
//The only table property I'm assigning is the auto_create property.
//Many others could also be applied.  Look at ads.h include file for
//more constants.
STATIC FUNCTION SetTableProp( aFile )
   LOCAL cFileName

   hb_FNameSplit( afile[ 1 ],, @cFileName )

   AdsDDSetTableProperty( cFileName, ADS_DD_TABLE_AUTO_CREATE, .t. )

//  AdsDDSetTableProperty( cFileName, ADS_DD_TABLE_ENCRYPTION, .t. )

RETURN NIL


*-------------------------------------------------------------------------------------------------------------------------------
STATIC FUNCTION ShowError( cMsg, oErr )
   LOCAL cErr

   cErr := STR( AdsGetLastError() )
   
   ALERT( "Error : " + ALLTRIM( cErr ) + " " + ;
            cMsg + " " + oErr:Subsystem + " " + ;
            STR( oErr:subCode ) + " " + oErr:operation + " " + oErr:description )

   dbCloseAll()
   
RETURN NIL

//-----------------------------------------------------------------------------------------------------
STATIC FUNCTION CreateAndUseFreeTable()
   LOCAL aStruct := { ;
               { "CHARACTER", "C", 25, 0 }, ;
               { "NUMERIC"  , "N",  8, 0 }, ;
               { "DOUBLE"   , "N",  8, 2 }, ;
               { "DATE"     , "D",  8, 0 }, ;
               { "LOGICAL"  , "L",  1, 0 }, ;
               { "MEMO1"    , "M", 10, 0 }, ;
               { "MEMO2"    , "M", 10, 0 }  ;
            }

      DbCreate( "testdbf", aStruct, "DBFCDX", .T., "MYALIAS" )

      Browse()

RETURN NIL
 


Observa que una vez construyes el .exe, para probarlo necesitas enviar el "path" a donde se deben crear las tablas, el dd, y la tabla libre. Por ejemplo: "c:\createdd.exe c:\data\"

Reinaldo.
User avatar
reinaldocrespo
 
Posts: 979
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby George » Thu Jan 29, 2015 11:54 pm

Hola,

Asi lo uso:
FUNCTION ADSOpeningDataBase()
// Para Tablas libre
REQUEST DBFCDX
USE "DB_PARAMS.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS DB_PARAMS
USE "SUMREP1.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS SUMREP1
USE "VERSION.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS VERSION
USE "DEVICES.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS DEVICES

// Para el dictionario de datos ADS
AdsConnect60( cPathDataDict, 2, "UserName", "Password", 1, @hConn) // ADS = 2 CLIENT/SERVER DATABASE
USE "USERS" NEW SHARED ALIAS USERS
USE "CUSTOMER" NEW SHARED ALIAS CUSTOMER


Saludos,

George
George
 
Posts: 726
Joined: Tue Oct 18, 2005 6:49 pm

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby Yessica » Fri Jan 30, 2015 1:45 am

George wrote:Hola,

Asi lo uso:
FUNCTION ADSOpeningDataBase()
// Para Tablas libre
REQUEST DBFCDX
USE "DB_PARAMS.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS DB_PARAMS
USE "SUMREP1.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS SUMREP1
USE "VERSION.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS VERSION
USE "DEVICES.DBF" VIA "DBFCDX" NEW EXCLUSIVE ALIAS DEVICES

// Para el dictionario de datos ADS
AdsConnect60( cPathDataDict, 2, "UserName", "Password", 1, @hConn) // ADS = 2 CLIENT/SERVER DATABASE
USE "USERS" NEW SHARED ALIAS USERS
USE "CUSTOMER" NEW SHARED ALIAS CUSTOMER


Saludos,

George


Gracias por contestar una pregunta mas. Puedes usarlas al mismo tiempo ambas ?, Libres y en el DD?

Como pones en codigo fuente la siguiente instruccion:
EXECUTE PROCEDURE sp_PackTable('C:\Data\Custtemp.adt')
Porque en el Arquitect, es asi tal cual lo escribi, pero como lo hago para meter esa instruccion a mi prg?

Ojalá y puedas ayudarme.
Yessica
 
Posts: 78
Joined: Thu May 28, 2009 6:58 pm

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby Yessica » Fri Jan 30, 2015 3:21 pm

reinaldocrespo wrote:Abajo te incluyo código que acabo de probar y funciona perfectamente. Crea varias tablas de varios tipos diferentes (DBFNTX, DBFVFP, ADSADT) usando ADS RDD. Luego crea un dd y añade las 3 tablas al DD. Luego se conecta al DD y luego crea una 4ta tabla usando DBFCDX para entonces abrirla como un free table.

He probado usando xharbour de SVN + Borland c 5.82. El código es independiente de GUI, o sea, nada tiene que ver con fw y es código muy sencillo y corto. ¿Te funciona igual a ti?

Code: Select all  Expand view  RUN
//This console mode app shows how to create a few tables of different types.
//How to create an Advantage Data Dictionary and add the newly created
//tables the data dictionary file.
//I'm using various table types using ADS RDDs for DBF/NTX, DBF/VFP, ADT/ADI
//
//After that it atttempts to connect to the dd, create a new table and then
//open the new table as a free table.
//In short- it creates tables and dd, opens dd bound tables and free tables
//at the same time.
//
//The sample code uses pure rdds + some ACE calls.
//No GUI dependency as only a console mode app is being built, which should
//build just the same under Windows as well as under Linux.
//
#include "ads.ch"

#xcommand DEFAULT <uVar1> := <uVal1> ;
                [, <uVarN> := <uValN> ] => ;
                  <uVar1> := iif( <uVar1> == nil, <uVal1>, <uVar1> ) ;;
                [ <uVarN> := iif( <uVarN> == nil, <uValN>, <uVarN> ); ]

REQUEST DBFCDX
REQUEST ADS          //Make sure rddads gets linked to our app.
REQUEST hb_gt_win    //needed for console mode app.

//Static variable cPath will contain the path where tables and DD will be created.
//After connecting to an existing DD, there is no need to use the file path as the
//DD saves the relative path of each table as part of its metadata.
STATIC cPath

*-----------------------------------------------------------------------------------------------------
FUNCTION Main()

   LOCAL afiles

   SetMode(25,80)      //25 lines by 80 columns console

   rddRegister( "ADS", 1 )
   
   rddSetDefault( "ADS" )

   adsSetServerType( ADS_LOCAL_SERVER )

   //NON-compatible locking mode.  If other NON-ADS clients are going to
   //to work on the same tables, then make sure to use compatible locking mode.
   AdsLocking( .t. )  
   AdsRightsCheck( 0 )
   
   //Path for existing .dbf tables maybe sent as a parameter
   //on the command line.  This is just one idea.  It could be saved
   //on a .ini file or hardcoded.
   cPath   := hb_ArgV( 1 )
   
   //in case no path was sent on command line, assume current path.
   DEFAULT cpath := ""  
   
   //sanitize cPath contents.
   //IF !EMPTY( cPath ) .and. RIGHT( cPath, 1 ) != ''    ;cPath += ''  ;ENDIF
   
   //if you need to create some new tables other than existing tables look
   //at function CreateTables().  CreateTables shows how to create
   //adt tables, vfp tables, and dbf-ntx tables.
   //
   //CreateTables() creates an array with table names and structure for each.
   //It then creates the tables.  After being created they will be added to a newly
   //created data dictionary using function CreateDictionary().
   //If your .dbf tables are alreay present, then you won't need to execute
   //CreateTables, instead you could simply execute a Directory() harbour
   //function to retreive existing table names.  By storing the names of these tables
   //into afiles variable, you can then execute CreateDictionary() in exactly the same
   //manner.
   afiles := CreateTables()
   
   IF !EMPTY( afiles )     ;CreateDictionary( afiles )     ;ENDIF

   //now that we have a dd created, we will attempt to connect to it and
   //use the tables as dd bound tables.

    IF !AdsConnect60( cPath + "test_dd.add", ADS_LOCAL_SERVER, "user1", "password1" )
   
       Alert( "Cannot connect to test_dd" + Str( AdsGetLastError() ) )
      QUIT

   ENDIF


   //Now we create a dbfcdx table to be used as a free table.
   CreateAndUseFreeTable()

       
RETURN NIL

//--------------------------------------------------------------------------------------
//function CreateTables() will create three tables using stnd harbour func dbCreate
//Each table structure is saved on an array following the std returned by dbStruct()
//Each element on the array is an array describing the field.  Thus, the array
//for a table with 3 fields would look like this:
//aStructure := { { cFieldName1, cFieldType1, nFldWidth, nDecimals },;
//                { cFieldName2, cFieldType2, nFldWidth, nDecimals },;
//                { cFieldName3, cFieldType3, nFldWidth, nDecimals } }
//
STATIC FUNCTION CreateTables()
   LOCAL cAlias := "MyAlias"
   LOCAL afiles := {}
   LOCAL cFileName, e

    //---------------------- customers.adt --------------------------------------------
   LOCAL aStruc := { { "cust_id"    , "C", 10, 0 },;
                { "Sequence"        , "AutoInc", 07, 0 },;      //ADT extended field type autoincrement
                { "customer_name"   , "C", 25, 0 },;
                { "Start_date"      , "TimeStamp", 01, 0 },;    //ADT extended field type
                { "Notes"           , "M", 10, 0 } }
                       
    AdsSetFileType( ADS_ADT )  

    TRY    
        dbCreate( ( cFileName := cPath + "customers.adt" ), aStruc,, .t., cAlias )

        ( cAlias )->( OrdCreate( cPath + "customers", "cust_id", "cust_id" ) )
        ( cAlias )->( OrdCreate( cPath + "customers", "Start_date", "Start_date" ) )
        ( cAlias )->( dbclosearea() )

        AADD( afiles, { cFileName, "customers.adi" } )

   
    //------------------------ sales.dbf -------------------------------------------------
        aStruc := { { "cust_id" , "C", 10, 0 },;
                { "invoice"     , "C", 15, 0 },;
                { "s_date"      , "TimeStamp", 01, 0 },;    //VFP extended field type
                { "item_id"     , "C", 15, 0 },;
                { "Units"       , "N", 03, 0 },;
                { "Price"       , "Money", 09, 2 },;        //VFP extended field type
                { "Notes"       , "M", 10, 0 } }
                   
        AdsSetFileType( ADS_VFP )

        dbCreate( ( cFileName := cPath + "sales.dbf" ), aStruc,, .t., cAlias )

        ( cAlias )->( OrdCreate( cPath + "sales", "invoice", "invoice" ) )
        ( cAlias )->( OrdCreate( cPath + "sales", "cust_id", "cust_id" ) )
        ( cAlias )->( dbclosearea() )

        aadd( afiles, { cFileName, "sales.cdx" } )



    //------------------------ items.dbf -------------------------------------------------
        aStruc := { { "item_id"     , "C", 15, 0 },;
                { "Desc"    , "C", 25, 0 },;
                { "Price"   , "N", 07, 2 } }
                   
        AdsSetFileType( ADS_NTX )

        dbCreate( ( cFileName := cPath + "items.dbf" ), aStruc,, .t., cAlias )
        ( cAlias )->( OrdCreate( cPath + "itm_id",, "item_id" ) )
        ( cAlias )->( OrdCreate( cPath + "itm_desc",, "Desc" ) )
        ( cAlias )->( dbclosearea() )

        aadd( afiles, { cFileName, "itm_id.ntx;itm_desc.ntx" } )

    CATCH e
   
        ShowError( cFileName, e )
        afiles := {}
       
    END

RETURN afiles

/*--------------------------------------------------------------------------------------------------------
CreateDictionary creates an Advantage Data Dictionary based on already existing tables
--------------------------------------------------------------------------------------------------------*/

STATIC FUNCTION CreateDictionary( afiles )
   LOCAL cExt AS CHARACTER := ""
   LOCAL cDD := cPath + "test_dd.add"

   IF !ADSDDCREATE( cDD,, "Sample data dictinoary" )

      ALERT( "AdsCreate() of " + cDD + " failed. Error:" + Str( AdsGetLastError() ) )
      RETURN NIL

   ENDIF
   
   //Calling ACE function AdsDDSetDatabaseProperty()
   AdsDDSetDatabaseProperty( ADS_DD_ENABLE_INTERNET, .t. )
   AdsDDSetDatabaseProperty( ADS_DD_INTERNET_SECURITY_LEVEL, ADS_DD_LEVEL_2 )
   AdsDDSetDatabaseProperty( ADS_DD_DEFAULT_TABLE_PATH, cPath )
   AdsDDSetDatabaseProperty( ADS_DD_LOG_IN_REQUIRED, .t. )


   //ACE Function ADsDDCreateUser() creates a dd user.
   //When a new dd is created user ADSSYS is auto-created as the dd administrator
   //it is a good idea to create other users to limit access and permissions.
   //
   AdsDDCreateUser( , "user1", "password1", "User named userd1 with password password1" )
   AdsDDCreateUser( , "user2", "password2", "Description of user2" )
   AdsDDCreateUser( , "user3", "password3", "Optional description of user3" )

   //array aFiles contains the names of the tables to be added to the newly created
   //data dictionary.  
   //element 1 on the array is the table name,
   //element 2 on the array is the index file name.
   //Since .dbf tables could be vfp, cdx, or ntx type tables,
   //we are using the extension on the index file name to "guess" the .dbf
   //file type.  If this is already known beforehand, then the code below
   //could be much simpler.  I'm using AEVAL only because I love it albeit it is
   //more cryptic.  The same can be done on a FOR EACH (FOR/REPEAT/WHILE) loop
    AEVAL( aFiles, ;
        { |e| hb_FNameSplit( iif( len( e ) > 1, e[ 2 ], e[ 1 ] ), , , @cExt ), ;
            AdsSetFiletype( iif( lower( cExt ) $ ".adt,.adi", ADS_ADT, ;
                        iif( lower( cExt ) == ".ntx", ADS_NTX, ADS_VFP ) ) ),;
            addfiletoDD( e, cPath ), ;
            SetTableProp( e ), ;
            QOut( "Adding table to DD", ;
                        e[ 1 ], ;
                        AdsSetFileType(), ;
                        cExt, ;
                        ADSGetLastError() ) } )

   //assign the password "password" to the ADSSYS user of the DD.  Just as default.
    AdsDDSetDatabaseProperty( ADS_DD_ADMIN_PASSWORD, "password" )

    Wait

return Nil

//-------------------------------------------------------------------------------------------------------
//This is the code that adds the table to the DD.
STATIC FUNCTION AddFiletoDD( aFile, cPath )
   LOCAL cIndexs := ""

   IF LEN( afile ) > 1 .AND. LEFT( afile[ 2 ], 1 ) <> "."
   
        AEVAL( afile, { |e| cIndexs += e +";" }, 2 )
        cIndexs := LEFT( cIndexs, LEN( cIndexs ) -1 )
       
   ENDIF

RETURN( AdsDDAddTable( left( afile[ 1 ], at(".", afile[1] )-1 ), ;
                cPath + aFile[ 1 ], ;
                cIndexs ) )

//--------------------------------------------------------------------------------------------------------
//You may use this function to assign certain properties to all tables.  
//The only table property I'm assigning is the auto_create property.
//Many others could also be applied.  Look at ads.h include file for
//more constants.
STATIC FUNCTION SetTableProp( aFile )
   LOCAL cFileName

   hb_FNameSplit( afile[ 1 ],, @cFileName )

   AdsDDSetTableProperty( cFileName, ADS_DD_TABLE_AUTO_CREATE, .t. )

//  AdsDDSetTableProperty( cFileName, ADS_DD_TABLE_ENCRYPTION, .t. )

RETURN NIL


*-------------------------------------------------------------------------------------------------------------------------------
STATIC FUNCTION ShowError( cMsg, oErr )
   LOCAL cErr

   cErr := STR( AdsGetLastError() )
   
   ALERT( "Error : " + ALLTRIM( cErr ) + " " + ;
            cMsg + " " + oErr:Subsystem + " " + ;
            STR( oErr:subCode ) + " " + oErr:operation + " " + oErr:description )

   dbCloseAll()
   
RETURN NIL

//-----------------------------------------------------------------------------------------------------
STATIC FUNCTION CreateAndUseFreeTable()
   LOCAL aStruct := { ;
               { "CHARACTER", "C", 25, 0 }, ;
               { "NUMERIC"  , "N",  8, 0 }, ;
               { "DOUBLE"   , "N",  8, 2 }, ;
               { "DATE"     , "D",  8, 0 }, ;
               { "LOGICAL"  , "L",  1, 0 }, ;
               { "MEMO1"    , "M", 10, 0 }, ;
               { "MEMO2"    , "M", 10, 0 }  ;
            }

      DbCreate( "testdbf", aStruct, "DBFCDX", .T., "MYALIAS" )

      Browse()

RETURN NIL
 


Observa que una vez construyes el .exe, para probarlo necesitas enviar el "path" a donde se deben crear las tablas, el dd, y la tabla libre. Por ejemplo: "c:\createdd.exe c:\data\"

Reinaldo.


Buen dia Reinaldo:

Me doy cuenta que creaste una tabla DBF, aun cuando yo uso ADT. No hay problema. Probaste no creándola?, es decir una vez establecida la conexión al diccionario, abrir una tabla ya existente, "no creándola", pues al parecer cuando se crea la toma como temporal y yo necesito abrir la que ya existe no crearla en el momento.

Con un simple:

USE "C:\CARPETA\tabla.adt" SHARED

Yo abria las tablas libres, usando al mismo tiempo las que están en el diccionario.

Puedes probar con una tabla libre ya existente, abrirla y abrir tablas al mismo tiempo que estén en el diccionario??
Yessica
 
Posts: 78
Joined: Thu May 28, 2009 6:58 pm

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby reinaldocrespo » Fri Jan 30, 2015 3:46 pm

No veo que haga alguna diferencia y de hecho tu misma pudieras hacer la prueba con el mismo código que te he escrito.

Abajo te incluyo nuevo código que hace la prueba tal como la deseas. Observa que he removido código que crean tablas y el dd y he añadido una sola función de 2 lineas para abrir y ver una tabla libre ya existente después de estar conectados al ADS DD. La tabla existente y el DD son producto del código que anteriormente tienes en este mismo hilo:

Code: Select all  Expand view  RUN
//This console mode app shows how to create a few tables of different types.
//How to create an Advantage Data Dictionary and add the newly created
//tables the data dictionary file.
//I'm using various table types using ADS RDDs for DBF/NTX, DBF/VFP, ADT/ADI
//
//After that it atttempts to connect to the dd, create a new table and then
//open the new table as a free table.
//In short- it creates tables and dd, opens dd bound tables and free tables
//at the same time.
//
//The sample code uses pure rdds + some ACE calls.
//No GUI dependency as only a console mode app is being built, which should
//build just the same under Windows as well as under Linux.
//
#include "ads.ch"

#xcommand DEFAULT <uVar1> := <uVal1> ;
                [, <uVarN> := <uValN> ] => ;
                  <uVar1> := iif( <uVar1> == nil, <uVal1>, <uVar1> ) ;;
                [ <uVarN> := iif( <uVarN> == nil, <uValN>, <uVarN> ); ]

REQUEST DBFCDX
REQUEST ADS          //Make sure rddads gets linked to our app.
REQUEST hb_gt_win    //needed for console mode app.

//Static variable cPath will contain the path where tables and DD will be created.
//After connecting to an existing DD, there is no need to use the file path as the
//DD saves the relative path of each table as part of its metadata.
STATIC cPath

*-----------------------------------------------------------------------------------------------------
FUNCTION Main()

   LOCAL afiles

   SetMode(25,80)      //25 lines by 80 columns console

   rddRegister( "ADS", 1 )
   
   rddSetDefault( "ADS" )

   adsSetServerType( ADS_LOCAL_SERVER )

   //NON-compatible locking mode.  If other NON-ADS clients are going to
   //to work on the same tables, then make sure to use compatible locking mode.
   AdsLocking( .t. )  
    AdsRightsCheck( 0 )
   
   //Path for existing .dbf tables maybe sent as a parameter
   //on the command line.  This is just one idea.  It could be saved
   //on a .ini file or hardcoded.
   cPath   := hb_ArgV( 1 )
   
   //in case no path was sent on command line, assume current path.
   DEFAULT cpath := ""  
   
    IF !AdsConnect60( cPath + "test_dd.add", ADS_LOCAL_SERVER, "user1", "password1" )
   
       Alert( "Cannot connect to test_dd" + Str( AdsGetLastError() ) )
      QUIT

   ENDIF

   //Now we create a dbfcdx table to be used as a free table.
   //CreateAndUseFreeTable()
   OpenExistingFreeTable()

       
RETURN NIL


//-----------------------------------------------------------------------------------------------------
STATIC FUNCTION OpenExistingFreeTable()

   DbUseArea( .T., "DBFCDX", "testdbf", "TestAlias", .T., .F. )
   Browse()
   
RETURN NIL


//-----------------------------------------------------------------------------------------------------
 



Igualmente funciona perfectamente.

Te animo a que escribas un ejemplo reducido, o sea, tan reducido como sea posible, que recree el problema que describes. Seguramente así te podamos ayudar mejor. No creo que exista problema alguno con abrir tablas libres mientras estás conectado a un dd, de otra manera mucha gente estaría reportando ese problema y si te fijas en el foro de Advantage no existe mención de problema tal.


Saludos,


Reinaldo.
User avatar
reinaldocrespo
 
Posts: 979
Joined: Thu Nov 17, 2005 5:49 pm
Location: Fort Lauderdale, FL

Re: Uso de Diccionario de Datos ADS y tablas libres

Postby Yessica » Fri Jan 30, 2015 4:16 pm

reinaldocrespo wrote:No veo que haga alguna diferencia y de hecho tu misma pudieras hacer la prueba con el mismo código que te he escrito.

Abajo te incluyo nuevo código que hace la prueba tal como la deseas. Observa que he removido código que crean tablas y el dd y he añadido una sola función de 2 lineas para abrir y ver una tabla libre ya existente después de estar conectados al ADS DD. La tabla existente y el DD son producto del código que anteriormente tienes en este mismo hilo:

Code: Select all  Expand view  RUN
//This console mode app shows how to create a few tables of different types.
//How to create an Advantage Data Dictionary and add the newly created
//tables the data dictionary file.
//I'm using various table types using ADS RDDs for DBF/NTX, DBF/VFP, ADT/ADI
//
//After that it atttempts to connect to the dd, create a new table and then
//open the new table as a free table.
//In short- it creates tables and dd, opens dd bound tables and free tables
//at the same time.
//
//The sample code uses pure rdds + some ACE calls.
//No GUI dependency as only a console mode app is being built, which should
//build just the same under Windows as well as under Linux.
//
#include "ads.ch"

#xcommand DEFAULT <uVar1> := <uVal1> ;
                [, <uVarN> := <uValN> ] => ;
                  <uVar1> := iif( <uVar1> == nil, <uVal1>, <uVar1> ) ;;
                [ <uVarN> := iif( <uVarN> == nil, <uValN>, <uVarN> ); ]

REQUEST DBFCDX
REQUEST ADS          //Make sure rddads gets linked to our app.
REQUEST hb_gt_win    //needed for console mode app.

//Static variable cPath will contain the path where tables and DD will be created.
//After connecting to an existing DD, there is no need to use the file path as the
//DD saves the relative path of each table as part of its metadata.
STATIC cPath

*-----------------------------------------------------------------------------------------------------
FUNCTION Main()

   LOCAL afiles

   SetMode(25,80)      //25 lines by 80 columns console

   rddRegister( "ADS", 1 )
   
   rddSetDefault( "ADS" )

   adsSetServerType( ADS_LOCAL_SERVER )

   //NON-compatible locking mode.  If other NON-ADS clients are going to
   //to work on the same tables, then make sure to use compatible locking mode.
   AdsLocking( .t. )  
    AdsRightsCheck( 0 )
   
   //Path for existing .dbf tables maybe sent as a parameter
   //on the command line.  This is just one idea.  It could be saved
   //on a .ini file or hardcoded.
   cPath   := hb_ArgV( 1 )
   
   //in case no path was sent on command line, assume current path.
   DEFAULT cpath := ""  
   
    IF !AdsConnect60( cPath + "test_dd.add", ADS_LOCAL_SERVER, "user1", "password1" )
   
       Alert( "Cannot connect to test_dd" + Str( AdsGetLastError() ) )
      QUIT

   ENDIF

   //Now we create a dbfcdx table to be used as a free table.
   //CreateAndUseFreeTable()
   OpenExistingFreeTable()

       
RETURN NIL


//-----------------------------------------------------------------------------------------------------
STATIC FUNCTION OpenExistingFreeTable()

   DbUseArea( .T., "DBFCDX", "testdbf", "TestAlias", .T., .F. )
   Browse()
   
RETURN NIL


//-----------------------------------------------------------------------------------------------------
 



Igualmente funciona perfectamente.

Te animo a que escribas un ejemplo reducido, o sea, tan reducido como sea posible, que recree el problema que describes. Seguramente así te podamos ayudar mejor. No creo que exista problema alguno con abrir tablas libres mientras estás conectado a un dd, de otra manera mucha gente estaría reportando ese problema y si te fijas en el foro de Advantage no existe mención de problema tal.


Saludos,


Reinaldo.


Estoy usando lo que me mandaste pero me marca un error aquí:

DbUseArea( .T., "?????", "miADT", "TadtAlias", .T., .F. ) // en los signos de interrogación es el tipo de tabla yo Uso ADT, como seria ahi entonces, porque yo le pongo ADTADI y marca error.

Browse()
Yessica
 
Posts: 78
Joined: Thu May 28, 2009 6:58 pm

Next

Return to FiveWin para Harbour/xHarbour

Who is online

Users browsing this forum: No registered users and 20 guests