File size: 5,113 Bytes
7510827
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "sqliteInt.h"
#include "unity.h"
#include <string.h>
#include <stdlib.h>

/* Globals for test */
static sqlite3 *gDb = NULL;
static Parse gParse;

/* Helper: add a RenameToken to gParse.pRename pointing at p */
static RenameToken* addRenameToken(void *p){
  RenameToken *r = (RenameToken*)sqlite3_malloc(sizeof(RenameToken));
  TEST_ASSERT_NOT_NULL(r);
  memset(r, 0, sizeof(*r));
  r->p = p;
  r->pNext = gParse.pRename;
  gParse.pRename = r;
  return r;
}

/* Helper: free all RenameToken nodes in gParse.pRename */
static void freeAllRenameTokens(void){
  RenameToken *p = gParse.pRename;
  while( p ){
    RenameToken *pNext = p->pNext;
    sqlite3_free(p);
    p = pNext;
  }
  gParse.pRename = NULL;
}

void setUp(void) {
  int rc = sqlite3_open(":memory:", &gDb);
  TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
  memset(&gParse, 0, sizeof(gParse));
  gParse.db = gDb;
  gParse.pRename = NULL;
}

void tearDown(void) {
  freeAllRenameTokens();
  if( gDb ){
    int rc = sqlite3_close(gDb);
    TEST_ASSERT_EQUAL_INT(SQLITE_OK, rc);
    gDb = NULL;
  }
}

/* Utility: create an ExprList with a single integer expression and assign alias */
static ExprList* makeExprListWithAlias(Parse *pParse, int val, const char *alias){
  char buf[32];
  sqlite3_snprintf(sizeof(buf), buf, "%d", val);
  Expr *pExpr = sqlite3Expr(pParse->db, TK_INTEGER, buf);
  TEST_ASSERT_NOT_NULL(pExpr);
  ExprList *pList = sqlite3ExprListAppend(pParse, NULL, pExpr);
  TEST_ASSERT_NOT_NULL(pList);
  Token t;
  t.z = (char*)alias;
  t.n = (int)strlen(alias);
  sqlite3ExprListSetName(pParse, pList, &t, 1);
  return pList;
}

/* Utility: append another integer expression with alias to an existing list */
static void appendExprWithAlias(Parse *pParse, ExprList **ppList, int val, const char *alias){
  char buf[32];
  sqlite3_snprintf(sizeof(buf), buf, "%d", val);
  Expr *pExpr = sqlite3Expr(pParse->db, TK_INTEGER, buf);
  TEST_ASSERT_NOT_NULL(pExpr);
  *ppList = sqlite3ExprListAppend(pParse, *ppList, pExpr);
  TEST_ASSERT_NOT_NULL(*ppList);
  Token t;
  t.z = (char*)alias;
  t.n = (int)strlen(alias);
  sqlite3ExprListSetName(pParse, *ppList, &t, 1);
}

/* Test: passing NULL pEList is a no-op (tokens unchanged) */
void test_sqlite3RenameExprlistUnmap_null_list_noop(void){
  int dummy1 = 0x11;
  int dummy2 = 0x22;
  RenameToken *rt1 = addRenameToken(&dummy1);
  RenameToken *rt2 = addRenameToken(&dummy2);

  sqlite3RenameExprlistUnmap(&gParse, NULL);

  TEST_ASSERT_EQUAL_PTR(&dummy1, rt1->p);
  TEST_ASSERT_EQUAL_PTR(&dummy2, rt2->p);
}

/* Test: unmaps tokens for expression nodes and zEName aliases in the list */
void test_sqlite3RenameExprlistUnmap_unmaps_expr_nodes_and_aliases(void){
  /* Build ExprList with two items: 1 AS a, 2 AS b */
  ExprList *pList = makeExprListWithAlias(&gParse, 1, "a");
  appendExprWithAlias(&gParse, &pList, 2, "b");

  /* Capture pointers to alias names and one expression node */
  TEST_ASSERT_TRUE(pList->nExpr >= 2);
  char *zName0 = pList->a[0].zEName;
  char *zName1 = pList->a[1].zEName;
  TEST_ASSERT_NOT_NULL(zName0);
  TEST_ASSERT_NOT_NULL(zName1);
  Expr *pExpr0 = pList->a[0].pExpr;
  TEST_ASSERT_NOT_NULL(pExpr0);

  /* Create RenameToken entries for:
  **  - The first expression node pointer (should be unmapped by walker)
  **  - Both alias zEName pointers (should be unmapped by explicit remap)
  **  - An unrelated pointer (should remain unchanged)
  */
  int unrelatedDummy = 0xABCD;
  RenameToken *rtExpr = addRenameToken((void*)pExpr0);
  RenameToken *rtName0 = addRenameToken((void*)zName0);
  RenameToken *rtName1 = addRenameToken((void*)zName1);
  RenameToken *rtUnrelated = addRenameToken(&unrelatedDummy);

  /* Call function under test */
  sqlite3RenameExprlistUnmap(&gParse, pList);

  /* Validate: mapped tokens for expr and names are cleared; unrelated unchanged */
  TEST_ASSERT_NULL(rtExpr->p);
  TEST_ASSERT_NULL(rtName0->p);
  TEST_ASSERT_NULL(rtName1->p);
  TEST_ASSERT_EQUAL_PTR(&unrelatedDummy, rtUnrelated->p);

  sqlite3ExprListDelete(gDb, pList);
}

/* Test: when there are no matching tokens (neither expr nodes nor zEName),
** the rename list remains unchanged. */
void test_sqlite3RenameExprlistUnmap_no_matching_tokens(void){
  ExprList *pList = makeExprListWithAlias(&gParse, 3, "c");
  /* Create a token that does not correspond to any node or alias in pList */
  int other = 123;
  RenameToken *rtOther = addRenameToken(&other);

  /* Sanity: ensure we did NOT add tokens pointing to pList's nodes or zEName */
  TEST_ASSERT_NOT_NULL(pList->a[0].pExpr);
  TEST_ASSERT_NOT_NULL(pList->a[0].zEName);
  TEST_ASSERT_NOT_EQUAL_PTR(pList->a[0].pExpr, rtOther->p);
  TEST_ASSERT_NOT_EQUAL_PTR(pList->a[0].zEName, rtOther->p);

  sqlite3RenameExprlistUnmap(&gParse, pList);

  /* No changes expected */
  TEST_ASSERT_EQUAL_PTR(&other, rtOther->p);

  sqlite3ExprListDelete(gDb, pList);
}

int main(void) {
  UNITY_BEGIN();
  RUN_TEST(test_sqlite3RenameExprlistUnmap_null_list_noop);
  RUN_TEST(test_sqlite3RenameExprlistUnmap_unmaps_expr_nodes_and_aliases);
  RUN_TEST(test_sqlite3RenameExprlistUnmap_no_matching_tokens);
  return UNITY_END();
}