diff --git a/src/tiny_sqlite.nim b/src/tiny_sqlite.nim index b9dce98..0b1142b 100644 --- a/src/tiny_sqlite.nim +++ b/src/tiny_sqlite.nim @@ -62,6 +62,12 @@ type values: seq[DbValue] columns: seq[string] + ColumnMetadata* = object + databaseName*: string + tableName*: string + originName*: string + + const SqliteRcOk = [ sqlite.SQLITE_OK, sqlite.SQLITE_DONE, sqlite.SQLITE_ROW ] @@ -574,6 +580,25 @@ proc value*(statement: SqlStatement, for row in statement.iterate(params): return some(row.values[0]) +func columnCount*(statement: SqlStatement): int = + ## Get column count for the prepared statement. + assertCanUseStatement statement + sqlite.column_count(statement.handle) + +func columnMetadata*(statement: SqlStatement, idx: Natural): Option[ColumnMetadata] = + ## Get column metadata for the given column of the prepared statement. + ## See https://www.sqlite.org/c3ref/column_database_name.html + assertCanUseStatement statement + let + db = sqlite.column_database_name(statement.handle, idx.int32) + table = sqlite.column_table_name(statement.handle, idx.int32) + origin = sqlite.column_origin_name(statement.handle, idx.int32) + if db == nil or table == nil or origin == nil: + return none(ColumnMetadata) + some(ColumnMetadata(databaseName: $db, + tableName: $table, + originName: $origin)) + proc finalize*(statement: SqlStatement): void = ## Finalize the statement. This needs to be called once the statement is no longer used to ## prevent memory leaks. Finalizing an already finalized statement is a harmless no-op. diff --git a/src/tiny_sqlite/sqlite_wrapper.nim b/src/tiny_sqlite/sqlite_wrapper.nim index 4c0c690..44fa004 100644 --- a/src/tiny_sqlite/sqlite_wrapper.nim +++ b/src/tiny_sqlite/sqlite_wrapper.nim @@ -223,6 +223,12 @@ proc column_count*(stmt: Stmt): cint proc column_name*(stmt: Stmt, col: cint): cstring {.cdecl, dynlib: Lib, importc: "sqlite3_column_name".} +proc column_database_name*(stmt: Stmt, col: cint): cstring + {.cdecl, dynlib: Lib, importc: "sqlite3_column_database_name".} + +proc column_origin_name*(stmt: Stmt, col: cint): cstring + {.cdecl, dynlib: Lib, importc: "sqlite3_column_origin_name".} + proc column_table_name*(stmt: Stmt, col: cint): cstring {.cdecl, dynlib: Lib, importc: "sqlite3_column_table_name".} diff --git a/tests/tests.nim b/tests/tests.nim index a4f7ba6..2336ff3 100644 --- a/tests/tests.nim +++ b/tests/tests.nim @@ -265,6 +265,18 @@ test "row.unpack": expect AssertionDefect: discard row.unpack(tuple[name: string]) +test "stmt.columnMetadata": + withDb: + let stmt = db.stmt(SelectPersons) + check stmt.columnCount == 2 + let col1 = stmt.columnMetadata(1) + check col1.isSome + check col1.get.databaseName == "main" + check col1.get.tableName == "Person" + check col1.get.originName == "age" + let col2 = stmt.columnMetadata(2) + check col2.isNone + test "stmt.all": withDb: let stmt = db.stmt(SelectPersons)