Cobol Foro

Cobol Foro (https://www.cobolforo.es/index.php)
-   Cocina PowerCOBOL (https://www.cobolforo.es/forumdisplay.php?f=24)
-   -   [PowerCOBOL] SQlite3 con PowerCobol (https://www.cobolforo.es/showthread.php?t=1642)

fastpho 28 de abril de 2023 13:22

SQlite3 con PowerCobol
 
Permite integrar el motor de base de datos de SQlite con nuestras aplicaciones.
En mi caso es para poder interactuar con una aplicacion que hice para Android
y poder leer la informacion de la BD y evitar utilizar archivos con formato .CSV
como interface.
Su implementacion es muy sencilla descargar Binarios precompilados
para Windows para su version 32 bits (sqlite3.dll) no hace falta registrarla.

1 - Copiar Sqlite3.dll en la carpeta del proyecto
2 - Agregar la funciones de la libreria en el Archivo COBOL85
3 - Luego llamar a esas funciones via call
4 - Informacion de las funciones en : https://sqlite.org/c3ref/funclist.html

Ejemplo para abrir , crear , insertar , actualizar un registro y cerrar

Declaracion Variables
Código COBOL:
  1.  01  BD-HANDLE                      PIC 9(9) COMP-5  IS GLOBAL. *>Handle de la BD
  2.  01  BD-FILE-NAME                   PIC X(50)        IS GLOBAL. *>Nombre de la BD
  3.  01  BD-SQL-QUERY                   PIC X(256)       IS GLOBAL. *>string sql (Create , Insert , Delete , Update , Select)
  4.  01  BD-SQL-STRING-LENGHT           PIC S9(9) COMP-5 IS GLOBAL.
  5.  01  BD-HANDLE-STMT                 PIC 9(9) COMP-5  IS GLOBAL.  *>Puntero Statement
  6.  01  BD-STMT-PTR REDEFINES BD-HANDLE-STMT POINTER    IS GLOBAL.  *>Redefines del Puntero Statement
  7.  
  8.  01  BD-INT-POINTER                 POINTER          IS GLOBAL.
  9.  01  BD-INT                         PIC 9(9) COMP-5  IS GLOBAL. *> INTEGER
  10.  01  BD-DOB                         PIC 9(9) COMP-5  IS GLOBAL. *> DOUBLE
  11.  
  12.  01  BD-TEXT-POINTER                POINTER          IS GLOBAL.
  13.  01  BD-TEXT                        PIC X(256)       IS GLOBAL. *> TEXT
  14.  01  BD-SQL-ERROR                   POINTER          IS GLOBAL.
  15.  
  16.  
  17.  01  BD-FILA-ID                     PIC 9(9) COMP-5  IS GLOBAL.
  18.  01  BD-COLUMNA-CANTIDAD            PIC 9(9) COMP-5  IS GLOBAL.
  19.  01  BD-COLUMNA-NUMERO              PIC 9(9) COMP-5  IS GLOBAL.
  20.  01  BD-COLUMNA-NOMBRE              PIC X(256)       IS GLOBAL.
  21.  01  BD-COLUMNA-POINTER             POINTER          IS GLOBAL.
  22.  
  23.  
  24. * Estado de la Base de Datos
  25.  01  BD-STATUS                      PIC 9(9) COMP-5  IS GLOBAL.
  26. *>Estado de la BD
  27.  01  ESTADOS-BD IS GLOBAL.
  28.      03 SQLITE_OK       PIC 9(9) COMP-5  VALUE 0.   *> /* Successful result */
  29.      03 SQLITE_ERROR    PIC 9(9) COMP-5  VALUE 1.   *> /* Generic error */
  30.      03 SQLITE_BUSY     PIC 9(9) COMP-5  VALUE 5.   *> /* The database file is locked */
  31.      03 SQLITE_LOCKED   PIC 9(9) COMP-5  VALUE 6.   *> /*  A table in the database is locked */
  32.      03 SQLITE_READONLY PIC 9(9) COMP-5  VALUE 8.   *> /*  Attempt to write a readonly database */
  33.      03 SQLITE_EMPTY    PIC 9(9) COMP-5  VALUE 16.  *> /*  Attempt to write a readonly database */
  34.      
  35.      
  36.      03 SQLITE_MISUSE   PIC 9(9) COMP-5  VALUE 21.  *> /* Library used incorrectly */
  37.      03 SQLITE_WARNING  PIC 9(9) COMP-5  VALUE 28.  *> /* unusual and possibly ill-advised operation is taking place.*/
  38.      
  39.      03 SQLITE-ROW      PIC 9(9) COMP-5  VALUE 100. *> /* sqlite3_step() has another row ready */
  40.      03 SQLITE-DONE     PIC 9(9) COMP-5  VALUE 101. *> /* sqlite3_step() has finished executing */
  41. * Tipos de Datos sqlite    
  42.  01  BD-COLUMNA-TIPO       PIC 9(4) COMP-5 IS GLOBAL.
  43.       88  SQL-INTEGER        VALUE 1. *>
  44.       88  SQL-REAL           VALUE 2. *>  
  45.       88  SQL-TEXT           VALUE 3. *>
  46.       88  SQL-BLOB           VALUE 4. *>
  47.       88  SQL-NULL           VALUE 5. *>
  48.      
  49.  
  50.  01 FECHA-CONVERTIR       PIC 9(8)         IS GLOBAL. *> AAAAMMDD a Convertir
  51.  01 FECHA-CONVERTIDA-UNIX PIC 9(13)        IS GLOBAL. *> Fecha con formato unix
  52.  01 FECHA-UNIX1970        PIC S9(9) COMP-5 IS GLOBAL. *> desde AAAAMMDDD 19700101
  53.  01 FECHA-INT             PIC S9(9) COMP-5 IS GLOBAL.
  54.  01 FECHA-AMD             PIC 9(8)         IS GLOBAL.
  55.  01 FECHA-AMD-ED          PIC XXXX/XX/XX   IS GLOBAL.
  56.  
  57.  01 NULO                           PIC 9(9)  COMP-5 VALUE 0 IS GLOBAL.    *> NULO
  58.  
  59.  *>[url]https://sqlite.org/cintro.html[/url]
  60. *>Funciones de la libreria sqlit3.dll
  61. *>[url]https://sqlite.org/c3ref/funclist.html[/url]
  62. *>Funciones Declaradas en el archivo COBOL85.CBR
  63. *>Fecha 17-04-2023
  64.  01  FUNCIONES-SQLITE3-LIB          PIC X(50)        IS GLOBAL.
  65. *> sqlite3-connection functions
  66.     *>  sqlite3_libversion (OUT <text>)                                                  *> Devuelve la versión de sqlite a través del parámetro OUT. OK probado
  67.     *>  sqlite3_libversion_number (OUT <int>                   )                         *> Devuelve el número de versión como un int  OK probado
  68.     *>  sqlite3_open       (<nombre de archivo>, OUT <controlador de la base de datos>). *> Esto abre un archivo de base de datos SQLite , nueva o existente como se especifica en el argumento de nombre de archivo.OK probado
  69.     *>  sqlite3_close       (<db-handle>)(<identificador de la base de datos>)           *> Destructor de la interface , cierra la BD OK probado
  70.     *>  sqlite3_exec       (<gestor-bd>,<cadena-sql>)                                    *> Es una envoltura  sqlite3_prepare_v2(), sqlite3_step() y sqlite3_finalize() OK probado
  71.     *>  sqlite3_errmsg     (<db-handle>, OUT <mensaje de error)                          *> Devuelve texto en inglés como un parámetro OUT que describe el último error en la conexión. OK probado
  72.  
  73. *> sqlit3-statement functions    
  74.   *> sqlite3_prepare_v2  *>Constructor OK probado
  75.   *> sqlite3_finalize    *>Destructor  OK probado
  76.      *> Pass
  77.         *> sqlite3_step         int sqlite3_step(sqlite3_stmt*);  OK probado
  78.         *> sqlite3_reset        int sqlite3_reset(sqlite3_stmt *pStmt); OK probado
  79.         *> sqlite3_finalize     int sqlite3_finalize(sqlite3_stmt *pStmt); OK probado
  80.        
  81.       *> Statement column access (0-base indices)
  82.         *> sqlite3_column_count    int sqlite3_column_count(sqlite3_stmt *pStmt);   OK probado
  83.         *> sqlite3_column_type     int sqlite3_column_type(sqlite3_stmt*, int iCol);  OK probado
  84.         *> sqlite3_column_name     const char *sqlite3_column_name(sqlite3_stmt*, int N); OK probado
  85.      *> Statement column type
  86.         *> sqlite3_column_int      int sqlite3_column_int(sqlite3_stmt*, int iCol);  OK probado
  87.         *> sqlite3_column_text     const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);   OK probado
  88.         *> sqlite3_column_double   double sqlite3_column_double(sqlite3_stmt*, int iCol);   OK probado
  89.         *> sqlite3_column_blob     no implementado
  90.  

Abrir BD

Código COBOL:
  1. *------------------------------------------------------------------    
  2. *>sqlite3_open
  3. *    DISPLAY "------------".
  4. *    DISPLAY "sqlite3_open".
  5.  
  6.      MOVE SPACES                 TO FUNCIONES-SQLITE3-LIB.
  7.      MOVE "sqlite3_open"         TO FUNCIONES-SQLITE3-LIB.    
  8.      MOVE "datos.db"  & X"00"    TO BD-FILE-NAME.
  9.      
  10.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  11.               USING BY REFERENCE BD-FILE-NAME
  12.                     BY REFERENCE BD-HANDLE
  13.              returning  BD-STATUS
  14.  
  15.      end-call.
  16.      IF BD-STATUS  NOT = SQLITE_OK THEN
  17.         CALL "BD-ERROR"
  18.      ELSE
  19.         MOVE  "OK" TO "Caption" OF CmStatic2
  20.      END-IF.    

Crear BD

Código COBOL:
  1. *------------------------------------------------------------------    
  2. *>sqlite3_exec
  3. *    DISPLAY "------------".
  4. *    DISPLAY "sqlite3_exec".
  5. *    DISPLAY "CREATE".
  6.      MOVE SPACES                 TO BD-SQL-QUERY.
  7.      MOVE SPACES                 TO FUNCIONES-SQLITE3-LIB.
  8.      MOVE "sqlite3_exec"         TO FUNCIONES-SQLITE3-LIB.    
  9.      MOVE "CREATE TABLE usuarios (id INTEGER PRIMARY KEY AUTOINCREMENT  , nombre TEXT , edad INTEGER )" & X"00" TO BD-SQL-QUERY.
  10.  
  11.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  12.               USING
  13.                     BY VALUE   BD-HANDLE
  14.                     BY CONTENT BD-SQL-QUERY
  15.               BY VALUE 0
  16.               BY VALUE 0
  17.               BY VALUE 0
  18.              returning  BD-STATUS
  19.  
  20.      end-call.
  21.      
  22.  
  23.      IF BD-STATUS NOT = SQLITE_OK THEN
  24.         CALL "BD-ERROR"
  25.      ELSE
  26.         MOVE "OK" TO "Caption" OF CmStatic2
  27.      END-IF.
  28.      

Insertar Registro BD

Código COBOL:
  1. *------------------------------------------------------------------    
  2. *>sqlite3_exec
  3. *    DISPLAY "------------------".
  4. *    DISPLAY "sqlite3_exec".
  5. *    DISPLAY "INSERT".
  6.  
  7.      MOVE SPACES                 TO FUNCIONES-SQLITE3-LIB.
  8.      MOVE "sqlite3_exec"         TO FUNCIONES-SQLITE3-LIB.    
  9.  
  10.      MOVE SPACES                 TO BD-SQL-QUERY.    
  11.      string "INSERT INTO usuarios (nombre , edad ) " delimited by size  
  12.             " VALUES ('Leonardo' , 24 )" delimited by size
  13.             x"00" delimited by size
  14.             into BD-SQL-QUERY
  15.      end-string.
  16.  
  17.      
  18.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  19.               USING
  20.                     BY VALUE   BD-HANDLE
  21.                     BY CONTENT BD-SQL-QUERY
  22.               BY VALUE 0
  23.               BY VALUE 0
  24.               BY VALUE 0
  25.              returning  BD-STATUS
  26.  
  27.      end-call.
  28.      IF BD-STATUS NOT = SQLITE_OK
  29.         CALL "BD-ERROR"
  30.      END-IF.

Actualizar Registro BD
Código COBOL:
  1.  PROCEDURE       DIVISION.
  2. *------------------------------------------------------------------    
  3. *>sqlite3_exec
  4. *    DISPLAY "------------------".
  5. *    DISPLAY "sqlite3_exec".
  6. *    DISPLAY "UPDATE".
  7.  
  8.      MOVE SPACES                 TO FUNCIONES-SQLITE3-LIB.
  9.      MOVE SPACES                 TO BD-SQL-QUERY.        
  10.      MOVE "sqlite3_exec"         TO FUNCIONES-SQLITE3-LIB.
  11.  
  12.  
  13.      string "UPDATE usuarios SET  nombre = 'xxxx' " delimited by size  
  14.             "  WHERE id = 1" delimited by size
  15.             x"00" delimited by size
  16.             into BD-SQL-QUERY
  17.      end-string.
  18.  
  19.      
  20.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  21.               USING
  22.                     BY VALUE   BD-HANDLE
  23.                     BY CONTENT BD-SQL-QUERY
  24.               BY VALUE 0
  25.               BY VALUE 0
  26.               BY VALUE 0
  27.              returning  BD-STATUS
  28.  
  29.      end-call.
  30.      
  31.      IF BD-STATUS NOT = SQLITE_OK
  32.         CALL "BD-ERROR"
  33.      ELSE
  34.         MOVE  "OK" TO "Caption" OF CmStatic2
  35.      END-IF.

Cerar BD
Código COBOL:
  1. *------------------------------------------------------------------    
  2. *>sqlite3_close
  3. *    DISPLAY "------------".
  4. *    DISPLAY "sqlite3_close".
  5.  
  6.      MOVE SPACES                 TO FUNCIONES-SQLITE3-LIB.
  7.      MOVE "sqlite3_close"        TO FUNCIONES-SQLITE3-LIB.    
  8.  
  9.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  10.               USING     BY VALUE BD-HANDLE
  11.              returning  BD-STATUS
  12.  
  13.      end-call.
  14.  
  15.      IF BD-STATUS NOT = SQLITE_OK THEN
  16.         CALL "BD-ERROR"
  17.      ELSE
  18.         MOVE  "OK" TO "Caption" OF CmStatic2        
  19.      END-IF.

Saludos....

Joseg 28 de abril de 2023 15:26

Muito interessante!
Obrigado

Josber 28 de abril de 2023 17:05

Gracias @fastpho, lo único que recomiendo encarecidamente cuando se trabaja con BDs, es que los nombre de las variables que usemos para esas BDs, no contengan el guion medio (-), y sí el guion bajo (_), esto es porque sql, lo puede confundir con el signo de restar (-), el programa puede hacer cosas inesperadas y te vuelves loco buscando el error, (por experiencia propia). Aquí, no parece que se vaya a dar la condición, pero, no es malo, coger esa costumbre. Sólo hay que fijarse en las variables propias de sql, en las que todas son SQLITE_xxxx, y no SQLITE-xxxx

Por lo demás, un excelente aporte

Un salu2.-

fastpho 28 de abril de 2023 17:35

Gracias @Josber , voy a tomar la sugerencia para evitar posibles problemas
Saludos....

luisbago 28 de abril de 2023 20:05

un idx2sqlite seria fabuloso, así se traslada datos sin intermediarios

Joseg 2 de mayo de 2023 12:49

1 Archivos Adjunto(s)
Cita:

Citación del post de fastpho (Mensaje 8885)
Gracias @Josber , voy a tomar la sugerencia para evitar posibles problemas
Saludos....

O mesmo exemplo, mas usando o Sqlit3.Lib. Não necessita de cobol85.cbr

Para criar o .LIB na mesma pasta a onde esta o SQLITE3.DLL
Linha de comandos: lib /DEF:sqlite3.def /OUT:sqlite3.lib /MACHINE:x32 (ou x64)

Joseg 12 de mayo de 2023 12:37

Hola,

Como implementar un loop en PowerCobol?

Ejemplo de lista de todos los registros de "MyTable":
Código SQL:
  1. SELECT * FROM MyTable

Creo que tienes que usar "sqlite3_prepare" y "sqlite3_step", o implementar una "devolución de llamada" (callback),
Código COBOL:
  1. 01 CALLBACK USAGE PROCEDURE-POINTER.

... pero no lo estoy consiguiendo.

Gracias,
Jose

fastpho 12 de mayo de 2023 13:49

Hola @Joseg

Para poder realizar un "select" yo no lo pude hacer por "CALLBACK"
trabajo con la version 5.0 de PowerCobol y no acepta PROCEDURE-POINTER
Entonces para resolverlo hago :

sqlite3_open_v2
sqlite3_prepare_v2

sqlite3_step aca hay que meter el loop si
Código:

SQLITE_ROW
o
Código:

SQLITE_DONE
sqlite3_finalize
sqlite3_close_v2
Saludos...

Joseg 12 de mayo de 2023 18:39

Cita:

Citación del post de fastpho (Mensaje 8902)
Hola @Joseg

Para poder realizar un "select" yo no lo pude hacer por "CALLBACK"
trabajo con la version 5.0 de PowerCobol y no acepta PROCEDURE-POINTER
Entonces para resolverlo hago :

sqlite3_open_v2
sqlite3_prepare_v2

sqlite3_step aca hay que meter el loop si
Código:

SQLITE_ROW
o
Código:

SQLITE_DONE
sqlite3_finalize
sqlite3_close_v2
Saludos...

Muchas gracias :)

Pero, sigue sin funcionar :(

Código COBOL:
  1.  working-storage.
  2.  01  num-bytes                      pic s9(09) COMP-5  IS GLOBAL.
  3.  01  num-columns                    pic s9(09) COMP-5  IS GLOBAL.
  4.  01  pStmt                          usage pointer      IS GLOBAL.
  5.  01  zTail                          pic s9(09) COMP-5  IS GLOBAL.
  6.  
  7.  procedure division.
  8.  
  9.      MOVE "chinook.db"  & X"00"  TO BD-FILE-NAME.
  10.      
  11.      call "sqlite3_open_v2"  & X"00"  WITH  STDCALL  LINKAGE
  12.               USING BY REFERENCE BD-FILE-NAME
  13.                     BY REFERENCE BD-HANDLE
  14.                     BY VALUE 2  *> SQLITE_OPEN_READWRITE
  15.                     BY VALUE 0
  16.              returning  BD-STATUS
  17.  
  18.      end-call.
  19.  
  20.      string "SELECT * from artists WHERE name='Body Count' " delimited by size  
  21.             X"00" delimited by size
  22.             into BD-SQL-QUERY
  23.             WITH POINTER num-bytes.
  24.  
  25.      move zero to zTail
  26.        
  27.      call  "sqlite3_prepare_v2"  & X"00" WITH  STDCALL  LINKAGE
  28.               USING
  29.                     BY VALUE     BD-HANDLE
  30.                     BY CONTENT   BD-SQL-QUERY
  31.                     BY VALUE     num-bytes
  32.                     by reference pStmt
  33.                     by VALUE     zTail
  34.              returning  BD-STATUS
  35.  
  36.      end-call.    
  37.  
  38. *loop
  39.      call "sqlite3_step"  & X"00" WITH  STDCALL  LINKAGE
  40.            using
  41.                by reference pStmt
  42.            returning BD-STATUS
  43.      end-call.
  44.  
  45.     evaluate ESTADOS-BD
  46.        when SQLITE-ROW
  47.            display "SQLITE-ROW"
  48.        when SQLITE-DONE
  49.            display "SQLITE-DONE"
  50.     end-evaluate

¿Qué tiene de malo esta parte del código?
call "sqlite3_step" da el error
SQLITE_MISUSE = 21. *> Library used incorrectly

Powercobol v9
Gracias,
José

fastpho 12 de mayo de 2023 20:13

@Joseg
La funcion sqlite3_step espera el valor por value no por reference seria asi :
Código COBOL:
  1. working-storage.
  2. 01 stmt-handle   PIC 9(9) COMP-5.
  3. 01 redefines stmt-handle.
  4.     05  pStmt usage pointer.


Código COBOL:
  1.      call "sqlite3_step"  & X"00" WITH  STDCALL  LINKAGE
  2.            using  by value stmt-handle
  3.            returning BD-STATUS
  4.      end-call
Saludos...

Josber 13 de mayo de 2023 14:06

Cita:

Citación del post de Joseg (Mensaje 8901)
Hola,

Como implementar un loop en PowerCobol?

Ejemplo de lista de todos los registros de "MyTable":
Código SQL:
  1. SELECT * FROM MyTable

Creo que tienes que usar "sqlite3_prepare" y "sqlite3_step", o implementar una "devolución de llamada" (callback),
Código COBOL:
  1. 01 CALLBACK USAGE PROCEDURE-POINTER.

... pero no lo estoy consiguiendo.

Gracias,
Jose

A ver, yo con SQLLite, no lo sé, porque no lo he usado nunca pero, con SQL_Embebido o SQL normal, lo que se hace para hacer un bucle es, lo primero, crear un cursor y lo segundo es un FETCH a ese cursor, hasta que SQLSTATE, sea "02000", que indica un "fin_de_fichero", por lo que me supongo que en este caso, será muy parecido, es que otra manera de hacerlo, me parece rara

En PWC, con SQL_Embebido, sería algo así:

Código COBOL:
  1. EXEC SQL
  2.         DECLARE  cursor_consulta CURSOR FOR
  3.                        SELECT * FROM CLIENTES
  4.                                    WHERE .....
  5.                                    ORDER BY .....
  6. END-EXEC.
  7.  
  8. INITIALIZE SQLSTATE.
  9.  
  10. EXEC SQL
  11.          OPEN cursor_consulta
  12. END-EXEC.
  13.  
  14. PERFORM WITH NO LIMIT
  15.                EXEC SQL
  16.                        FETCH cursor_consulta
  17.                                  INTO .....
  18.                END-EXEC
  19.                IF SQLSTATE = "02000"
  20.                    EXEC SQL
  21.                             CLOSE cursor_consulta
  22.                    END-EXEC
  23.                    EXIT PERFORM
  24.                END-IF
  25. END-PERFORM.

por lo menos, esa es la manera con la que yo hago un bucle. Lo puedes hacer con un PREPARE también pero, es más lioso, y se usa si tienes que montar la consulta armando un STRING, pero ese es otro tema.

Un salu2.-

Joseg 15 de mayo de 2023 17:08

Cita:

Citación del post de fastpho (Mensaje 8905)
@Joseg
La funcion sqlite3_step espera el valor por value no por reference seria asi :
Código COBOL:
  1. working-storage.
  2. 01 stmt-handle   PIC 9(9) COMP-5.
  3. 01 redefines stmt-handle.
  4.     05  pStmt usage pointer.


Código COBOL:
  1.      call "sqlite3_step"  & X"00" WITH  STDCALL  LINKAGE
  2.            using  by value stmt-handle
  3.            returning BD-STATUS
  4.      end-call
Saludos...


Ok, la función "sqlite3_step" ya está bien.
La función "sqlite3_column_count" también está bien.

La siguiente función siempre devuelve NULL (5)
Código COBOL:
  1.      move 1 to wnum-columns
  2.      call "sqlite3_column_type"  & X"00"  WITH  STDCALL  LINKAGE
  3.                            using
  4.                                    by value stmt-handle
  5.                                    by value wnum-columns
  6.                                    returning BD-COLUMNA-TIPO
  7.      end-call
¿Puede publicar una parte del código que se repite desde una tabla hasta que los datos se puedan consultar en PowerCobol?

Gracias por la ayuda.
Jose

fastpho 15 de mayo de 2023 20:28

Hola @Joseg como recorrer la tabla para saber que tipo valor se puede almacenar por columnas
Código COBOL:
  1. *-------------------------------------------------------------------------      
  2. *>STEP
  3. *-------------------------------------------------------------------------
  4.      DISPLAY "------------------".
  5.      DISPLAY "sqlite3_step      ".
  6.  
  7.      PERFORM DB-STEP.
  8.      evaluate bd-status
  9.      when  SQLITE_ROW  
  10.         perform muestro-cabecera
  11.      when  SQLITE_DONE
  12.         display "termino"
  13.         continue
  14.      when other
  15.         display "error"
  16.         exit program
  17.      end-evaluate.
  18. *-------------------------------------------------------------------------    
  19. *>FINALIZE
  20. *-------------------------------------------------------------------------
  21.      DISPLAY "------------------".
  22.      DISPLAY "sqlite3_finalize".
  23.  
  24.      MOVE SPACES                  TO FUNCIONES-SQLITE3-LIB.
  25.      MOVE "sqlite3_finalize"      TO FUNCIONES-SQLITE3-LIB.    
  26.      
  27.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  28.               USING        BY VALUE   stmt-handle
  29.                            returning  BD-STATUS
  30.  
  31.      end-call.          
  32.    
  33.      IF BD-STATUS NOT = SQLITE_OK then
  34.           DISPLAY "ERROR "
  35.      
  36.      ELSE
  37.           DISPLAY "OK"
  38.      END-IF.
  39. *-------------------------------------------------------------------------    
  40. *>CLOSE_V2
  41. *-------------------------------------------------------------------------
  42.      DISPLAY "------------------".
  43.      DISPLAY "sqlite3_close_v2".
  44.  
  45.      MOVE SPACES                  TO FUNCIONES-SQLITE3-LIB.
  46.      MOVE "sqlite3_close_v2"      TO FUNCIONES-SQLITE3-LIB.    
  47.      
  48.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  49.               USING        BY VALUE   BD-HANDLE
  50.                            returning  BD-STATUS
  51.  
  52.      end-call.          
  53.    
  54.      IF BD-STATUS NOT = SQLITE_OK then
  55.              CALL "BD-ERROR"
  56.           EXIT PROGRAM
  57.      ELSE
  58.           DISPLAY "OK"
  59.      END-IF.
  60.          
  61.      
  62.      EXIT PROGRAM.
  63.  
  64. *-------------------------------------------------------------------------
  65.  MUESTRO-CABECERA.
  66. *-------------------------------------------------------------------------
  67.  
  68.      PERFORM  DB-CANTIDAD-COLUMNAS.
  69.      
  70.      MOVE ZEROS TO BD-COLUMNA-NUMERO.
  71.      PERFORM VARYING BD-COLUMNA-NUMERO  FROM 0 BY 1  UNTIL BD-COLUMNA-NUMERO = BD-COLUMNA-CANTIDAD
  72.     *>sqlite3_column_type
  73. *          DISPLAY "--------------------"
  74. *          DISPLAY "sqlite3_column_type"
  75.  
  76.            MOVE SPACES                  TO FUNCIONES-SQLITE3-LIB
  77.            MOVE "sqlite3_column_type"   TO FUNCIONES-SQLITE3-LIB    
  78.  
  79.            call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  80.              USING        BY VALUE   stmt-handle
  81.                           BY VALUE   BD-COLUMNA-NUMERO *> COMIENZA DE 0 LAS COLUMNAS HASTA sqlite3_column_count - 1
  82.                           returning  BD-COLUMNA-TIPO   *> RETORNA EL TIPO DE COLUMNA
  83.            end-call          
  84.  
  85.           DISPLAY "--------------------"
  86.           DISPLAY " COL NRO : " , BD-COLUMNA-NUMERO  , " es  COLUMNA-TIPO  " , BD-COLUMNA-TIPO  
  87.           DISPLAY "--------------------"
  88.      END-PERFORM.
  89.  
  90. *-------------------------------------------------------------------------
  91.  DB-CANTIDAD-COLUMNAS.
  92. *-------------------------------------------------------------------------
  93. *>sqlite3_column_count
  94. *    DISPLAY "--------------------".
  95. *    DISPLAY "sqlite3_column_count".
  96.  
  97.      MOVE SPACES                  TO FUNCIONES-SQLITE3-LIB.
  98.      MOVE "sqlite3_column_count"  TO FUNCIONES-SQLITE3-LIB.    
  99.  
  100.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  101.               USING        BY VALUE   stmt-handle
  102.                            returning  BD-COLUMNA-CANTIDAD
  103.  
  104.      end-call.          
  105.  
  106. *     DISPLAY "BD-COLUMNA-CANTIDAD : " , BD-COLUMNA-CANTIDAD.
  107.  
  108. *-------------------------------------------------------------------------
  109.  DB-STEP.
  110. *-------------------------------------------------------------------------
  111. *>sqlite3_step
  112. *    DISPLAY "--------------------".
  113. *    DISPLAY "sqlite3_step".
  114.  
  115.      MOVE SPACES TO FUNCIONES-SQLITE3-LIB.
  116.      MOVE "sqlite3_step"          TO FUNCIONES-SQLITE3-LIB.    
  117.  
  118.      call     FUNCIONES-SQLITE3-LIB  WITH STDCALL LINKAGE
  119.               USING        BY VALUE   stmt-handle
  120.                            returning  BD-STATUS
  121.  
  122.      end-call.      
  123. *    DISPLAY BD-STATUS.    
  124.      
  125.  
  126.  
Saludos ...

Joseg 16 de mayo de 2023 17:48

Cita:

Citación del post de fastpho (Mensaje 8910)
Hola @Joseg como recorrer la tabla para saber que tipo valor se puede almacenar por columnas
Código COBOL:
  1. *-------------------------------------------------------------------------      
  2. *>STEP
  3. *-------------------------------------------------------------------------
  4.      DISPLAY "------------------".
  5.      DISPLAY "sqlite3_step      ".
  6.  
  7.      PERFORM DB-STEP.
  8.      evaluate bd-status
  9.      when  SQLITE_ROW  
  10.         perform muestro-cabecera
  11.      when  SQLITE_DONE
  12.         display "termino"
  13.         continue
  14.      when other
  15.         display "error"
  16.         exit program
  17.      end-evaluate.
  18. *-------------------------------------------------------------------------    
  19. *>FINALIZE
  20. *-------------------------------------------------------------------------
  21.      DISPLAY "------------------".
  22.      DISPLAY "sqlite3_finalize".
  23.  
  24.      MOVE SPACES                  TO FUNCIONES-SQLITE3-LIB.
  25.      MOVE "sqlite3_finalize"      TO FUNCIONES-SQLITE3-LIB.    
  26.      
  27.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  28.               USING        BY VALUE   stmt-handle
  29.                            returning  BD-STATUS
  30.  
  31.      end-call.          
  32.    
  33.      IF BD-STATUS NOT = SQLITE_OK then
  34.           DISPLAY "ERROR "
  35.      
  36.      ELSE
  37.           DISPLAY "OK"
  38.      END-IF.
  39. *-------------------------------------------------------------------------    
  40. *>CLOSE_V2
  41. *-------------------------------------------------------------------------
  42.      DISPLAY "------------------".
  43.      DISPLAY "sqlite3_close_v2".
  44.  
  45.      MOVE SPACES                  TO FUNCIONES-SQLITE3-LIB.
  46.      MOVE "sqlite3_close_v2"      TO FUNCIONES-SQLITE3-LIB.    
  47.      
  48.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  49.               USING        BY VALUE   BD-HANDLE
  50.                            returning  BD-STATUS
  51.  
  52.      end-call.          
  53.    
  54.      IF BD-STATUS NOT = SQLITE_OK then
  55.              CALL "BD-ERROR"
  56.           EXIT PROGRAM
  57.      ELSE
  58.           DISPLAY "OK"
  59.      END-IF.
  60.          
  61.      
  62.      EXIT PROGRAM.
  63.  
  64. *-------------------------------------------------------------------------
  65.  MUESTRO-CABECERA.
  66. *-------------------------------------------------------------------------
  67.  
  68.      PERFORM  DB-CANTIDAD-COLUMNAS.
  69.      
  70.      MOVE ZEROS TO BD-COLUMNA-NUMERO.
  71.      PERFORM VARYING BD-COLUMNA-NUMERO  FROM 0 BY 1  UNTIL BD-COLUMNA-NUMERO = BD-COLUMNA-CANTIDAD
  72.     *>sqlite3_column_type
  73. *          DISPLAY "--------------------"
  74. *          DISPLAY "sqlite3_column_type"
  75.  
  76.            MOVE SPACES                  TO FUNCIONES-SQLITE3-LIB
  77.            MOVE "sqlite3_column_type"   TO FUNCIONES-SQLITE3-LIB    
  78.  
  79.            call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  80.              USING        BY VALUE   stmt-handle
  81.                           BY VALUE   BD-COLUMNA-NUMERO *> COMIENZA DE 0 LAS COLUMNAS HASTA sqlite3_column_count - 1
  82.                           returning  BD-COLUMNA-TIPO   *> RETORNA EL TIPO DE COLUMNA
  83.            end-call          
  84.  
  85.           DISPLAY "--------------------"
  86.           DISPLAY " COL NRO : " , BD-COLUMNA-NUMERO  , " es  COLUMNA-TIPO  " , BD-COLUMNA-TIPO  
  87.           DISPLAY "--------------------"
  88.      END-PERFORM.
  89.  
  90. *-------------------------------------------------------------------------
  91.  DB-CANTIDAD-COLUMNAS.
  92. *-------------------------------------------------------------------------
  93. *>sqlite3_column_count
  94. *    DISPLAY "--------------------".
  95. *    DISPLAY "sqlite3_column_count".
  96.  
  97.      MOVE SPACES                  TO FUNCIONES-SQLITE3-LIB.
  98.      MOVE "sqlite3_column_count"  TO FUNCIONES-SQLITE3-LIB.    
  99.  
  100.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  101.               USING        BY VALUE   stmt-handle
  102.                            returning  BD-COLUMNA-CANTIDAD
  103.  
  104.      end-call.          
  105.  
  106. *     DISPLAY "BD-COLUMNA-CANTIDAD : " , BD-COLUMNA-CANTIDAD.
  107.  
  108. *-------------------------------------------------------------------------
  109.  DB-STEP.
  110. *-------------------------------------------------------------------------
  111. *>sqlite3_step
  112. *    DISPLAY "--------------------".
  113. *    DISPLAY "sqlite3_step".
  114.  
  115.      MOVE SPACES TO FUNCIONES-SQLITE3-LIB.
  116.      MOVE "sqlite3_step"          TO FUNCIONES-SQLITE3-LIB.    
  117.  
  118.      call     FUNCIONES-SQLITE3-LIB  WITH STDCALL LINKAGE
  119.               USING        BY VALUE   stmt-handle
  120.                            returning  BD-STATUS
  121.  
  122.      end-call.      
  123. *    DISPLAY BD-STATUS.    
  124.      
  125.  
  126.  
Saludos ...


Muchas gracias. Tu ayuda ha sido muy importante.
Mi ultima duda es como convertir un puntero en texto o una fecha o un campo numerico o incluso un "BLOB",
ser consultable en powercobol.

ejemplo:

Código COBOL:
  1.           evaluate  BD-COLUMNA-TIPO
  2.              when 3
  3.                 call "sqlite3_column_text" & X"00" WITH  STDCALL  LINKAGE
  4.                             using
  5.                                  by value stmt-handle,
  6.                                  by value BD-COLUMNA-NUMERO
  7.                                  returning TEXT-POINTER
  8.                 end-call
  9.           end-evaluate


Saludos
José

fastpho 16 de mayo de 2023 19:59

Hola @Joseg con respecto a los tipos de datos
yo estoy trabajando en Android(B4A) con:

Código COBOL:
  1.       88  SQL_INTEGER         VALUE 1.  
  2.       88  SQL-REAL               VALUE 2.  
  3.       88  SQL_TEXT              VALUE 3.  

*Tema: Tipo dato Entero*

Para pwcobol es un PIC 9(1...13) dependiendo el uso.
Código COBOL:
  1. evaluate  BD-COLUMNA-TIPO
  2.              when 1
  3.                 perform DB-COLUMNA-INT
  4.  end-evaluate
  5.  
  6.  DB-COLUMNA-INT.
  7. *>Columna tipo Integer
  8.      MOVE SPACES               TO FUNCIONES-SQLITE3-LIB.
  9.      MOVE "sqlite3_column_int" TO FUNCIONES-SQLITE3-LIB.
  10.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  11.              USING        BY VALUE   BD-HANDLE-STMT
  12.                           BY VALUE   BD-COLUMNA-NUMERO
  13.                           returning  BD-INT
  14.      end-call.          
  15.     *>DEVUELVE BD-INT.

*Tema : Tipo de dato Fecha*
en Android represento las fechas en ticks(type Long)

Código VB:
  1. DateTime.DateFormat="dd-MM-yyyy"
  2. Dim SomeTime As Long
  3. SomeTime = DateTime.DateParse("16/05/2023")
Para sqlite es un SQL_INTEGER (SomeTime)
Para pwcobol la paso a PIC X(13) (SomeTime)

Código COBOL:
  1. LINKAGE SECTION.
  2.  01  sqlite3-value-text     PIC X(256).
  3.  
  4.  evaluate  BD-COLUMNA-TIPO
  5.              when 3 *>Date Ticks
  6.                perform DB-COLUMNA-TEXT
  7.  end-evaluate
  8.  
  9.  DB-COLUMNA-TEXT.
  10.     *>Columna tipo TEXT
  11.      MOVE SPACES                TO FUNCIONES-SQLITE3-LIB.
  12.      MOVE "sqlite3_column_text" TO FUNCIONES-SQLITE3-LIB.
  13.      MOVE SPACES          TO BD-TEXT.
  14.      call     FUNCIONES-SQLITE3-LIB WITH  STDCALL  LINKAGE
  15.              USING        BY VALUE   BD-HANDLE-STMT
  16.                           BY VALUE   BD-COLUMNA-NUMERO
  17.                           returning  BD-TEXT-POINTER
  18.      end-call.          
  19.      SET ADDRESS OF sqlite3-value-text TO BD-TEXT-POINTER.
  20.      STRING
  21.             sqlite3-value-text delimited by low-value
  22.             into BD-TEXT
  23.      END-STRING.
  24.      SET  BD-TEXT-POINTER TO NULL.
  25.     *>DEVUELVE BD-TEXT.

*Tema : Tipo de dato Real*
Tambien lo trato con sqlite3_column_text y lo muevo a
Código COBOL:
  1.  01 importe-text   pic X(13)
y luego lo convierto a numerico

Código COBOL:
  1.     evaluate  BD-COLUMNA-TIPO
  2.              when 2 *>Real
  3.                perform DB-COLUMNA-TEXT
  4.       end-evaluate

*Tema : Tipo de dato Blob*

No lo he implementado en android
Pero creo que lo mejor es guardar la direccion de la
imagen fisica del archivo de la memoria del celular o
mobil y no la imagen como tal.

*Tema : Tipo de dato Text*

simplemente como text PIC X(1...256)

Espero que te ayude y se entienda.
Saludos...

Joseg 17 de mayo de 2023 16:44

Gracias por la ayuda. Todo está funcionando ahora. :bat::bat::bat:

Abrazo.
José

Nitzer 17 de mayo de 2023 17:56

El problema de todo esto, es la cantidad de código y lo poco explícito que parece para acceder a los datos.
YO ya os dije que utilizo un activex que me hicieron para acceder y ejecutar y es tremendamente sencillo y claro.

Llevo muchos años trabajando practicamente solo con bases de datos y estoy encantado :)

Joseg 18 de mayo de 2023 00:01

Cita:

Citación del post de Nitzer (Mensaje 8914)
El problema de todo esto, es la cantidad de código y lo poco explícito que parece para acceder a los datos.
YO ya os dije que utilizo un activex que me hicieron para acceder y ejecutar y es tremendamente sencillo y claro.

Llevo muchos años trabajando practicamente solo con bases de datos y estoy encantado :)

