Manual de Referencia de HDBC RDD (Replaceable Database Driver)
El RDD de HDBC (RDDHDBC) es un motor que permite a los programadores de Harbour interactuar con cualquier base de datos SQL conectada mediante HDBC utilizando los comandos clásicos de xBase (USE, APPEND BLANK, REPLACE, SKIP, SEEK, SET FILTER, etc.).
Esta capa traduce en tiempo real las operaciones procedurales al dialecto SQL del motor configurado (SQLite, MySQL, PostgreSQL, etc.), lo que es ideal para portar aplicaciones "Legacy" o para desarrolladores que prefieran evitar el uso de objetos y sentencias SQL manuales.
1. Configuración Inicial e Inyección del RDD
Para comenzar, debe enlazar el núcleo de conexión THDbc global al sistema de RDDs de Harbour.
Code: Select all | Expand
#include "hdbc_conn.ch"
#include "hdbc.ch"
#include "rddsys.ch"
PROCEDURE Main()
LOCAL oDbc := THDbc():new( HDBC_DRIVER_SQLITE )
oDbc:connect( "database=test_rdd.db" )
// 1. Registrar el driver en el subsistema RDD
rddRegister( "RDDHDBC", RDT_FULL )
// 2. Transmitir la conexión activa al ámbito RDD
HDbcRdd_Init( oDbc )
// 3. (Opcional) Hacerlo el RDD por defecto
RddSetDefault( "RDDHDBC" )[!TIP]
Al finalizar la aplicación, libere la memoria asociada llamando aHDbcRdd_End()antes de cerrar la conexión deTHDbc.
2. Operaciones Básicas xBase (CRUD)
2.1 Creación de Tablas (dbCreate)
Puede crear tablas remotas usando diccionarios de arrays estándar de Harbour o el tipo especializado TIMESTAMP.
Code: Select all | Expand
LOCAL aStruct := { ;
{ "ID", "N", 10, 0 }, ;
{ "NOMBRE", "C", 50, 0 }, ;
{ "SALARIO", "N", 12, 2 }, ;
{ "FECHA", "D", 8, 0 }, ;
{ "ACTIVO", "L", 1, 0 } ;
}
dbCreate( "empleados", aStruct, "RDDHDBC" )2.2 Apertura (USE)
Code: Select all | Expand
USE empleados ALIAS EMP VIA "RDDHDBC" NEW
IF NetErr()
? "Error abriendo tabla remota"
ENDIF2.3 Altas (APPEND BLANK y REPLACE)
Code: Select all | Expand
SELECT EMP
APPEND BLANK
REPLACE FIELD->ID WITH 1, ;
FIELD->NOMBRE WITH "Juan Pérez", ;
FIELD->SALARIO WITH 2500.50, ;
FIELD->ACTIVO WITH .T.2.4 Navegación (dbSkip, EOF, BOF)
Code: Select all | Expand
EMP->( dbGoTop() )
DO WHILE ! EMP->( Eof() )
? "ID:", EMP->ID, "Nombre:", EMP->NOMBRE
EMP->( dbSkip() )
ENDDO2.5 Bajas Lógicas y Físicas
Si su motor detecta una columna interna para eliminaciones lógicas (SoftDeletes), el comando DELETE realizará un UPDATE subyacente. Para borrados físicos convencionales (si no hay tabla soft-delete configurada), emitirá DELETE FROM.
Code: Select all | Expand
GOTO 2
DELETE
? "Registro 2 marcado como borrado. Deleted():", Deleted()3. Funciones Avanzadas del RDD
3.1 Índices y Búsquedas (INDEX ON y dbSeek)
El RDD permite indexación dinámica local en memoria / servidor permitiendo búsquedas rápidas.
Code: Select all | Expand
USE clientes ALIAS CLI NEW VIA "RDDHDBC"
INDEX ON FIELD->nombre TAG por_nombre
SEEK "Maria García"
IF Found()
? "ENCONTRADA! ID:", CLI->id, "Ciudad:", CLI->ciudad
ENDIF3.2 Filtrado y Contención (SET FILTER y SCOPES)
Mientras que el filtro evalúa registro a registro, HDBC también soporta los SCOPES (Acotaciones de Índice), los cuales son extremadamente más rápidos porque limitan la consulta nativa en su pre-generación inyectando sentencias lógicas.
Uso de SET FILTER:
Code: Select all | Expand
SET FILTER TO CLI->ciudad == "Madrid"
GO TOP
DO WHILE ! Eof()
? "Encontrado en Madrid:", CLI->nombre
SKIP
ENDDO
SET FILTER TO // Limpiar FiltroUso de SCOPES (Filtro Inteligente Indexado):
Code: Select all | Expand
// Asumiendo un tag 'idx_ciudad' creado...
ORDSETFOCUS( "idx_ciudad" )
// Acota tanto por arriba (0) como por abajo (1)
ORDSCOPE( 0, "Madrid" )
ORDSCOPE( 1, "Madrid" )
GO TOP
// El bucle ahora sólo navega clientes de Madrid de modo relámpago
ORDSCOPE( 0, NIL ) // Limpiar scope3.3 Relaciones Entidad-Referencia (SET RELATION)
Vincule cursores mediante apuntadores síncronos xBase para avanzar múltiples WorkAreas en paralelo:
Code: Select all | Expand
USE facturas ALIAS FAC NEW VIA "RDDHDBC"
SELECT CLI
INDEX ON FIELD->id TAG id_cli
SELECT FAC
SET RELATION TO FAC->cliente_id INTO CLI
GO TOP
DO WHILE ! Eof()
// Por debajo, el driver localizará concurrentemente en el puntero de CLI
? "Factura:", FAC->id, "-> Cliente:", CLI->nombre
SKIP
ENDDO3.4 Inyección de Vistas SQL Complejas ("SQL-as-Table")
Este es uno de los recursos más potentes del RDDHDBC. Puede inyectar cualquier string puramente DML (SELECT ... JOIN ... GROUP BY) y montarlo como un WorkArea que puede ser escaneado unidireccionalmente.
Code: Select all | Expand
USE "SELECT c.nombre, COALESCE(SUM(f.total), 0) as total FROM clientes c LEFT JOIN facturas f ON c.id = f.cliente_id GROUP BY c.id, c.nombre" ALIAS RESUMEN NEW VIA "RDDHDBC"
IF Used()
DO WHILE ! Eof()
? "Resumen:", RESUMEN->nombre, "Total:", RESUMEN->total
SKIP
ENDDO
CLOSE RESUMEN
ENDIF4. Transacciones y Bloqueos
El RDD soporta mecanismos híbridos valiéndose en el control de su objeto padre oDbc.
Transacciones
Emplee directamente el nivel oDbc para encapsular y revertir de acuerdo a las capacidades ACID del servidor:
Code: Select all | Expand
oDbc:beginTrans()
REPLACE SEC->saldo WITH SEC->saldo + 500
IF lTodoCorrecto
oDbc:commit()
ELSE
oDbc:rollback()
ENDIF5. Mantenimiento Físico (PACK y ZAP)
El RDDHDBC integra utilidades físicas nativas para el mantenimiento del modelo de datos tradicional xBase.
ZAP (Vaciado Completo)
Al invocar ZAP, el motor del RDD ignorará cualquier cláusula SQL DELETE FROM tradicional, e intentará ejecutar el comando nativo TRUNCATE TABLE en el servidor, reseteando la tabla sin castigar el log de transacciones (mucho más rápido).
Code: Select all | Expand
USE auditorias ALIAS AUD VIA "RDDHDBC" EXCLUSIVE
ZAP
? "Tabla de auditoría truncada radicalmente."PACK (Purga de Bajas Lógicas SoftDeletes)
En las tablas tradicionales DBF PACK compactaba el archivo físico. En HDBC, si su tabla emplea "Bajas Lógicas" (una columna deleted_at), el comando genérico DELETE sólo hace Soft-Deletes rellenando la fecha, dejando las filas en base de datos.
Ejecutar el comando PACK mandará la instrucción SQL definitiva que extermina físicamente de la base de datos aquellos registros previamente marcados con la baja lógica, replicando el comportamiento xBase exacto.
Code: Select all | Expand
USE clientes ALIAS CLI VIA "RDDHDBC" EXCLUSIVE
PACK
? "Base de datos saneada permanentemente de tuplas borradas."Bloqueos de Registros Optimistas
Puede emitir instrucciones RLock() para reservar temporalmente los estados del cursor mientras se mutan datos atómicamente si el driver del RDMS lo permite.
Code: Select all | Expand
GO TOP
IF RLock()
REPLACE SEC->saldo WITH 2000
UNLOCK
ELSE
? "Alguien más tiene bloqueada esta fila."
ENDIFY esto funciona con:
MySQL, MariaDb, SQLite y clónicos, Postgres, Oracle, SQLServer, Interbase, Firebird y ODBC
Ya es una realidad escribir un PRG para cualquier base de datos!!!