AryaWu/sqlite
0
1#include "sqliteInt.h"2#include "unity.h"3#include <string.h>4#include <stdlib.h>5 6/* Wrapper for the static function under test (provided by the module) */7extern int test_viewGetColumnNames(Parse *pParse, Table *pTable);8 9/* Helper: create a minimal SELECT "SELECT 1 AS <n1>, 2 AS <n2>" with an empty FROM list */10static Select* makeConstSelect(Parse *pParse, sqlite3 *db, const char *n1, const char *n2){11 Token tOne, tTwo, tN1, tN2;12 Expr *e1 = 0;13 Expr *e2 = 0;14 ExprList *pEList = 0;15 16 tOne.z = "1"; tOne.n = 1;17 tTwo.z = "2"; tTwo.n = 1;18 19 /* Build expression list with aliases */20 e1 = sqlite3ExprAlloc(db, TK_INTEGER, &tOne, 0);21 TEST_ASSERT_NOT_NULL(e1);22 pEList = sqlite3ExprListAppend(pParse, 0, e1);23 TEST_ASSERT_NOT_NULL(pEList);24 tN1.z = (char*)n1; tN1.n = (int)strlen(n1);25 sqlite3ExprListSetName(pParse, pEList, &tN1, 1);26 27 e2 = sqlite3ExprAlloc(db, TK_INTEGER, &tTwo, 0);28 TEST_ASSERT_NOT_NULL(e2);29 pEList = sqlite3ExprListAppend(pParse, pEList, e2);30 TEST_ASSERT_NOT_NULL(pEList);31 tN2.z = (char*)n2; tN2.n = (int)strlen(n2);32 sqlite3ExprListSetName(pParse, pEList, &tN2, 1);33 34 /* Create an empty SrcList object (nSrc=0) to satisfy internal cursor assignment */35 SrcList *pSrc = (SrcList*)sqlite3DbMallocZero(db, sizeof(SrcList));36 TEST_ASSERT_NOT_NULL(pSrc);37 pSrc->nSrc = 0;38 39 /* Build the Select object */40 Select *pSel = sqlite3SelectNew(pParse, pEList, pSrc, 0, 0, 0, 0, 0, 0);41 TEST_ASSERT_NOT_NULL(pSel);42 return pSel;43}44 45/* Helper: create an ExprList serving as a VIEW argument list: "(name1, name2)" */46static ExprList* makeArgList(Parse *pParse, sqlite3 *db, const char *n1, const char *n2){47 ExprList *pList = 0;48 Token tN;49 Expr *e = 0;50 51 /* First name */52 tN.z = (char*)n1; tN.n = (int)strlen(n1);53 e = sqlite3ExprAlloc(db, TK_ID, &tN, 0);54 TEST_ASSERT_NOT_NULL(e);55 pList = sqlite3ExprListAppend(pParse, 0, e);56 TEST_ASSERT_NOT_NULL(pList);57 sqlite3ExprListSetName(pParse, pList, &tN, 1);58 59 /* Second name */60 tN.z = (char*)n2; tN.n = (int)strlen(n2);61 e = sqlite3ExprAlloc(db, TK_ID, &tN, 0);62 TEST_ASSERT_NOT_NULL(e);63 pList = sqlite3ExprListAppend(pParse, pList, e);64 TEST_ASSERT_NOT_NULL(pList);65 sqlite3ExprListSetName(pParse, pList, &tN, 1);66 67 return pList;68}69 70void setUp(void) {71 /* no-op */72}73void tearDown(void) {74 /* no-op */75}76 77/* Test: pTable->nCol < 0 triggers circular definition error and returns non-zero */78void test_viewGetColumnNames_circular_definition_error(void){79 sqlite3 *db = 0;80 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));81 82 Parse p = {0};83 p.db = db;84 85 Table *pView = (Table*)sqlite3DbMallocZero(db, sizeof(Table));86 TEST_ASSERT_NOT_NULL(pView);87 pView->zName = sqlite3DbStrDup(db, "v_circular");88 TEST_ASSERT_NOT_NULL(pView->zName);89 pView->nCol = -1; /* Mark as "computing" to simulate circular */90 pView->tabFlags = TF_View; /* mark as view */91 92 int rc = test_viewGetColumnNames(&p, pView);93 TEST_ASSERT_NOT_EQUAL(0, rc);94 TEST_ASSERT_GREATER_THAN_INT(0, 0); /* keep Unity happy with a check */95 TEST_ASSERT_TRUE(p.nErr > 0);96 97 sqlite3DeleteTable(db, pView);98 sqlite3_close(db);99}100 101/* Test: pSelect==NULL path -> nErr++ and DB_UnresetViews flag set */102void test_viewGetColumnNames_null_select_sets_UnresetViews_and_errors(void){103 sqlite3 *db = 0;104 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));105 106 Parse p = {0};107 p.db = db;108 109 Schema *pSchema = db->aDb[0].pSchema;110 TEST_ASSERT_NOT_NULL(pSchema);111 unsigned int origFlags = pSchema->schemaFlags;112 113 Table *pView = (Table*)sqlite3DbMallocZero(db, sizeof(Table));114 TEST_ASSERT_NOT_NULL(pView);115 pView->zName = sqlite3DbStrDup(db, "v_nullsel");116 TEST_ASSERT_NOT_NULL(pView->zName);117 pView->nCol = 0; /* Unknown columns yet */118 pView->tabFlags = TF_View; /* Is a view */119 pView->pSchema = pSchema; /* Belongs to main schema */120 pView->u.view.pSelect = 0; /* No select defined -> duplication fails */121 122 int rc = test_viewGetColumnNames(&p, pView);123 TEST_ASSERT_NOT_EQUAL(0, rc);124 TEST_ASSERT_TRUE((pSchema->schemaFlags & DB_UnresetViews) != 0);125 126 /* Restore schema flags to avoid side-effects on later tests */127 pSchema->schemaFlags = origFlags;128 129 sqlite3DeleteTable(db, pView);130 sqlite3_close(db);131}132 133/* Test: Successful derivation without argument list (names from SELECT aliases) */134void test_viewGetColumnNames_success_no_arglist(void){135 sqlite3 *db = 0;136 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));137 138 Parse p = {0};139 p.db = db;140 141 /* Build SELECT "SELECT 1 AS a, 2 AS b" */142 Select *pSel = makeConstSelect(&p, db, "a", "b");143 144 /* Build view table object */145 Table *pView = (Table*)sqlite3DbMallocZero(db, sizeof(Table));146 TEST_ASSERT_NOT_NULL(pView);147 pView->zName = sqlite3DbStrDup(db, "v_ok");148 TEST_ASSERT_NOT_NULL(pView->zName);149 pView->nCol = 0; /* Unknown initially */150 pView->tabFlags = TF_View; /* Mark as view */151 pView->pSchema = db->aDb[0].pSchema;152 pView->u.view.pSelect = pSel;153 154 int rc = test_viewGetColumnNames(&p, pView);155 TEST_ASSERT_EQUAL(0, rc);156 157 TEST_ASSERT_EQUAL_INT(2, pView->nCol);158 TEST_ASSERT_EQUAL_INT(pView->nCol, pView->nNVCol);159 TEST_ASSERT_NOT_NULL(pView->aCol);160 TEST_ASSERT_NOT_NULL(pView->aCol[0].zCnName);161 TEST_ASSERT_NOT_NULL(pView->aCol[1].zCnName);162 TEST_ASSERT_EQUAL_STRING("a", pView->aCol[0].zCnName);163 TEST_ASSERT_EQUAL_STRING("b", pView->aCol[1].zCnName);164 165 sqlite3DeleteTable(db, pView); /* Frees pSel via deleteTable(IsView) */166 sqlite3_close(db);167}168 169/* Test: Successful derivation with explicit arglist in pTable->pCheck (names from arglist) */170void test_viewGetColumnNames_success_with_arglist(void){171 sqlite3 *db = 0;172 TEST_ASSERT_EQUAL(SQLITE_OK, sqlite3_open(":memory:", &db));173 174 Parse p = {0};175 p.db = db;176 177 /* Build SELECT "SELECT 1 AS a, 2 AS b" (two result columns) */178 Select *pSel = makeConstSelect(&p, db, "ignored1", "ignored2");179 180 /* Build argument list "(x, y)" that should provide the final column names */181 ExprList *pArgList = makeArgList(&p, db, "x", "y");182 183 /* Build view table object */184 Table *pView = (Table*)sqlite3DbMallocZero(db, sizeof(Table));185 TEST_ASSERT_NOT_NULL(pView);186 pView->zName = sqlite3DbStrDup(db, "v_args");187 TEST_ASSERT_NOT_NULL(pView->zName);188 pView->nCol = 0;189 pView->tabFlags = TF_View;190 pView->pSchema = db->aDb[0].pSchema;191 pView->u.view.pSelect = pSel;192 pView->pCheck = pArgList; /* For views, pCheck holds the arglist */193 194 int rc = test_viewGetColumnNames(&p, pView);195 TEST_ASSERT_EQUAL(0, rc);196 197 TEST_ASSERT_EQUAL_INT(2, pView->nCol);198 TEST_ASSERT_EQUAL_INT(pView->nCol, pView->nNVCol);199 TEST_ASSERT_NOT_NULL(pView->aCol);200 TEST_ASSERT_EQUAL_STRING("x", pView->aCol[0].zCnName);201 TEST_ASSERT_EQUAL_STRING("y", pView->aCol[1].zCnName);202 203 sqlite3DeleteTable(db, pView); /* Frees pSel and pArgList */204 sqlite3_close(db);205}206 207int main(void){208 UNITY_BEGIN();209 RUN_TEST(test_viewGetColumnNames_circular_definition_error);210 RUN_TEST(test_viewGetColumnNames_null_select_sets_UnresetViews_and_errors);211 RUN_TEST(test_viewGetColumnNames_success_no_arglist);212 RUN_TEST(test_viewGetColumnNames_success_with_arglist);213 return UNITY_END();214}