No encontré ningún OCX con posibilidad de conectarse a la Base de Datos (pero sería interesante)..
La idea de acceder a SQLITE directamente, sin ODBC, es facilitar la instalación de la aplicación por parte de "no informáticos".

Nitzer 18 de mayo de 2023 10:16

Cita:

Citación del post de Joseg (Mensaje 8915)
No encontré ningún OCX con posibilidad de conectarse a la Base de Datos (pero sería interesante)..
La idea de acceder a SQLITE directamente, sin ODBC, es facilitar la instalación de la aplicación por parte de "no informáticos".

@Joseg, no se que pasó en mi anterior mensaje, se me cortó toda la parte final del mismo. Se ha quedado un texto que parece que esté regañando ajajajajaj

En algún mensaje expliqué como empecé con las bases de datos en Power.
Ya sabemos que power tiene varios controles para ello, el primero DbAccess, es por donde empecé para ir comprendiendo , pero pronto te das cuenta que no es lo que buscas.
Luego continué con sql embebido y la configuración de cobol85, que tampoco me terminaba de convencer, aunque hacía su función.
Lo siguiente y con lo que mas he estado ha sido utilizado el control ADO, con ese casi todo lo puedes hacer, la pena es que no hay mucha información enPower, pero a fin de cuentas es ADO, y de ado hay muuuuucha información en internet, empecé a ver todos los métodos, funciones, etc ... y aplicarlas en power, unas iban bien y otras no , me quedé con las que funcionaban y así he estado varios años completamente satisfecho.

