Line data Source code
1 : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2 : * Copyright (C) 2024 Frediano Ziglio
3 : *
4 : * This library is free software; you can redistribute it and/or
5 : * modify it under the terms of the GNU Library General Public
6 : * License as published by the Free Software Foundation; either
7 : * version 2 of the License, or (at your option) any later version.
8 : *
9 : * This library is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : * Library General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU Library General Public
15 : * License along with this library; if not, write to the
16 : * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 : * Boston, MA 02111-1307, USA.
18 : */
19 :
20 : /**
21 : * This tests execute some command using tsql and defncopy to check behaviour
22 : */
23 :
24 : #include "common.h"
25 :
26 : #if HAVE_STRING_H
27 : #include <string.h>
28 : #endif /* HAVE_STRING_H */
29 :
30 : #ifdef HAVE_UNISTD_H
31 : #include <unistd.h>
32 : #endif
33 :
34 : #include <freetds/sysdep_private.h>
35 : #include <freetds/replacements.h>
36 :
37 : /* content of output file, from command executed */
38 : static char *output;
39 :
40 : static bool
41 : read_login_info(void)
42 : {
43 10 : return read_login_info_base(&common_pwd, DEFAULT_PWD_PATH) != NULL;
44 : }
45 :
46 : static void
47 20 : cleanup(void)
48 : {
49 20 : unlink("empty");
50 20 : unlink(output_fn());
51 20 : unlink(input_fn());
52 20 : TDS_ZERO_FREE(output);
53 20 : }
54 :
55 : static void
56 30 : defncopy(const char *object_name)
57 : {
58 : char cmd[2048];
59 30 : char *const end = cmd + sizeof(cmd) - 1;
60 : char *p;
61 : FILE *f;
62 :
63 : /* empty input */
64 30 : f = fopen(input_fn(), "w");
65 30 : assert(f);
66 30 : fclose(f);
67 :
68 30 : strcpy(cmd, "defncopy" EXE_SUFFIX);
69 30 : p = strchr(cmd, 0);
70 30 : p = add_server(p, end);
71 30 : p = add_string(p, end, " ");
72 30 : p = quote_arg(p, end, object_name);
73 30 : p = add_string(p, end, "<");
74 30 : p = add_string(p, end, input_fn());
75 30 : p = add_string(p, end, " >");
76 30 : p = add_string(p, end, output_fn());
77 30 : *p = 0;
78 30 : printf("Executing: %s\n", cmd);
79 30 : if (system(cmd) != 0) {
80 0 : printf("Output is:\n");
81 0 : cat(output_fn(), stdout);
82 0 : fprintf(stderr, "Failed command\n");
83 0 : exit(1);
84 : }
85 30 : TDS_ZERO_FREE(output);
86 30 : output = read_file(output_fn());
87 30 : }
88 :
89 : /* Builds the command with Sybase syntax */
90 : static void
91 10 : defncopy_sybase(const char *object_name)
92 : {
93 : char cmd[2048];
94 10 : char *const end = cmd + sizeof(cmd) - 1;
95 : char *p;
96 : FILE *f;
97 :
98 : /* empty input */
99 10 : f = fopen(input_fn(), "w");
100 10 : assert(f);
101 10 : fclose(f);
102 :
103 10 : strcpy(cmd, "defncopy" EXE_SUFFIX);
104 10 : p = strchr(cmd, 0);
105 10 : p = add_login(p, end);
106 10 : p = add_string(p, end, " out ");
107 10 : p = add_string(p, end, output_fn());
108 10 : if (common_pwd.database[0]) {
109 10 : p = add_string(p, end, " ");
110 10 : p = quote_arg(p, end, common_pwd.database);
111 : }
112 10 : p = add_string(p, end, " ");
113 10 : p = quote_arg(p, end, object_name);
114 10 : *p = 0;
115 10 : printf("Executing: %s\n", cmd);
116 :
117 10 : if (system(cmd) != 0) {
118 0 : printf("Output is:\n");
119 0 : cat(output_fn(), stdout);
120 0 : fprintf(stderr, "Failed command\n");
121 0 : exit(1);
122 : }
123 10 : TDS_ZERO_FREE(output);
124 :
125 10 : output = read_file(output_fn());
126 10 : }
127 :
128 : /* table with a column name that is also a keyword, should be quoted */
129 : static void
130 10 : test_keyword(void)
131 : {
132 : const char *sql;
133 : static const char clean[] =
134 : "IF OBJECT_ID('dbo.table_with_column_named_key') IS NOT NULL DROP TABLE dbo.table_with_column_named_key\n";
135 :
136 10 : tsql(clean);
137 10 : tsql(
138 : "IF OBJECT_ID('dbo.table_with_column_named_key') IS NOT NULL DROP TABLE dbo.table_with_column_named_key\n"
139 : "GO\n"
140 : "CREATE TABLE dbo.table_with_column_named_key\n"
141 : "(\n"
142 : " [key] nvarchar(4000) NOT NULL\n"
143 : ")\n");
144 10 : defncopy("dbo.table_with_column_named_key");
145 10 : cat(output_fn(), stdout);
146 10 : normalize_spaces(output);
147 10 : sql =
148 : "CREATE TABLE [dbo].[table_with_column_named_key]\n"
149 : " ( [key] nvarchar(4000) NOT NULL\n"
150 : " )\n"
151 : "GO";
152 10 : if (strstr(output, sql) == NULL) {
153 0 : fprintf(stderr, "Expected SQL string not found\n");
154 0 : exit(1);
155 : }
156 10 : tsql(clean);
157 10 : tsql(sql);
158 10 : tsql(clean);
159 10 : }
160 :
161 :
162 : /* same as previous but using Sybase syntax */
163 : static void
164 10 : test_keyword_sybase(void)
165 : {
166 : const char *sql;
167 : static const char clean[] =
168 : "IF OBJECT_ID('dbo.table_with_column_named_key') IS NOT NULL DROP TABLE dbo.table_with_column_named_key\n";
169 :
170 10 : tsql(clean);
171 : /* *INDENT-OFF* */
172 10 : sql =
173 : "IF OBJECT_ID('dbo.table_with_column_named_key') IS NOT NULL DROP TABLE dbo.table_with_column_named_key\n"
174 : "GO\n"
175 : "CREATE TABLE dbo.table_with_column_named_key\n"
176 : "(\n"
177 : " [key] nvarchar(4000) NOT NULL\n"
178 : ")\n";
179 : /* *INDENT-ON* */
180 10 : tsql(sql);
181 10 : defncopy_sybase("dbo.table_with_column_named_key");
182 10 : cat(output_fn(), stdout);
183 10 : normalize_spaces(output);
184 : /* *INDENT-OFF* */
185 10 : sql =
186 : "CREATE TABLE [dbo].[table_with_column_named_key]\n"
187 : " ( [key] nvarchar(4000) NOT NULL\n"
188 : " )\n"
189 : "GO";
190 : /* *INDENT-ON* */
191 10 : if (strstr(output, sql) == NULL) {
192 0 : fprintf(stderr, "Expected SQL string not found\n");
193 0 : exit(1);
194 : }
195 10 : tsql(clean);
196 10 : tsql(sql);
197 10 : tsql(clean);
198 10 : }
199 :
200 : /* table with an index with a space inside */
201 : static void
202 10 : test_index_name_with_space(void)
203 : {
204 : const char *sql;
205 : static const char clean[] =
206 : "IF OBJECT_ID('dbo.tblReportPeriod') IS NOT NULL DROP TABLE dbo.tblReportPeriod\n";
207 :
208 10 : tsql(clean);
209 10 : tsql(
210 : "CREATE TABLE dbo.tblReportPeriod\n"
211 : " ( RecordID int NOT NULL\n"
212 : " , FromDate nvarchar(40) NULL\n"
213 : " , ToDate nvarchar(40) NULL\n"
214 : " )\n"
215 : "CREATE nonclustered INDEX [From Date] on dbo.tblReportPeriod(FromDate)\n");
216 10 : defncopy("dbo.tblReportPeriod");
217 10 : cat(output_fn(), stdout);
218 10 : normalize_spaces(output);
219 10 : sql =
220 : "CREATE TABLE [dbo].[tblReportPeriod]\n"
221 : " ( [RecordID] int NOT NULL\n"
222 : " , [FromDate] nvarchar(40) NULL\n"
223 : " , [ToDate] nvarchar(40) NULL\n"
224 : " )\n"
225 : "GO\n"
226 : "\n"
227 : "CREATE nonclustered INDEX [From Date] on [dbo].[tblReportPeriod]([FromDate])";
228 10 : if (strstr(output, sql) == NULL) {
229 0 : fprintf(stderr, "Expected SQL string not found\n");
230 0 : exit(1);
231 : }
232 10 : tsql(clean);
233 10 : tsql(sql);
234 10 : tsql(clean);
235 10 : }
236 :
237 : /* table with an index with a space inside */
238 : static void
239 10 : test_weird_index_names(void)
240 : {
241 : const char *sql, *sql_sybase;
242 : static const char clean[] =
243 : "IF OBJECT_ID('dbo.tblReportPeriod2') IS NOT NULL DROP TABLE dbo.tblReportPeriod2\n";
244 :
245 10 : tsql(clean);
246 10 : tsql(
247 : "CREATE TABLE dbo.tblReportPeriod2\n"
248 : " ( RecordID int NOT NULL\n"
249 : " , [To, ] nvarchar(40) NULL\n"
250 : " , [To] nvarchar(40) NULL\n"
251 : " , [To, , ] nvarchar(40) NULL\n"
252 : " )\n"
253 : "CREATE nonclustered INDEX [From Date] on dbo.tblReportPeriod2([To, ],[To, , ])\n");
254 10 : defncopy("dbo.tblReportPeriod2");
255 10 : cat(output_fn(), stdout);
256 10 : normalize_spaces(output);
257 10 : sql =
258 : "CREATE TABLE [dbo].[tblReportPeriod2]\n"
259 : " ( [RecordID] int NOT NULL\n"
260 : " , [To, ] nvarchar(40) NULL\n"
261 : " , [To] nvarchar(40) NULL\n"
262 : " , [To, , ] nvarchar(40) NULL\n"
263 : " )\n"
264 : "GO\n"
265 : "\n"
266 : "CREATE nonclustered INDEX [From Date] on [dbo].[tblReportPeriod2]([To, ],[To, , ])";
267 : /* Sybase remove spaces at the end */
268 10 : sql_sybase =
269 : "CREATE TABLE [dbo].[tblReportPeriod2]\n"
270 : " ( [RecordID] int NOT NULL\n"
271 : " , [To,] nvarchar(40) NULL\n"
272 : " , [To] nvarchar(40) NULL\n"
273 : " , [To, ,] nvarchar(40) NULL\n"
274 : " )\n"
275 : "GO\n"
276 : "\n"
277 : "CREATE nonclustered INDEX [From Date] on [dbo].[tblReportPeriod2]([To,],[To, ,])";
278 10 : if (strstr(output, sql) == NULL && strstr(output, sql_sybase) == NULL) {
279 0 : fprintf(stderr, "Expected SQL string not found\n");
280 0 : exit(1);
281 : }
282 10 : tsql(clean);
283 10 : tsql(sql);
284 10 : tsql(clean);
285 10 : }
286 :
287 10 : TEST_MAIN()
288 : {
289 : FILE *f;
290 :
291 10 : cleanup();
292 10 : update_path();
293 :
294 10 : if (!read_login_info())
295 : return 1;
296 :
297 10 : f = fopen("empty", "w");
298 10 : if (f)
299 10 : fclose(f);
300 :
301 10 : test_keyword();
302 10 : test_keyword_sybase();
303 10 : test_index_name_with_space();
304 10 : test_weird_index_names();
305 :
306 10 : cleanup();
307 10 : return 0;
308 : }
|