DVX_GUI/sql/dvxsql.dhs

389 lines
9.2 KiB
Text

.section Libraries
.topic sql.overview
.title dvxSql -- SQL Database Interface
.toc 0 dvxSql -- SQL Database Interface
.default
.index dvxSql
.index SQL
.index SQLite
.index Database
.h2 dvxSql -- SQL Database Interface
High-level wrapper around SQLite3 for DVX applications. Manages database connections and result set cursors via integer handles so BASIC code never touches raw pointers. All handles are 1-based; 0 indicates an error or invalid handle.
Header: sql/dvxSql.h
.h3 Limits
.table
Constant Value Description
-------- ----- -----------
MAX_DBS 16 Maximum number of simultaneously open databases.
MAX_CURSORS 64 Maximum number of simultaneously open result set cursors.
.endtable
.h3 Handle Model
Database and cursor handles are int32_t values. A successful open or query returns a handle greater than zero. Handle 0 is reserved as the invalid/error sentinel. Closing a database automatically finalizes all cursors that belong to it.
.link sql.db Database Operations
.link sql.cursor Cursor Operations
.link sql.utility Utility Functions
.link sql.example Example
.topic sql.db
.title Database Operations
.toc 1 Database Operations
.index dvxSqlOpen
.index dvxSqlClose
.index dvxSqlExec
.index dvxSqlError
.index dvxSqlAffectedRows
.h2 Database Operations
.h3 dvxSqlOpen
.code
int32_t dvxSqlOpen(const char *path);
.endcode
Open a SQLite database file. Creates the file if it does not exist.
.table
Parameter Description
--------- -----------
path Path to the database file.
.endtable
Returns a database handle greater than 0 on success, or 0 on error (null path, open failure, or no free slots).
.h3 dvxSqlClose
.code
void dvxSqlClose(int32_t db);
.endcode
Close a database and free all associated resources. Any open cursors belonging to this database are automatically finalized.
.table
Parameter Description
--------- -----------
db Database handle returned by dvxSqlOpen.
.endtable
Safe to call with an invalid handle (no-op).
.h3 dvxSqlExec
.code
bool dvxSqlExec(int32_t db, const char *sql);
.endcode
Execute one or more SQL statements that return no result rows. Suitable for DDL (CREATE TABLE, DROP TABLE, etc.) and DML (INSERT, UPDATE, DELETE).
.table
Parameter Description
--------- -----------
db Database handle.
sql SQL statement(s) to execute.
.endtable
Returns true on success, false on error. On failure, the error message is available via dvxSqlError. On success, the affected row count is available via dvxSqlAffectedRows.
.h3 dvxSqlError
.code
const char *dvxSqlError(int32_t db);
.endcode
Return the last error message for a database handle. The returned string is stored internally and valid until the next operation on the same handle.
.table
Parameter Description
--------- -----------
db Database handle.
.endtable
Returns the error string, or "Invalid database handle" if the handle is invalid.
.h3 dvxSqlAffectedRows
.code
int32_t dvxSqlAffectedRows(int32_t db);
.endcode
Return the number of rows inserted, updated, or deleted by the last dvxSqlExec call on this handle.
.table
Parameter Description
--------- -----------
db Database handle.
.endtable
Returns the row count, or 0 if the handle is invalid.
.topic sql.cursor
.title Cursor Operations
.toc 1 Cursor Operations
.index dvxSqlQuery
.index dvxSqlNext
.index dvxSqlEof
.index dvxSqlFieldCount
.index dvxSqlFieldName
.index dvxSqlFieldText
.index dvxSqlFieldByName
.index dvxSqlFieldInt
.index dvxSqlFieldDbl
.index dvxSqlFreeResult
.h2 Cursor Operations
Result set cursors are created by dvxSqlQuery and must be freed with dvxSqlFreeResult when no longer needed. A new cursor is positioned before the first row; call dvxSqlNext to advance to the first row before reading field values.
.h3 dvxSqlQuery
.code
int32_t dvxSqlQuery(int32_t db, const char *sql);
.endcode
Execute a SELECT query and return a cursor handle for iterating the results. The cursor is positioned before the first row.
.table
Parameter Description
--------- -----------
db Database handle.
sql SQL SELECT statement.
.endtable
Returns a cursor handle greater than 0 on success, or 0 on error (invalid handle, null SQL, SQL syntax error, or no free cursor slots). On failure, the error message is available via dvxSqlError on the database handle.
.h3 dvxSqlNext
.code
bool dvxSqlNext(int32_t rs);
.endcode
Advance the cursor to the next row.
.table
Parameter Description
--------- -----------
rs Cursor handle returned by dvxSqlQuery.
.endtable
Returns true if a row is now available for reading, false if the cursor has reached the end or the handle is invalid.
.h3 dvxSqlEof
.code
bool dvxSqlEof(int32_t rs);
.endcode
Test whether the cursor is past the last row.
.table
Parameter Description
--------- -----------
rs Cursor handle.
.endtable
Returns true if the cursor is exhausted or the handle is invalid, false otherwise.
.h3 dvxSqlFieldCount
.code
int32_t dvxSqlFieldCount(int32_t rs);
.endcode
Return the number of columns in the result set.
.table
Parameter Description
--------- -----------
rs Cursor handle.
.endtable
Returns the column count, or 0 if the handle is invalid.
.h3 dvxSqlFieldName
.code
const char *dvxSqlFieldName(int32_t rs, int32_t col);
.endcode
Return the name of a column by index.
.table
Parameter Description
--------- -----------
rs Cursor handle.
col Column index (0-based).
.endtable
Returns the column name, or "" if the handle or index is invalid.
.h3 dvxSqlFieldText
.code
const char *dvxSqlFieldText(int32_t rs, int32_t col);
.endcode
Return the value of a column as a string.
.table
Parameter Description
--------- -----------
rs Cursor handle.
col Column index (0-based).
.endtable
Returns the text value, or "" if the handle or index is invalid or the value is NULL.
.h3 dvxSqlFieldByName
.code
const char *dvxSqlFieldByName(int32_t rs, const char *name);
.endcode
Return the value of a column identified by name as a string. The name match is case-insensitive.
.table
Parameter Description
--------- -----------
rs Cursor handle.
name Column name (case-insensitive).
.endtable
Returns the text value, or "" if the handle is invalid, the name is NULL, or no column with that name exists.
.h3 dvxSqlFieldInt
.code
int32_t dvxSqlFieldInt(int32_t rs, int32_t col);
.endcode
Return the value of a column as a 32-bit integer.
.table
Parameter Description
--------- -----------
rs Cursor handle.
col Column index (0-based).
.endtable
Returns the integer value, or 0 if the handle or index is invalid.
.h3 dvxSqlFieldDbl
.code
double dvxSqlFieldDbl(int32_t rs, int32_t col);
.endcode
Return the value of a column as a double-precision floating point number.
.table
Parameter Description
--------- -----------
rs Cursor handle.
col Column index (0-based).
.endtable
Returns the double value, or 0.0 if the handle or index is invalid.
.h3 dvxSqlFreeResult
.code
void dvxSqlFreeResult(int32_t rs);
.endcode
Close a result set cursor and free its resources. Must be called for every cursor returned by dvxSqlQuery.
.table
Parameter Description
--------- -----------
rs Cursor handle.
.endtable
Safe to call with an invalid handle (no-op).
.topic sql.utility
.title Utility Functions
.toc 1 Utility Functions
.index dvxSqlEscape
.h2 Utility Functions
.h3 dvxSqlEscape
.code
int32_t dvxSqlEscape(const char *src, char *dst, int32_t dstSize);
.endcode
Escape a string for safe inclusion in SQL string literals. Doubles single quotes so that O'Brien becomes O''Brien.
.table
Parameter Description
--------- -----------
src Source string to escape.
dst Destination buffer for the escaped string.
dstSize Size of the destination buffer in bytes.
.endtable
Returns the length of the escaped string (not including the null terminator), or -1 if the buffer was too small or any parameter is NULL/invalid.
.topic sql.example
.title Example Usage
.toc 1 Example Usage
.index SQL Example
.h2 Example Usage
.h3 Creating a Table and Inserting Data
.code
int32_t db = dvxSqlOpen("mydata.db");
if (!db) {
// handle error
}
dvxSqlExec(db, "CREATE TABLE IF NOT EXISTS contacts ("
"id INTEGER PRIMARY KEY, "
"name TEXT, "
"phone TEXT)");
dvxSqlExec(db, "INSERT INTO contacts (name, phone) "
"VALUES ('Alice', '555-0100')");
.endcode
.h3 Querying and Iterating Results
.code
int32_t rs = dvxSqlQuery(db, "SELECT id, name, phone FROM contacts");
if (!rs) {
printf("Error: %s\n", dvxSqlError(db));
}
while (dvxSqlNext(rs)) {
int32_t id = dvxSqlFieldInt(rs, 0);
const char *name = dvxSqlFieldText(rs, 1);
const char *phone = dvxSqlFieldText(rs, 2);
printf("%d: %s -- %s\n", id, name, phone);
}
dvxSqlFreeResult(rs);
dvxSqlClose(db);
.endcode
.h3 Escaping User Input
.code
char escaped[512];
dvxSqlEscape(userInput, escaped, sizeof(escaped));
char sql[1024];
snprintf(sql, sizeof(sql),
"INSERT INTO notes (text) VALUES ('%s')", escaped);
dvxSqlExec(db, sql);
.endcode