Pero mi interés por la sql seguía creciendo y necesitaba aplicar consultas mas grandes, procedimientos almacenados, funciones, etc ... en ese momento empecé a buscar por internet, pero no encontré gran cosa.
Pero conocía a una empresa que tenía varios ocx y con la que ya había contactado , la empresa es FathSowtware, que por cierto hace unos meses cerró y ya no hay manera de encontrar sus productos, pero Admir que es quien llevaba la empresa, lo había conocido e intercamabiado correos, así que le dije si me podía hacer un activex para acceder nativamente a sqlserver y .... tras 27 prototipos y 200 dolares , conseguí lo que buscaba :)

Desde entonces todo ha cambiado.
Si queréis le puedo preguntar si estaría dispuesto a venderlo o regalarlo o lo que sea, es un ocx sencilla,se registra y se distribuye y por ahora y tras varios años, todo perfecto.

Y siento si el mensaje anterior se malinterpretó, admiro el trabajo de cada uno de vosotros.

Joseg 18 de mayo de 2023 11:40

Todo bien.
Estamos aquí para ayudarnos unos a otros.
Este OCX parece interesante, pero comprar un producto aparentemente descatalogado no sería buena idea. Como producto gratuito/de código abierto, me gustaría probarlo.

Saludos

fastpho 18 de mayo de 2023 14:50

