Well, the fields of the table are not the same as the fields of the result of a query!
AFAIK the "higher level" wrapper can't do what you want. I once played around with it and wrote something like this: import strutils, os # NOTE: Some versions of the nim library have the wrong size for TFIELDS import mysql template mRaise(m: string) = var e = new IOError e.msg = m raise e template mRaise(con: PMySQL) = var e = new IOError e.msg = $ mysql.error(con) raise e template traceIt(m: string, doit: stmt): stmt = echo "Trace: ", m doit proc showFields*(res: PRES) = let fnum = int(mysql.numFields(res)) # cast string to int #var fnames: seq[string] #newSeq(fnames, fnum) for i in 0.. <fnum: let fp = mysql.fetch_field_direct(res, cast[cint](i)) case fp.ftype of FIELD_TYPE_VAR_STRING: echo i, " ", fp.name, " (vstring)" of FIELD_TYPE_STRING: echo i, " ", fp.name, " (string)" of FIELD_TYPE_LONG: echo i, " ", fp.name, " (int32)" of FIELD_TYPE_INT24: echo i, " ", fp.name, " (int24)" of FIELD_TYPE_TINY: echo i, " ", fp.name, " (int8)" of FIELD_TYPE_DECIMAL: echo i, " ", fp.name, " (decimal)" of FIELD_TYPE_TIMESTAMP: echo i, " ", fp.name, " (timestamp)" of FIELD_TYPE_DATE: echo i, " ", fp.name, " (date)" of FIELD_TYPE_BLOB: echo i, " ", fp.name, " (binary)" else: echo i, " ", fp.name, " (", fp.ftype, ")!!!!!!!!!!!!!!!!!!" #fnames.add ($fp.name) let con: PMySQL = mysql.init(nil) if con == nil: mRaise "init failed" if mysql.realConnect(con, "localhost", "root", "", "test", 0, nil, 0) == nil: defer: traceIt "close con", mysql.close(con) mRaise con let q = "SELECT * FROM data" if mysql.realQuery(con, q, q.len) != 0: mRaise con #var res = mysql.storeResult(con) var res = mysql.useResult(con) if res != nil: showFields res #var f = cast[ptr array[2, TFIELD]](mysql.fetch_fields(res)) #quit 0 #echo res.row_count #echo mysql.affected_rows con #echo mysql.num_rows res var row: cstringArray while true: row = mysql.fetchRow(res) if row == nil: break let fnum = int(mysql.numFields(res)) # cast string to int for i in 0.. <fnum: if row[i] == nil: echo "NULL" else: echo row[i] if row != nil: while mysql.fetchRow(res) != nil: discard mysql.freeResult(res) Example: -- Adminer 4.2.5 MySQL dump SET NAMES utf8; SET time_zone = '+00:00'; SET foreign_key_checks = 0; SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; DROP TABLE IF EXISTS `data`; CREATE TABLE `data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `value` varchar(10) NOT NULL, `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `en` enum('a','a','b','c') NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8; INSERT INTO `data` (`id`, `value`, `ts`, `en`) VALUES (1, 'c', '2014-11-14 12:17:10', 'a'), (2, 'b', '2014-11-14 12:16:03', 'a'); -- 2016-07-28 13:16:14 Output: 0 id (int32) 1 value (vstring) 2 ts (timestamp) 3 en (string) 1 c 2014-11-14 13:17:10 a 2 b 2014-11-14 13:16:03 a Still. You may consider that using a "free form" result with fieldnames is probably not needed for what you want to do. Using PHP all day I also thought that it is strange to not have access to the field names. But in a typed language you want to get objects or tuples with typed fields back from the database, not a bunch of strings associated to another bunch of strings. So there is much more to this topic and highly dependent on what you really need to do.