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 RDDPara 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" )--- 2. Operaciones Básicas xBase (CRUD) 2.1 Creación de Tablas (dbCreate)[!TIP]
Al finalizar la aplicación, libere la memoria asociada llamando a HDbcRdd_End() antes de cerrar la conexión de THDbc.
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" )Code: Select all | Expand
USE empleados ALIAS EMP VIA "RDDHDBC" NEW
IF NetErr()
? "Error abriendo tabla remota"
ENDIFCode: 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.Code: Select all | Expand
EMP->( dbGoTop() )
DO WHILE ! EMP->( Eof() )
? "ID:", EMP->ID, "Nombre:", EMP->NOMBRE
EMP->( dbSkip() )
ENDDOSi 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()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
ENDIFMientras 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 scopeVincule 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
ENDDOEste 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
ENDIFEl RDD soporta mecanismos híbridos valiéndose en el control de su objeto padre oDbc.
TransaccionesEmplee 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()
ENDIFEl 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."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."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!!!