Cita:

Citación del post de Nitzer (Mensaje 8914)
El problema de todo esto, es la cantidad de código y lo poco explícito que parece para acceder a los datos.
YO ya os dije que utilizo un activex que me hicieron para acceder y ejecutar y es tremendamente sencillo y claro.

Llevo muchos años trabajando practicamente solo con bases de datos y estoy encantado :)

@Nitzer , el codigo que he subido esta crudo
para que puedan entenderlo , por eso se ve poco explicito y tantas lineas de codigo como decis...(no he malinterpretado tu mensaje) :bien:

La idea de esto es hacerle mas facil la vida (programacion) a los/las
futuros desarrolladores y sepan que con COBOL se puede hacer lo mismo
que con otros lenguajes y obtener los mismos resultados y en algunos
casos hasta mas rapido y efeciente.

Este es un lenguaje denominado de "VIEJOS" , que ya ni se enseña ,
no es un lenguaje "COOL" , pero hay que tratar de llevar a la
juventud a creer en el.

No voy a seguir delirando .....

Volviendo al tema sqlite , es muy simple su implementacion como explique
en el post nro 1

Lo que he echo es envolver la funciones del libreria(sqlite3.dll) de tal forma que queda exactamente igual a cualquier llamada por (invoke o call)
de un activex (dll o ocx) y evitar tantas lineas de codigo.


