Well, I figured it.
I'm probably doing all sorts of things wrong here, but this seemed enough (by empirical messing around :-) to get the answers I was interested in, which was whether the SQL would parse or not for a given statement. It's rough and ready but it works. Just link with the sqlite3 library. Run as: $ runparser "select * from abc" Good SQL $ runparser "select * frim abc" near "frim": syntax error Bad SQL $ runparser "select r.kp, substr(r.kp,1,13) as records, r.result2, r.result4, r.result12, min(1,(r.arecords2/100)) as ap2, min(1,(r.arecords4/100)) as ap4, min(1,(r.arecords12/100)) as ap12, min(1,(r.arecords2/100))*d.dhj as ad2, min(1,(r.arecords4/100))*d.dhj as ad4, min(1,(r.arecords12/100))*d.dhj as ad12, d.ourgrps, d.dhj from answers_read r, dhj_pp d where r.kp = d.kp and r.kp like 'UNC788Y%' order by r.kp, r.cost limit 10" Good SQL spot the difference now... ;-) $ runparser "select r.kp, substr(r.kp,1,13) as records, r.result2, r.result4, r.result12, min(1,(r.arecords2/100)) os ap2, min(1,(r.arecords4/100)) as ap4, min(1,(r.arecords12/100)) as ap12, min(1,(r.arecords2/100))*d.dhj as ad2, min(1,(r.arecords4/100))*d.dhj as ad4, min(1,(r.arecords12/100))*d.dhj as ad12, d.ourgrps, d.dhj from answers_read r, dhj_pp d where r.kp = d.kp and r.kp like 'UNC788Y%' order by r.kp, r.cost limit 10" near "ap2": syntax error Bad SQL ------------ #include "sqlite3.h" #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <stdio.h> #include <string.h> /* ** Compile the UTF-8 encoded SQL statement zSql into a statement handle. */ int sqlite3_prepare_mine( const char *zSql /* UTF-8 encoded SQL statement. */ ){ Parse sParse; char *zErrMsg = 0; int rc; sqlite3 *db; sqlite3_open("/tmp/junkdb", &db); memset(&sParse, 0, sizeof(sParse)); sParse.db = db; if( sqlite3SafetyOn(db) ){ return SQLITE_MISUSE; } sqlite3RunParser(&sParse, zSql, &zErrMsg); if( sqlite3SafetyOff(db) ){ return SQLITE_MISUSE; } sqlite3_close(db); if(strncmp(index(zErrMsg, ':'), ": syntax error",14) == 0) { fprintf(stderr, "\n%s\n", zErrMsg); rc = 1; } else { rc = 0; } return rc; } int main(int *argc, char **argv) { int retcode = sqlite3_prepare_mine(argv[1]); if(retcode == 0) { puts("\nGood SQL\n"); exit(0); } else { puts("Bad SQL\n"); exit(1); } return 0; }