HDBC RDD (Replaceable Database Driver) Reference Manual
The HDBC RDD (RDDHDBC) is a powerful engine allowing Harbour developers to interact with any HDBC-connected SQL database uniformly mapping classic xBase commands (USE, APPEND BLANK, REPLACE, SKIP, SEEK, SET FILTER, etc.).
This bridging layer translates your procedural legacy operations dynamically down into native dialects fitting your configured backing engine (SQLite, MySQL, PostgreSQL, etc.). It acts as a perfect gateway for porting existing applications or satisfying developers refusing direct object-oriented manual SQL interactions.
1. Initial Setup and Driver Injection
To begin leveraging WorkAreas, bind your globally instantiated THDbc connection underlying the Harbour core RDD subsystem.
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. Register the core architecture internally
rddRegister( "RDDHDBC", RDT_FULL )
// 2. Cascade your active connection stream down to the RDD scope
HDbcRdd_Init( oDbc )
// 3. (Optional) Force all standard commands to ride this driver
RddSetDefault( "RDDHDBC" )[!TIP]
Before terminating the system scope gracefully, wipe unreleased states utilizingHDbcRdd_End()before concludingTHDbcdisconnect logic.
2. Basic xBase Operations (CRUD)
2.1 Table Generation (dbCreate)
You can architect remote structures directly by feeding a standard structural array blueprint extended with the specialized TIMESTAMP type natively.
Code: Select all | Expand
LOCAL aStruct := { ;
{ "ID", "N", 10, 0 }, ;
{ "NAME", "C", 50, 0 }, ;
{ "SALARY", "N", 12, 2 }, ;
{ "DATE", "D", 8, 0 }, ;
{ "ACTIVE", "L", 1, 0 } ;
}
dbCreate( "employees", aStruct, "RDDHDBC" )2.2 WorkArea Allocation (USE)
Code: Select all | Expand
USE employees ALIAS EMP VIA "RDDHDBC" NEW
IF NetErr()
? "Server failed handling remote table mount"
ENDIF2.3 Insertion (APPEND BLANK & REPLACE)
Code: Select all | Expand
SELECT EMP
APPEND BLANK
REPLACE FIELD->ID WITH 1, ;
FIELD->NAME WITH "John Doe", ;
FIELD->SALARY WITH 2500.50, ;
FIELD->ACTIVE WITH .T.2.4 Navigation (dbSkip, EOF, BOF)
Code: Select all | Expand
EMP->( dbGoTop() )
DO WHILE ! EMP->( Eof() )
? "ID:", EMP->ID, "Name:", EMP->NAME
EMP->( dbSkip() )
ENDDO2.5 Dropping Logic (Physical vs Logical)
Whenever the inner schema observes standard deletion columns (SoftDeletes flag logic), the underlying DELETE routing overrides to UPDATE. Otherwise conventional physically dropping DELETE FROM execution applies natively preventing disk pollution.
Code: Select all | Expand
GOTO 2
DELETE
? "Target instance stripped. Deleted():", Deleted()3. Advanced Remote Features
3.1 Fetch Scopes (INDEX ON & dbSeek)
Create runtime virtual indexing to hasten binary narrowing avoiding sequentially linear sweeps.
Code: Select all | Expand
USE clients ALIAS CLI NEW VIA "RDDHDBC"
INDEX ON FIELD->name TAG query_name
SEEK "Maria Garcia"
IF Found()
? "MATCHED ALIAS! ID:", CLI->id, "City:", CLI->city
ENDIF3.2 Condition Restricting (SET FILTER & SCOPES)
While SET FILTER inherently navigates evaluating record by record, HDBC naturally honors index SCOPES thresholds. Scoping performs logarithmically faster because it intervenes during the early native pre-generation injecting boundaries straight into the SQL request.
Usage of SET FILTER:
Code: Select all | Expand
SET FILTER TO CLI->city == "London"
GO TOP
DO WHILE ! Eof()
? "Located resident:", CLI->name
SKIP
ENDDO
SET FILTER TO // Purge constraintUsage of SCOPES (Smart Indexing Bounds):
Code: Select all | Expand
// Assuming an 'idx_city' tag is created...
ORDSETFOCUS( "idx_city" )
// Lock bounds for TOP (0) and BOTTOM (1)
ORDSCOPE( 0, "London" )
ORDSCOPE( 1, "London" )
GO TOP
// Loop traverses exclusively limited London bounds at lightning speed
ORDSCOPE( 0, NIL ) // Revert top bound wipe out3.3 Foreign Relational Mapping (SET RELATION)
Enforce runtime cascading pointers syncing chained aliases asynchronously while advancing parent cursors step-by-step parallelizing child targets seamlessly.
Code: Select all | Expand
USE invoices ALIAS INV NEW VIA "RDDHDBC"
SELECT CLI
INDEX ON FIELD->id TAG idx_cli
SELECT INV
SET RELATION TO INV->client_id INTO CLI
GO TOP
DO WHILE ! Eof()
// Background translation fetches matching row
? "Order Number:", INV->id, "-> Pertaining Client:", CLI->name
SKIP
ENDDO3.4 Raw DML Aliasing ("SQL-as-Table")
Probably representing RDDHDBC heaviest lifting trick allowing you to package highly volatile aggregated queries directly transforming results wrapping around purely readable WorkAreas.
Code: Select all | Expand
USE "SELECT c.name, COALESCE(SUM(i.total), 0) as subtotal FROM clients c LEFT JOIN invoices i ON c.id = i.client_id GROUP BY c.id, c.name" ALIAS REPORT NEW VIA "RDDHDBC"
IF Used()
DO WHILE ! Eof()
? "Ledger stats:", REPORT->name, "Subtotal:", REPORT->subtotal
SKIP
ENDDO
CLOSE REPORT
ENDIF4. Concurrency Flow
Native RDDHDBC logic heavily relies upon the initialized driver bounds.
Transaction Wrapping
Utilize master oDbc object hooks enclosing blocks strictly honoring RDMS ACID specifications.
Code: Select all | Expand
oDbc:beginTrans()
REPLACE SEC->balance WITH SEC->balance + 500
IF lSuccess
oDbc:commit()
ELSE
oDbc:rollback()
ENDIF5. Physical Maintenance (PACK and ZAP)
RDDHDBC flawlessly couples Harbour legacy maintenance commands with strict backend architectural standards.
ZAP (Full Truncate)
By invoking ZAP, the RDD driver will omit any standard linear DELETE FROM protocol SQL clauses, issuing a definitive native TRUNCATE TABLE command into the targeted engine instead. It resets the database without unnecessarily choking transaction logs (substantially faster).
Code: Select all | Expand
USE audit_trails ALIAS AUD VIA "RDDHDBC" EXCLUSIVE
ZAP
? "Audit table radically truncated back to pristine conditions."PACK (SoftDelete Flushing/Purging)
In traditional DBFs, PACK compacted empty binary slots sequentially. Within HDBC, if an active session flags "Logical Deletion" features (possessing a compliant trailing deleted_at column), issuing the DELETE command exclusively yields Soft-Deletes modifying the date stamp, leaving real data securely attached remotely.
Enacting the PACK command orchestrates the definitive heavy-duty SQL statement dropping permanently any row previously marked with the logical deletion timeframe, fulfilling purely compliant 1:1 xBase replication workflows.
Code: Select all | Expand
USE clients ALIAS CLI VIA "RDDHDBC" EXCLUSIVE
PACK
? "Database thoroughly sanitized definitively dropping hidden soft-deleted entries."Soft Targeting Locks
Optionally leverage standard RLock() to tentatively deny writes targeting your mutating tuples if your engine dialect fully orchestrates external transaction locks locking records atomically safely.
Code: Select all | Expand
GO TOP
IF RLock()
REPLACE SEC->balance WITH 2000
UNLOCK
ELSE
? "Overlapping constraint violation. Process stalled remotely."
ENDIFAnd this works with: MySQL, MariaDB, SQLite and clones, Postgres, Oracle, SQLServer, Interbase, Firebird and ODBC. Writing a PRG for any database is now a reality!!!