Ian Hardingham wrote: > I'm using an SQLite implementation that someone else made for my > high-level language of choice. > > While looking through the imp, I've just found this function, which is > used as the callback argument to sqlite3_exec. Does this look like an > ok useage? It seems to me like this might be doing a lot of work for > some data I may never use.
If it's not buggy, and you don't need it to perform better, then leave it alone. If you need it to perform better, don't do any optimizing until you've measured where your hotspots really are by using, e.g., gprof and/or whatever profiling tools exist for your language. If you find that this interface is really your issue, scope out how feasible/cost-effective it is to change it. This will be determined by a great many variables -- size of the code base & number of entry points to this interface, quality of client code, level of abstraction client code provides from this interface to higher layers, availability of a covering test suite, amount of time you have to do the work, number of round-trips you can make with your QA team (if they exist) before delivery, how much new client code you think will be written that eventually calls down to this interface over the next weeks/months/years, etc etc etc. If so, and if it makes sense, consider creating a new interface instead of editing the existing one. This allows you to upgrade the client code a little bit at a time to use the new interface. The drawback is that now you're maintaining two interfaces. Probable hot spots in the existing code: string scans (dStrlen), string copies (dStrcpy) and calls to 'new'. The fewer of those you can do, the better off you'll be. I'd say a good reference as to the "proper" way to hook SQLite into a high-level language is the SQLite devs' own implementation for Tcl. You want to grab e.g. http://sqlite.org/sqlite-tea-3070500.tar.gz and have a look at tclsqlite3.c, function DbEvalNextCmd on line 124807 and function dbEvalColumnValue on line 124743. Things this gets right that your implementation doesn't, from my quick glance: 1. It keeps a cache of prepared statements and re-uses statements that have been run recently. You are re-preparing statements every time. 2. It only asks for columns that the client is asking for (only you can know whether higher layers are getting this right). 3. It only computes the column names once during the statement. You are computing them on every row. 4. It only processes one result row at a time (synchronously calling up to the high-level language), keeping memory usage low. You are stuffing the whole result set into memory before returning it to the client. Fixing this might be the biggest hassle on this list, because it might impact many layers above. 5. It does not force all values to strings. You are (and, depending on which language you're using, you'll probably convert them back to native types higher up somewhere). Shared drawback: 1. Text data is copied. This can't be helped for Tcl because it's enforced by the Tcl extention API. Maybe your language lets you just point directly at a const char* and use copy-on-write semantics or some such. Eric > Any help much appreciated, > Thanks, > Ian > > int Callback(void *pArg, int argc, char **argv, char **columnNames) > { > // basically this callback is called for each row in the SQL query > result. > // for each row, argc indicates how many columns are returned. > // columnNames[i] is the name of the column > // argv[i] is the value of the column > > sqlite_resultrow* pRow; > sqlite_resultset* pResultSet; > char* name; > char* value; > int i; > > if (argc == 0) > return 0; > > pResultSet = (sqlite_resultset*)pArg; > if (!pResultSet) > return -1; > > // create a new result row > pRow = new sqlite_resultrow; > pResultSet->iNumCols = argc; > // loop through all the columns and stuff them into our row > for (i = 0; i < argc; i++) > { > // DBEUG CODE > // Con::printf("%s = %s\n", columnNames[i], argv[i] ? argv[i] : > "NULL"); > name = new char[dStrlen(columnNames[i]) + 1]; > dStrcpy(name, columnNames[i]); > pRow->vColumnNames.push_back(name); > if (argv[i]) > { > value = new char[dStrlen(argv[i]) + 1]; > dStrcpy(value, argv[i]); > pRow->vColumnValues.push_back(value); > } > else > { > value = new char[10]; > dStrcpy(value, "NULL"); > pRow->vColumnValues.push_back(value); > } > } > pResultSet->iNumRows++; > pResultSet->vRows.push_back(pRow); > > // return 0 or else the sqlexec will be aborted. > return 0; > } > _______________________________________________ > sqlite-users mailing list > sqlite-users@sqlite.org > http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users -- Eric A. Smith Stocks have reached what looks like a permanently high plateau. -- Irving Fisher, Professor of Economics, Yale University, 1929. _______________________________________________ sqlite-users mailing list sqlite-users@sqlite.org http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users