AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <stdlib.h>4#include <string.h>5#include <stdio.h>6 7static sqlite3 *gDb = NULL;8 9static void exec_sql(const char *zSql){10 char *zErr = NULL;11 int rc = sqlite3_exec(gDb, zSql, 0, 0, &zErr);12 if( rc!=SQLITE_OK ){13 const char *msg = zErr ? zErr : "SQL exec failed";14 TEST_FAIL_MESSAGE(msg);15 }16 sqlite3_free(zErr);17}18 19void setUp(void) {20 int rc = sqlite3_open(":memory:", &gDb);21 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);22}23 24void tearDown(void) {25 if( gDb ){26 int rc = sqlite3_close(gDb);27 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);28 gDb = NULL;29 }30}31 32/* Helper to call sqlite3_table_column_metadata and assert SQLITE_OK */33static void call_meta_ok(34 const char *zDb, const char *zTab, const char *zCol,35 const char **pzType, const char **pzColl,36 int *pNotNull, int *pPK, int *pAI37){38 int rc = sqlite3_table_column_metadata(39 gDb, zDb, zTab, zCol, pzType, pzColl, pNotNull, pPK, pAI40 );41 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);42}43 44/* Helper to call sqlite3_table_column_metadata and assert SQLITE_ERROR */45static void call_meta_error(46 const char *zDb, const char *zTab, const char *zCol,47 const char **pzType, const char **pzColl,48 int *pNotNull, int *pPK, int *pAI49){50 int rc = sqlite3_table_column_metadata(51 gDb, zDb, zTab, zCol, pzType, pzColl, pNotNull, pPK, pAI52 );53 TEST_ASSERT_EQUAL_INT(SQLITE_ERROR, rc);54}55 56void test_sqlite3_table_column_metadata_basic_columns(void){57 exec_sql("CREATE TABLE t1("58 " id INTEGER PRIMARY KEY, "59 " name TEXT COLLATE BINARY NOT NULL, "60 " age INTEGER, "61 " data BLOB"62 ");");63 64 const char *zType = NULL;65 const char *zColl = NULL;66 int notnull = -1, pk = -1, ai = -1;67 68 /* id column */69 call_meta_ok(NULL, "t1", "id", &zType, &zColl, ¬null, &pk, &ai);70 TEST_ASSERT_NOT_NULL(zType);71 TEST_ASSERT_NOT_NULL(zColl);72 TEST_ASSERT_EQUAL_STRING("INTEGER", zType);73 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));74 /* PRIMARY KEY does not necessarily set the explicit NOT NULL constraint bit */75 TEST_ASSERT_EQUAL_INT(0, notnull);76 TEST_ASSERT_EQUAL_INT(1, pk);77 TEST_ASSERT_EQUAL_INT(0, ai);78 79 /* name column */80 zType = zColl = NULL; notnull = pk = ai = -1;81 call_meta_ok(NULL, "t1", "name", &zType, &zColl, ¬null, &pk, &ai);82 TEST_ASSERT_NOT_NULL(zType);83 TEST_ASSERT_NOT_NULL(zColl);84 TEST_ASSERT_EQUAL_STRING("TEXT", zType);85 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));86 TEST_ASSERT_EQUAL_INT(1, notnull);87 TEST_ASSERT_EQUAL_INT(0, pk);88 TEST_ASSERT_EQUAL_INT(0, ai);89 90 /* age column */91 zType = zColl = NULL; notnull = pk = ai = -1;92 call_meta_ok(NULL, "t1", "age", &zType, &zColl, ¬null, &pk, &ai);93 TEST_ASSERT_NOT_NULL(zType);94 TEST_ASSERT_NOT_NULL(zColl);95 TEST_ASSERT_EQUAL_STRING("INTEGER", zType);96 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));97 TEST_ASSERT_EQUAL_INT(0, notnull);98 TEST_ASSERT_EQUAL_INT(0, pk);99 TEST_ASSERT_EQUAL_INT(0, ai);100 101 /* data column */102 zType = zColl = NULL; notnull = pk = ai = -1;103 call_meta_ok(NULL, "t1", "data", &zType, &zColl, ¬null, &pk, &ai);104 TEST_ASSERT_NOT_NULL(zType);105 TEST_ASSERT_NOT_NULL(zColl);106 TEST_ASSERT_EQUAL_STRING("BLOB", zType);107 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));108 TEST_ASSERT_EQUAL_INT(0, notnull);109 TEST_ASSERT_EQUAL_INT(0, pk);110 TEST_ASSERT_EQUAL_INT(0, ai);111}112 113void test_sqlite3_table_column_metadata_autoincrement(void){114 exec_sql("CREATE TABLE t2("115 " id INTEGER PRIMARY KEY AUTOINCREMENT, "116 " other TEXT"117 ");");118 119 const char *zType = NULL;120 const char *zColl = NULL;121 int notnull = -1, pk = -1, ai = -1;122 123 call_meta_ok(NULL, "t2", "id", &zType, &zColl, ¬null, &pk, &ai);124 TEST_ASSERT_NOT_NULL(zType);125 TEST_ASSERT_NOT_NULL(zColl);126 TEST_ASSERT_EQUAL_STRING("INTEGER", zType);127 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));128 /* Explicit NOT NULL not specified; notnull flag may be 0 */129 TEST_ASSERT_EQUAL_INT(0, notnull);130 TEST_ASSERT_EQUAL_INT(1, pk);131 TEST_ASSERT_EQUAL_INT(1, ai);132}133 134void test_sqlite3_table_column_metadata_rowid_alias(void){135 exec_sql("CREATE TABLE t3(a TEXT, b INTEGER);");136 137 const char *zType = NULL;138 const char *zColl = NULL;139 int notnull = -1, pk = -1, ai = -1;140 141 /* Using rowid alias on a rowid table */142 call_meta_ok(NULL, "t3", "rowid", &zType, &zColl, ¬null, &pk, &ai);143 TEST_ASSERT_NOT_NULL(zType);144 TEST_ASSERT_NOT_NULL(zColl);145 TEST_ASSERT_EQUAL_STRING("INTEGER", zType);146 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));147 TEST_ASSERT_EQUAL_INT(0, notnull);148 TEST_ASSERT_EQUAL_INT(1, pk);149 TEST_ASSERT_EQUAL_INT(0, ai);150}151 152void test_sqlite3_table_column_metadata_null_columnname_rowid_metadata(void){153 exec_sql("CREATE TABLE t4(x TEXT);");154 155 const char *zType = NULL;156 const char *zColl = NULL;157 int notnull = -1, pk = -1, ai = -1;158 159 /* zColumnName==NULL path behaves like rowid metadata per provided code */160 call_meta_ok(NULL, "t4", NULL, &zType, &zColl, ¬null, &pk, &ai);161 TEST_ASSERT_NOT_NULL(zType);162 TEST_ASSERT_NOT_NULL(zColl);163 TEST_ASSERT_EQUAL_STRING("INTEGER", zType);164 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));165 TEST_ASSERT_EQUAL_INT(0, notnull);166 TEST_ASSERT_EQUAL_INT(1, pk);167 TEST_ASSERT_EQUAL_INT(0, ai);168}169 170void test_sqlite3_table_column_metadata_no_such_column(void){171 exec_sql("CREATE TABLE t5(a INTEGER, b TEXT);");172 173 const char *zType = (const char*)0x1; /* sentinel non-NULL */174 const char *zColl = (const char*)0x1;175 int notnull = 123, pk = 123, ai = 123;176 177 call_meta_error(NULL, "t5", "does_not_exist", &zType, &zColl, ¬null, &pk, &ai);178 TEST_ASSERT_NULL(zType);179 TEST_ASSERT_NULL(zColl);180 TEST_ASSERT_EQUAL_INT(0, notnull);181 TEST_ASSERT_EQUAL_INT(0, pk);182 TEST_ASSERT_EQUAL_INT(0, ai);183}184 185void test_sqlite3_table_column_metadata_no_such_table(void){186 const char *zType = (const char*)0x1;187 const char *zColl = (const char*)0x1;188 int notnull = 123, pk = 123, ai = 123;189 190 call_meta_error(NULL, "no_table_here", "anything", &zType, &zColl, ¬null, &pk, &ai);191 TEST_ASSERT_NULL(zType);192 TEST_ASSERT_NULL(zColl);193 TEST_ASSERT_EQUAL_INT(0, notnull);194 TEST_ASSERT_EQUAL_INT(0, pk);195 TEST_ASSERT_EQUAL_INT(0, ai);196}197 198void test_sqlite3_table_column_metadata_view_error(void){199 exec_sql("CREATE TABLE base(a INTEGER, b TEXT);");200 exec_sql("CREATE VIEW v1 AS SELECT a, b FROM base;");201 202 const char *zType = (const char*)0x1;203 const char *zColl = (const char*)0x1;204 int notnull = 123, pk = 123, ai = 123;205 206 call_meta_error(NULL, "v1", "a", &zType, &zColl, ¬null, &pk, &ai);207 TEST_ASSERT_NULL(zType);208 TEST_ASSERT_NULL(zColl);209 TEST_ASSERT_EQUAL_INT(0, notnull);210 TEST_ASSERT_EQUAL_INT(0, pk);211 TEST_ASSERT_EQUAL_INT(0, ai);212}213 214void test_sqlite3_table_column_metadata_without_rowid_rowid_error(void){215 exec_sql("CREATE TABLE t6(a INTEGER, b TEXT, PRIMARY KEY(a, b)) WITHOUT ROWID;");216 217 const char *zType = (const char*)0x1;218 const char *zColl = (const char*)0x1;219 int notnull = 123, pk = 123, ai = 123;220 221 call_meta_error(NULL, "t6", "rowid", &zType, &zColl, ¬null, &pk, &ai);222 TEST_ASSERT_NULL(zType);223 TEST_ASSERT_NULL(zColl);224 TEST_ASSERT_EQUAL_INT(0, notnull);225 TEST_ASSERT_EQUAL_INT(0, pk);226 TEST_ASSERT_EQUAL_INT(0, ai);227}228 229void test_sqlite3_table_column_metadata_collation_nocase(void){230 exec_sql("CREATE TABLE t7(c TEXT COLLATE NOCASE);");231 232 const char *zType = NULL;233 const char *zColl = NULL;234 int notnull = -1, pk = -1, ai = -1;235 236 call_meta_ok(NULL, "t7", "c", &zType, &zColl, ¬null, &pk, &ai);237 TEST_ASSERT_NOT_NULL(zType);238 TEST_ASSERT_NOT_NULL(zColl);239 TEST_ASSERT_EQUAL_STRING("TEXT", zType);240 /* Collation name should be NOCASE (case-insensitive compare) */241 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "NOCASE"));242 TEST_ASSERT_EQUAL_INT(0, notnull);243 TEST_ASSERT_EQUAL_INT(0, pk);244 TEST_ASSERT_EQUAL_INT(0, ai);245}246 247void test_sqlite3_table_column_metadata_null_output_params(void){248 exec_sql("CREATE TABLE t8(x INTEGER, y TEXT);");249 250 /* Call with some NULL output pointers - should still succeed */251 int rc = sqlite3_table_column_metadata(252 gDb, NULL, "t8", "x", NULL, NULL, NULL, NULL, NULL253 );254 TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);255 256 /* Verify that when asking for outputs, values are as expected */257 const char *zType = NULL;258 const char *zColl = NULL;259 int notnull = -1, pk = -1, ai = -1;260 call_meta_ok(NULL, "t8", "x", &zType, &zColl, ¬null, &pk, &ai);261 TEST_ASSERT_NOT_NULL(zType);262 TEST_ASSERT_NOT_NULL(zColl);263 TEST_ASSERT_EQUAL_STRING("INTEGER", zType);264 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));265 TEST_ASSERT_EQUAL_INT(0, notnull);266 TEST_ASSERT_EQUAL_INT(0, pk);267 TEST_ASSERT_EQUAL_INT(0, ai);268}269 270void test_sqlite3_table_column_metadata_temp_schema(void){271 exec_sql("CREATE TEMP TABLE tt(c TEXT);");272 273 const char *zType = NULL;274 const char *zColl = NULL;275 int notnull = -1, pk = -1, ai = -1;276 277 call_meta_ok("temp", "tt", "c", &zType, &zColl, ¬null, &pk, &ai);278 TEST_ASSERT_NOT_NULL(zType);279 TEST_ASSERT_NOT_NULL(zColl);280 TEST_ASSERT_EQUAL_STRING("TEXT", zType);281 TEST_ASSERT_EQUAL_INT(0, sqlite3StrICmp(zColl, "BINARY"));282 TEST_ASSERT_EQUAL_INT(0, notnull);283 TEST_ASSERT_EQUAL_INT(0, pk);284 TEST_ASSERT_EQUAL_INT(0, ai);285}286 287int main(void) {288 UNITY_BEGIN();289 RUN_TEST(test_sqlite3_table_column_metadata_basic_columns);290 RUN_TEST(test_sqlite3_table_column_metadata_autoincrement);291 RUN_TEST(test_sqlite3_table_column_metadata_rowid_alias);292 RUN_TEST(test_sqlite3_table_column_metadata_null_columnname_rowid_metadata);293 RUN_TEST(test_sqlite3_table_column_metadata_no_such_column);294 RUN_TEST(test_sqlite3_table_column_metadata_no_such_table);295 RUN_TEST(test_sqlite3_table_column_metadata_view_error);296 RUN_TEST(test_sqlite3_table_column_metadata_without_rowid_rowid_error);297 RUN_TEST(test_sqlite3_table_column_metadata_collation_nocase);298 RUN_TEST(test_sqlite3_table_column_metadata_null_output_params);299 RUN_TEST(test_sqlite3_table_column_metadata_temp_schema);300 return UNITY_END();301}