static int set_schema_version(pool *p, const char *schema_name, unsigned int schema_version) { int res, xerrno = 0; const char *stmt, *errstr = NULL; array_header *results; /* CREATE TABLE $schema_name.schema_version ( * schema TEXT NOT NULL PRIMARY KEY, * version INTEGER NOT NULL * ); */ stmt = pstrcat(p, "CREATE TABLE IF NOT EXISTS ", schema_name, ".schema_version (schema TEXT NOT NULL PRIMARY KEY, version INTEGER NOT NULL);", NULL); res = proxy_db_exec_stmt(p, stmt, &errstr); if (res < 0) { (void) pr_log_debug(DEBUG3, MOD_PROXY_VERSION ": error executing statement '%s': %s", stmt, errstr); errno = EPERM; return -1; } stmt = pstrcat(p, "INSERT INTO ", schema_name, ".schema_version (schema, version) VALUES (?, ?);", NULL); res = proxy_db_prepare_stmt(p, stmt); if (res < 0) { xerrno = errno; (void) pr_log_debug(DEBUG3, MOD_PROXY_VERSION ": error preparing statement '%s': %s", stmt, strerror(xerrno)); errno = xerrno; return -1; } res = proxy_db_bind_stmt(p, stmt, 1, PROXY_DB_BIND_TYPE_TEXT, (void *) schema_name); if (res < 0) { return -1; } res = proxy_db_bind_stmt(p, stmt, 2, PROXY_DB_BIND_TYPE_INT, (void *) &schema_version); if (res < 0) { return -1; } results = proxy_db_exec_prepared_stmt(p, stmt, &errstr); if (results == NULL) { (void) pr_log_debug(DEBUG3, MOD_PROXY_VERSION ": error executing statement '%s': %s", stmt, errstr ? errstr : strerror(errno)); errno = EPERM; return -1; } return 0; }
static int get_schema_version(pool *p, const char *schema_name, unsigned int *schema_version) { int res, version; const char *stmt, *errstr = NULL; array_header *results; stmt = pstrcat(p, "SELECT version FROM ", schema_name, ".schema_version WHERE schema = ?;", NULL); res = proxy_db_prepare_stmt(p, stmt); if (res < 0) { /* This can happen when the schema_version table does not exist; treat * as "missing". */ pr_trace_msg(trace_channel, 5, "error preparing statement '%s', treating as missing schema version", stmt); *schema_version = 0; return 0; } res = proxy_db_bind_stmt(p, stmt, 1, PROXY_DB_BIND_TYPE_TEXT, (void *) schema_name); if (res < 0) { return -1; } results = proxy_db_exec_prepared_stmt(p, stmt, &errstr); if (results == NULL) { *schema_version = 0; return 0; } if (results->nelts != 1) { pr_log_debug(DEBUG3, MOD_PROXY_VERSION ": expected 1 result from statement '%s', got %d", stmt, results->nelts); errno = EINVAL; return -1; } version = atoi(((char **) results->elts)[0]); if (version < 0) { /* Invalid schema version; treat as "missing". */ pr_trace_msg(trace_channel, 5, "statement '%s' yielded invalid schema version %d, treating as missing", stmt, version); *schema_version = 0; return 0; } *schema_version = version; return 0; }
END_TEST START_TEST (db_bind_stmt_test) { int res; const char *table_path, *schema_name, *stmt; int idx, int_val; long long_val; char *text_val; res = proxy_db_bind_stmt(NULL, NULL, -1, -1, NULL); fail_unless(res < 0, "Failed to handle null arguments"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); res = proxy_db_bind_stmt(p, NULL, -1, -1, NULL); fail_unless(res < 0, "Failed to handle null statement"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); stmt = "SELECT COUNT(*) FROM table"; idx = -1; res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_INT, NULL); fail_unless(res < 0, "Failed to handle invalid index %d", idx); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); idx = 1; res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_INT, NULL); fail_unless(res < 0, "Failed to handle unprepared statement"); fail_unless(errno == ENOENT, "Expected ENOENT (%d), got '%s' (%d)", ENOENT, strerror(errno), errno); (void) unlink(db_test_table); table_path = db_test_table; schema_name = "proxy_test"; res = proxy_db_open(p, table_path, schema_name); fail_unless(res == 0, "Failed to open table '%s', schema '%s': %s", table_path, schema_name, strerror(errno)); res = create_table(p, schema_name, "foo"); fail_unless(res == 0, "Failed to create table 'foo': %s", strerror(errno)); stmt = "SELECT COUNT(*) FROM foo;"; res = proxy_db_prepare_stmt(p, stmt); fail_unless(res == 0, "Failed to prepare statement '%s': %s", stmt, strerror(errno)); res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_INT, NULL); fail_unless(res < 0, "Failed to handle missing INT value"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); int_val = 7; res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_INT, &int_val); fail_unless(res < 0, "Failed to handle invalid index value"); fail_unless(errno == EPERM, "Expected EPERM (%d), got '%s' (%d)", EPERM, strerror(errno), errno); res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_LONG, NULL); fail_unless(res < 0, "Failed to handle missing LONG value"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); long_val = 7; res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_LONG, &long_val); fail_unless(res < 0, "Failed to handle invalid index value"); fail_unless(errno == EPERM, "Expected EPERM (%d), got '%s' (%d)", EPERM, strerror(errno), errno); res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_TEXT, NULL); fail_unless(res < 0, "Failed to handle missing TEXT value"); fail_unless(errno == EINVAL, "Expected EINVAL (%d), got '%s' (%d)", EINVAL, strerror(errno), errno); text_val = "testing"; res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_TEXT, text_val); fail_unless(res < 0, "Failed to handle invalid index value"); fail_unless(errno == EPERM, "Expected EPERM (%d), got '%s' (%d)", EPERM, strerror(errno), errno); res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_NULL, NULL); fail_unless(res < 0, "Failed to handle invalid NULL value"); fail_unless(errno == EPERM, "Expected EPERM (%d), got '%s' (%d)", EPERM, strerror(errno), errno); stmt = "SELECT COUNT(*) FROM foo WHERE id = ?;"; res = proxy_db_prepare_stmt(p, stmt); fail_unless(res == 0, "Failed to prepare statement '%s': %s", stmt, strerror(errno)); int_val = 7; res = proxy_db_bind_stmt(p, stmt, idx, PROXY_DB_BIND_TYPE_INT, &int_val); fail_unless(res == 0, "Failed to bind INT value: %s", strerror(errno)); res = proxy_db_close(p, NULL); fail_unless(res == 0, "Failed to close database: %s", strerror(errno)); (void) unlink(db_test_table); }