1 /*
2  * Purpose: Test sending and receiving TEXT datatype
3  * Functions: dbmoretext dbreadtext dbtxptr dbtxtimestamp dbwritetext
4  */
5 
6 #include "common.h"
7 
8 #define BLOB_BLOCK_SIZE 4096
9 
10 int failed = 0;
11 
12 #define TABLE_NAME "freetds_dblib_t0013"
13 
14 char *testargs[] = { "", FREETDS_SRCDIR "/data.bin", "t0013.out" };
15 
16 DBPROCESS *dbproc, *dbprocw;
17 
18 static void
drop_table(void)19 drop_table(void)
20 {
21 	if (!dbproc)
22 		return;
23 
24 	dbcancel(dbproc);
25 
26 	sql_cmd(dbproc);
27 	dbsqlexec(dbproc);
28 	while (dbresults(dbproc) != NO_MORE_RESULTS) {
29 		/* nop */
30 	}
31 }
32 
33 static int
test(int argc,char ** argv,int over4k)34 test(int argc, char **argv, int over4k)
35 {
36 	LOGINREC *login;
37 	int i;
38 	DBINT testint;
39 	FILE *fp;
40 	long result, isiz;
41 	char *blob, *rblob;
42 	DBBINARY *textPtr = NULL, *timeStamp = NULL;
43 	char objname[256];
44 	char rbuf[BLOB_BLOCK_SIZE];
45 	long numread;
46 	int data_ok;
47 	int numtowrite, numwritten;
48 	set_malloc_options();
49 
50 	read_login_info(argc, argv);
51 	printf("Starting %s\n", argv[0]);
52 	dbinit();
53 
54 	dberrhandle(syb_err_handler);
55 	dbmsghandle(syb_msg_handler);
56 
57 	printf("About to logon\n");
58 
59 	login = dblogin();
60 	DBSETLPWD(login, PASSWORD);
61 	DBSETLUSER(login, USER);
62 	DBSETLAPP(login, "t0013");
63 
64 	printf("About to open, PASSWORD: %s, USER: %s, SERVER: %s\n", "", "", "");	/* PASSWORD, USER, SERVER); */
65 
66 	dbproc = dbopen(login, SERVER);
67 	dbprocw = dbopen(login, SERVER);
68 	if (strlen(DATABASE)) {
69 		dbuse(dbproc, DATABASE);
70 		dbuse(dbprocw, DATABASE);
71 	}
72 	dbloginfree(login);
73 	printf("logged in\n");
74 
75 	if (argc == 1) {
76 		argv = testargs;
77 		argc = 3;
78 	}
79 	if (argc < 3) {
80 		fprintf(stderr, "Usage: %s infile outfile\n", argv[0]);
81 		return 1;
82 	}
83 
84 	if ((fp = fopen(argv[1], "rb")) == NULL) {
85 		fprintf(stderr, "Cannot open input file: %s\n", argv[1]);
86 		return 2;
87 	}
88 	printf("Reading binary input file\n");
89 
90 	fseek(fp, 0, SEEK_END);
91 	isiz = ftell(fp);
92 	fseek(fp, 0, SEEK_SET);
93 
94 	blob = (char *) malloc(isiz);
95 	assert(blob);
96 	result = fread((void *) blob, isiz, 1, fp);
97 	assert(result == 1);
98 	fclose(fp);
99 
100 	drop_table();
101 
102 	sql_cmd(dbproc);
103 	dbsqlexec(dbproc);
104 	while (dbresults(dbproc) != NO_MORE_RESULTS) {
105 		/* nop */
106 	}
107 
108 	sql_cmd(dbproc);
109 	dbsqlexec(dbproc);
110 	while (dbresults(dbproc) != NO_MORE_RESULTS) {
111 		/* nop */
112 	}
113 
114 	sql_cmd(dbproc);
115 	dbsqlexec(dbproc);
116 	if (dbresults(dbproc) != SUCCEED) {
117 		fprintf(stderr, "Error inserting blob\n");
118 		return 4;
119 	}
120 
121 	for (i=0; (result = dbnextrow(dbproc)) != NO_MORE_ROWS; i++) {
122 		assert(REG_ROW == result);
123 		printf("fetching row %d\n", i+1);
124 		strcpy(objname, TABLE_NAME ".PigTure");
125 		textPtr = dbtxptr(dbproc, 1);
126 		timeStamp = dbtxtimestamp(dbproc, 1);
127 		break; /* can't proceed until no more rows */
128 	}
129 	assert(REG_ROW == result || 0 < i);
130 
131 	if (!textPtr && !timeStamp && dbtds(dbproc) >= DBTDS_7_2) {
132 		printf("Protocol 7.2+ detected, test not supported\n");
133 		free(blob);
134 		dbclose(dbproc);
135 		dbproc = NULL;
136 		dbexit();
137 		exit(0);
138 	}
139 
140 	if (!textPtr) {
141 		fprintf(stderr, "Error getting textPtr\n");
142 		exit(1);
143 	}
144 
145 	/*
146 	 * Use #ifdef if you want to test dbmoretext mode (needed for 16-bit apps)
147 	 * Use #ifndef for big buffer version (32-bit)
148 	 */
149 	printf("writing text ... ");
150 	if (over4k) {
151 		if (dbwritetext(dbprocw, objname, textPtr, DBTXPLEN, timeStamp, FALSE, isiz, (BYTE*) blob) != SUCCEED)
152 			return 5;
153 		printf("done (in one shot)\n");
154 		for (; (result = dbnextrow(dbproc)) != NO_MORE_ROWS; i++) {
155 			assert(REG_ROW == result);
156 			printf("fetching row %d?\n", i+1);
157 		}
158 	} else {
159 		if (dbwritetext(dbprocw, objname, textPtr, DBTXPLEN, timeStamp, FALSE, isiz, NULL) != SUCCEED)
160 			return 15;
161 		printf("done\n");
162 
163 		printf("dbsqlok\n");
164 		dbsqlok(dbprocw);
165 		printf("dbresults\n");
166 		dbresults(dbprocw);
167 
168 		numtowrite = 0;
169 		/* Send the update value in chunks. */
170 		for (numwritten = 0; numwritten < isiz; numwritten += numtowrite) {
171 			printf("dbmoretext %d\n", 1 + numwritten);
172 			numtowrite = (isiz - numwritten);
173 			if (numtowrite > BLOB_BLOCK_SIZE)
174 				numtowrite = BLOB_BLOCK_SIZE;
175 			dbmoretext(dbprocw, (DBINT) numtowrite, (BYTE *) (blob + numwritten));
176 		}
177 		dbsqlok(dbprocw);
178 		while (dbresults(dbprocw) != NO_MORE_RESULTS){
179 			printf("suprise!\n");
180 		}
181 	}
182 #if 0
183 	if (SUCCEED != dbclose(dbproc)){
184 		printf("dbclose failed");
185 		exit(1);
186 	}
187 	dbproc = dbopen(login, SERVER);
188 	assert(dbproc);
189 	if (strlen(DATABASE)) {
190 		dbuse(dbproc, DATABASE);
191 	}
192 #endif
193 	sql_cmd(dbproc);
194 	dbsqlexec(dbproc);
195 
196 	if (dbresults(dbproc) != SUCCEED) {
197 		failed = 1;
198 		printf("Was expecting a result set.");
199 		exit(1);
200 	}
201 
202 	for (i = 1; i <= dbnumcols(dbproc); i++) {
203 		printf("col %d, \"%s\", is type %s\n",
204 			i, dbcolname(dbproc, i), dbprtype(dbcoltype(dbproc, i)));
205 	}
206 	if (2 != dbnumcols(dbproc)) {
207 		fprintf(stderr, "Failed.  Expected 2 columns\n");
208 		exit(1);
209 	}
210 
211 	if (SUCCEED != dbbind(dbproc, 1, INTBIND, -1, (BYTE *) & testint)) {
212 		fprintf(stderr, "Had problem with bind\n");
213 		exit(1);
214 	}
215 
216 	if (REG_ROW != dbnextrow(dbproc)) {
217 		fprintf(stderr, "Failed.  Expected a row\n");
218 		exit(1);
219 	}
220 	if (testint != 1) {
221 		failed = 1;
222 		fprintf(stderr, "Failed.  Expected i to be %d, was %d\n", 1, (int) testint);
223 		exit(1);
224 	}
225 	dbnextrow(dbproc);
226 
227 	/* get the image */
228 	sql_cmd(dbproc);
229 	dbsqlexec(dbproc);
230 	dbresults(dbproc);
231 
232 	printf("select 2\n");
233 
234 	sql_cmd(dbproc);
235 	dbsqlexec(dbproc);
236 	if (dbresults(dbproc) != SUCCEED) {
237 		fprintf(stderr, "Error extracting blob\n");
238 		return 6;
239 	}
240 
241 	numread = 0;
242 	rblob = NULL;
243 	while ((result = dbreadtext(dbproc, rbuf, BLOB_BLOCK_SIZE)) != NO_MORE_ROWS) {
244 		if (result != 0) {	/* this indicates not end of row */
245 			rblob = (char*) realloc(rblob, result + numread);
246 			memcpy((void *) (rblob + numread), (void *) rbuf, result);
247 			numread += result;
248 		}
249 	}
250 
251 	data_ok = 1;
252 	if (memcmp(blob, rblob, numread) != 0) {
253 		printf("Saving first blob data row to file: %s\n", argv[2]);
254 		if ((fp = fopen(argv[2], "wb")) == NULL) {
255 			fprintf(stderr, "Unable to open output file: %s\n", argv[2]);
256 			return 3;
257 		}
258 		fwrite((void *) rblob, numread, 1, fp);
259 		fclose(fp);
260 		failed = 1;
261 		data_ok = 0;
262 	}
263 
264 	printf("Read blob data row %d --> %s %ld byte comparison\n",
265 	       (int) testint, data_ok ? "PASSED" : "failed", numread);
266 	free(rblob);
267 
268 	if (dbnextrow(dbproc) != NO_MORE_ROWS) {
269 		failed = 1;
270 		fprintf(stderr, "Was expecting no more rows\n");
271 		exit(1);
272 	}
273 
274 	free(blob);
275 	drop_table();
276 	dbclose(dbproc);
277 	dbproc = NULL;
278 
279 	dbexit();
280 
281 	return 0;
282 }
283 
284 int
main(int argc,char ** argv)285 main(int argc, char **argv)
286 {
287 	int res = test(argc, argv, 0);
288 	if (!res)
289 		res = test(argc, argv, 1);
290 	if (res)
291 		return res;
292 
293 	printf("%s %s\n", __FILE__, (failed ? "failed!" : "OK"));
294 	return failed ? 1 : 0;
295 }
296 
297