Saludos....

Nitzer 19 de mayo de 2023 09:55

@fastpho, siento el mensaje :(, os juro que no iba con mala intención.

He hablado con la persona que me hizo el ocx y me ha dicho que lo puedo distribuir libremente.

He pensado en hacer un pequeño video explicando como lo utilizo, un pequeño manual con los métodos y os voy pasado el ocx a quien lo quiera. El ocx pesa 2 mb

Decidme si merece la pena.

Joseg 19 de mayo de 2023 11:10

Cita:

Citación del post de Nitzer (Mensaje 8919)
@fastpho, siento el mensaje :(, os juro que no iba con mala intención.

He hablado con la persona que me hizo el ocx y me ha dicho que lo puedo distribuir libremente.

He pensado en hacer un pequeño video explicando como lo utilizo, un pequeño manual con los métodos y os voy pasado el ocx a quien lo quiera. El ocx pesa 2 mb

Decidme si merece la pena.

Estaria interesado.
Puedes usar Mega para subir (u otro).

Gracias

Kuk 19 de mayo de 2023 11:12

@Nitzer, puedes subirlo al foro directamente ;)

fastpho 19 de mayo de 2023 13:38

Cita:

Citación del post de Nitzer (Mensaje 8919)
@fastpho, siento el mensaje :(, os juro que no iba con mala intención.

He hablado con la persona que me hizo el ocx y me ha dicho que lo puedo distribuir libremente.

He pensado en hacer un pequeño video explicando como lo utilizo, un pequeño manual con los métodos y os voy pasado el ocx a quien lo quiera. El ocx pesa 2 mb

Decidme si merece la pena.

:sis:
@Nitzer
Seria muy bueno que puedas compartir la ocx ;)
Muchas gracias

Fito 20 de mayo de 2023 16:29

Hola:

Estoy muy interesado Andrés. Te estaba persiguiendo por discord por ese tema :mola:

Saludos

Fito

Joseg 30 de mayo de 2023 11:34

:astro:
el OCX fue compartido?!


La franja horaria es GMT +2. Ahora son las 13:47.

Powered by: vBulletin, Versión 3.8.7
Derechos de Autor ©2000 - 2026, Jelsoft Enterprises Ltd.