Dear list members,

I'm trying to set a default value for a column in my "CREATE TABLE" statement. 
I really, really want to bind the default value (using sqlite3_bind_*) rather 
than expressing it in SQL text to avoid the following problems:

 * SQL injection attacks;
 * floating point value rounding in conversion to/from text;
 * how else can I set a default value for a binary blob column?


The SQL syntax tree for the "CREATE TABLE" statement at 
http://www.sqlite.org/lang_createtable.html suggests binding a default value is 
permitted. In particular"create-table-stmt:column-def:column-constraint:expr:" 
can be a bind parameter.


The example code, below, highlights the problem I'm having. The code creates a 
table with a bound default value for one of the two columns. The statement is 
prepared (no syntax error warning), and the value bound successfully. But upon 
inserting a row that requires using the default parameter, it crashes in 
function sqlite3ExprCodeTarget(). (Inserting a row with both column values 
explicitly set works fine.)


Tech details: using sqlite-amalgamation-3080600 on Centos 7, compiling with 
GCC4.8.2.


Am I making a silly mistake? Or, contrary to the documentation, is binding a 
default column value in a "CREATE TABLE" statement not possible? If it's not 
possible, can anyone suggest another way to achieve the goal of avoiding 
conversion ofdefault column values to SQL text?


Many thanks,

Nathaniel


Example code:



#include <stdio.h>
#include <stdlib.h>
#include <sqlite3.h>

int main(int argc, char* argv[])
{
  sqlite3 *db = NULL;
  sqlite3_stmt *pStmt = NULL;
  int c;

  /* Open database */
  c = sqlite3_open_v2(
    "test.db", &db, (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE), 0);
  if (c) {
    fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
    exit(0);
  }

  /* Table creation SQL */
  const char *sql =
    "CREATE TABLE test_table ("
    "name     TEXT  DEFAULT ('joe'), "
    "interest TEXT  DEFAULT (?1))";

  /* Prepare SQL statement */
  c = sqlite3_prepare(db, sql, -1, &pStmt, NULL);
  if (c != SQLITE_OK) {
    fprintf(stderr, "Can't prepare statement: %s\n", sqlite3_errmsg(db));
    exit(0);
  }

  /* Bind SQL statement value */
  const char *golf = "golf";
  c = sqlite3_bind_text(pStmt, 1, golf, -1, SQLITE_STATIC);
  if (c != SQLITE_OK) {
    fprintf(stderr, "Can't bind statement: %s\n", sqlite3_errmsg(db));
    exit(0);
  }

  /* Evaluate SQL statement */
  c = sqlite3_step(pStmt);
  if (c != SQLITE_DONE) {
    fprintf(stderr, "Can't evaluate statement: %s\n", sqlite3_errmsg(db));
    exit(0);
  }

  /* Destroy prepared SQL statement */
  c = sqlite3_finalize(pStmt);
  if (c != SQLITE_OK) {
    fprintf(stderr, "Can't destroy statement: %s\n", sqlite3_errmsg(db));
    exit(0);
  }

  /* Insert row */
  const char *sql2 = "INSERT INTO test_table (name) VALUES ('jack');";
  char *errmsg = NULL;
  c = sqlite3_exec(db, sql2, NULL, NULL, &errmsg);
  if (c != SQLITE_OK) {
    fprintf(stderr, "Can't insert row: %s\n", errmsg);
    exit(0);
  }
  sqlite3_free(errmsg);

  /* Close database */
  c = sqlite3_close(db);
  if (c != SQLITE_OK) {
    fprintf(stderr, "Can't close database: %s\n", sqlite3_errmsg(db));
    exit(0);
  }

  return 0;
}
_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to