ecpglib.c 37.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* Copyright comment */
/*
 * The aim is to get a simpler inteface to the database routines.
 * All the tidieous messing around with tuples is supposed to be hidden
 * by this function.
 */
/* Author: Linus Tolke
   (actually most if the code is "borrowed" from the distribution and just
   slightly modified)
 */

/* Taken over as part of PostgreSQL by Michael Meskes <meskes@debian.org>
   on Feb. 5th, 1998 */

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <string.h>

21 22
#include <libpq-fe.h>
#include <libpq/pqcomm.h>
23 24 25 26
#include <ecpgtype.h>
#include <ecpglib.h>
#include <sqlca.h>

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
/* variables visible to the programs */
int no_auto_trans;

static struct sqlca sqlca_init  =
{
         {'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},
         sizeof(struct sqlca),
         0,
         { 0, {0}},
         {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},
         {0, 0, 0, 0, 0, 0},
         {0, 0, 0, 0, 0, 0, 0, 0},
         {0, 0, 0, 0, 0, 0, 0, 0}
};

struct sqlca sqlca =
{
         {'S', 'Q', 'L', 'C', 'A', ' ', ' ', ' '},
         sizeof(struct sqlca),
         0,
         { 0, {0}},
         {'N', 'O', 'T', ' ', 'S', 'E', 'T', ' '},
         {0, 0, 0, 0, 0, 0},
         {0, 0, 0, 0, 0, 0, 0, 0},
         {0, 0, 0, 0, 0, 0, 0, 0}
};
53

54 55 56 57 58 59 60
static struct connection
{
	char *name;
	PGconn *connection;
	struct connection *next;
} *all_connections = NULL, *actual_connection = NULL;

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
struct variable
{
	enum ECPGttype type;
	void *value;
	long varcharsize;
	long arrsize;
	long offset;
	enum ECPGttype ind_type;
	void *ind_value;
	long ind_varcharsize;
	long ind_arrsize;
	long ind_offset;
	struct variable *next;
};

struct statement
{
	int lineno;
	char *command;
	struct variable *inlist;
	struct variable *outlist;
};

84 85 86 87 88
static int	simple_debug = 0;
static FILE *debugstream = NULL;
static int	committed = true;

static void
89
register_error(long code, char *fmt,...)
90 91 92 93 94 95 96 97 98 99
{
	va_list		args;

	sqlca.sqlcode = code;
	va_start(args, fmt);
	vsprintf(sqlca.sqlerrm.sqlerrmc, fmt, args);
	va_end(args);
	sqlca.sqlerrm.sqlerrml = strlen(sqlca.sqlerrm.sqlerrmc);
}

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
static void
ECPGfinish(struct connection *act)
{
	if (act != NULL)
	{
		ECPGlog("ECPGfinish: finishing %s.\n", act->name);
		PQfinish(act->connection);
		/* remove act from the list */
		if (act == all_connections)
		{
			all_connections = act->next;
			free(act->name);
			free(act);
		}
		else
		{
			struct connection *con;
			
			for (con = all_connections; con->next && con->next !=  act; con = con->next);
			if (con->next)
			{
				con->next = act->next;
				free(act->name);
				free(act);
			}
		}
		
		if (actual_connection == act)
			actual_connection = all_connections;
	}
	else
		ECPGlog("ECPGfinish: called an extra time.\n");
}

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
static char *ecpg_alloc(long size, int lineno)
{
	char *new = (char *) malloc(size);

	if (!new)
	{
		ECPGfinish(actual_connection);
		ECPGlog("out of memory\n");
	        register_error(ECPG_OUT_OF_MEMORY, "out of memory in line %d", lineno);
		return NULL;
	}
	
	memset(new, '\0', size);
	return(new);
}

/* This function returns a newly malloced string that has the ' and \
   in the argument quoted with \.
 */
static
char *
quote_postgres(char *arg, int lineno)
{
	char	   *res = (char *) ecpg_alloc(2 * strlen(arg) + 1, lineno);
	int			i,
				ri;

	if (!res)
		return(res);
		
	for (i = 0, ri = 0; arg[i]; i++, ri++)
	{
		switch (arg[i])
		{
			case '\'':
			case '\\':
				res[ri++] = '\\';
			default:
				;
		}

		res[ri] = arg[i];
	}
	res[ri] = '\0';

	return res;
}

182 183 184 185 186 187 188
/* create a list of variables */
static bool
create_statement(int lineno, struct statement **stmt, char *query, va_list ap)
{
	struct variable **list = &((*stmt)->inlist);
	enum ECPGttype	type;
	
189 190
	if (!(*stmt = (struct statement *) ecpg_alloc(sizeof(struct statement), lineno)))
		return false;
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
	
	(*stmt)->command = query;
	(*stmt)->lineno = lineno;
	
	list = &((*stmt)->inlist);

	type = va_arg(ap, enum ECPGttype);
	
	while (type != ECPGt_EORT)
   	{  
   	   if (type == ECPGt_EOIT)
   	   {
   	   	list = &((*stmt)->outlist);
   	   }
   	   else
   	   {
		struct variable *var, *ptr;
						
209
		if (!(var = (struct variable *) ecpg_alloc(sizeof(struct variable), lineno)))
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
			return false;
	   	
	   	var->type = type;
	   	var->value = va_arg(ap, void *);
		var->varcharsize = va_arg(ap, long);
		var->arrsize = va_arg(ap, long);
		var->offset = va_arg(ap, long);
		var->ind_type = va_arg(ap, enum ECPGttype);
		var->ind_value = va_arg(ap, void *);
		var->ind_varcharsize = va_arg(ap, long);
		var->ind_arrsize = va_arg(ap, long);
		var->ind_offset = va_arg(ap, long);
		var->next = NULL;
		
		for (ptr = *list; ptr && ptr->next; ptr=ptr->next);
		
		if (ptr == NULL)
			*list = var;
		else
			ptr->next = var;
	   }
	   
	   type = va_arg(ap, enum ECPGttype);
	}
	
	return(true);
}

static bool
ECPGexecute(struct statement *stmt)
240 241 242 243 244
{
	bool		status = false;
	char	   *copiedquery;
	PGresult   *results;
	PGnotify   *notify;
245
	struct variable *var;
246

247 248
 	memcpy((char *)&sqlca, (char *)&sqlca_init, sizeof(sqlca));
	
249
	copiedquery = strdup(stmt->command);
250 251

	/*
252 253 254 255
	 * Now, if the type is one of the fill in types then we take the
	 * argument and enter that in the string at the first %s position.
	 * Then if there are any more fill in types we fill in at the next and
	 * so on.
256
	 */
257 258
	var = stmt->inlist;
	while (var)
259 260 261 262 263 264 265
	{
		char	   *newcopy;
		char	   *mallocedval = NULL;
		char	   *tobeinserted = NULL;
		char	   *p;
		char		buff[20];

266 267 268 269 270
		/*
		 * Some special treatment is needed for records since we want
		 * their contents to arrive in a comma-separated list on insert (I
		 * think).
		 */
271

Marc G. Fournier's avatar
Marc G. Fournier committed
272 273 274
		buff[0] = '\0';
		
		/* check for null value and set input buffer accordingly */
275
		switch (var->ind_type)
276
		{
Marc G. Fournier's avatar
Marc G. Fournier committed
277 278
			case ECPGt_short:
			case ECPGt_unsigned_short:
279
				if (*(short *) var->ind_value < 0)
Marc G. Fournier's avatar
Marc G. Fournier committed
280 281 282 283
					strcpy(buff, "null");
				break;
			case ECPGt_int:
			case ECPGt_unsigned_int:
284
				if (*(int *) var->ind_value < 0)
Marc G. Fournier's avatar
Marc G. Fournier committed
285 286 287 288
					strcpy(buff, "null");
				break;
			case ECPGt_long:
			case ECPGt_unsigned_long:
289
				if (*(long *) var->ind_value < 0L)
Marc G. Fournier's avatar
Marc G. Fournier committed
290 291 292 293 294 295 296 297
					strcpy(buff, "null");
				break;
			default:
				break;
		}
		
		if (*buff == '\0')
		{
298
		   switch (var->type)
Marc G. Fournier's avatar
Marc G. Fournier committed
299
		   {
300 301
			case ECPGt_short:
			case ECPGt_int:
302
				sprintf(buff, "%d", *(int *) var->value);
303 304 305 306 307
				tobeinserted = buff;
				break;

			case ECPGt_unsigned_short:
			case ECPGt_unsigned_int:
308
				sprintf(buff, "%d", *(unsigned int *) var->value);
309 310 311 312
				tobeinserted = buff;
				break;

			case ECPGt_long:
313
				sprintf(buff, "%ld", *(long *) var->value);
314 315 316 317
				tobeinserted = buff;
				break;

			case ECPGt_unsigned_long:
318
				sprintf(buff, "%ld", *(unsigned long *) var->value);
319 320 321 322
				tobeinserted = buff;
				break;

			case ECPGt_float:
323
				sprintf(buff, "%.14g", *(float *) var->value);
324 325 326 327
				tobeinserted = buff;
				break;

			case ECPGt_double:
328
				sprintf(buff, "%.14g", *(double *) var->value);
329 330 331 332
				tobeinserted = buff;
				break;

			case ECPGt_bool:
333
				sprintf(buff, "'%c'", (*(char *) var->value ? 't' : 'f'));
334 335 336
				tobeinserted = buff;
				break;

337 338 339 340
			case ECPGt_char:
			case ECPGt_unsigned_char:
				{
					/* set slen to string length if type is char * */
341
					int			slen = (var->varcharsize == 0) ? strlen((char *) var->value) : var->varcharsize;
342
					char * tmp;
343

344
					if (!(newcopy = ecpg_alloc(slen + 1, stmt->lineno)))
345 346
						return false;
						
347
					strncpy(newcopy, (char *) var->value, slen);
348 349
					newcopy[slen] = '\0';

350
					if (!(mallocedval = (char *) ecpg_alloc(2 * strlen(newcopy) + 3, stmt->lineno)))
351 352
						return false;
						
353
					strcpy(mallocedval, "'");
354
					tmp = quote_postgres(newcopy, stmt->lineno);
355 356 357 358
					if (!tmp)
						return false;
						
					strcat(mallocedval, tmp);
359 360 361 362 363 364 365 366
					strcat(mallocedval, "'");

					free(newcopy);

					tobeinserted = mallocedval;
				}
				break;

367 368
			case ECPGt_varchar:
				{
369 370
					struct ECPGgeneric_varchar *variable =
					(struct ECPGgeneric_varchar *) (var->value);
371
					char *tmp;
372

373
					if (!(newcopy = (char *) ecpg_alloc(variable->len + 1, stmt->lineno)))
374 375
						return false;
						
376 377
					strncpy(newcopy, variable->arr, variable->len);
					newcopy[variable->len] = '\0';
378

379
					if (!(mallocedval = (char *) ecpg_alloc(2 * strlen(newcopy) + 3, stmt->lineno)))
380 381
						return false;
					
382
					strcpy(mallocedval, "'");
383
					tmp = quote_postgres(newcopy, stmt->lineno);
384 385 386 387
					if (!tmp)
						return false;
					                                                
					strcat(mallocedval, tmp);
388 389 390 391 392 393 394 395 396 397
					strcat(mallocedval, "'");

					free(newcopy);

					tobeinserted = mallocedval;
				}
				break;

			default:
				/* Not implemented yet */
398
				register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
399
							   ECPGtype_name(var->type), stmt->lineno);
400 401
				return false;
				break;
Marc G. Fournier's avatar
Marc G. Fournier committed
402
		   }
403
		}
Marc G. Fournier's avatar
Marc G. Fournier committed
404 405
		else
		   tobeinserted = buff;
406

407 408 409
		/*
		 * Now tobeinserted points to an area that is to be inserted at
		 * the first %s
410
		 */
411
		if (!(newcopy = (char *) ecpg_alloc(strlen(copiedquery) + strlen(tobeinserted) + 1, stmt->lineno)))
412 413
			return false;
		 	
414 415 416
		strcpy(newcopy, copiedquery);
		if ((p = strstr(newcopy, ";;")) == NULL)
		{
417 418 419 420

			/*
			 * We have an argument but we dont have the matched up string
			 * in the string
421
			 */
422
			register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
423 424 425 426 427
			return false;
		}
		else
		{
			strcpy(p, tobeinserted);
428 429 430 431 432

			/*
			 * The strange thing in the second argument is the rest of the
			 * string from the old string
			 */
433 434 435 436 437 438
			strcat(newcopy,
				   copiedquery
				   + (p - newcopy)
				   + 2 /* Length of ;; */ );
		}

439 440
		/*
		 * Now everything is safely copied to the newcopy. Lets free the
441
		 * oldcopy and let the copiedquery get the var->value from the newcopy.
442 443 444 445 446 447 448 449 450 451
		 */
		if (mallocedval != NULL)
		{
			free(mallocedval);
			mallocedval = NULL;
		}

		free(copiedquery);
		copiedquery = newcopy;

452
		var = var->next;
453 454 455 456 457
	}

	/* Check if there are unmatched things left. */
	if (strstr(copiedquery, ";;") != NULL)
	{
458
		register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
459 460 461
		return false;
	}

462
	/* Now the request is built. */
463

464
	if (committed && !no_auto_trans)
465
	{
466
		if ((results = PQexec(actual_connection->connection, "begin transaction")) == NULL)
467
		{
468
			register_error(ECPG_TRANS, "Error starting transaction line %d.", stmt->lineno);
469 470 471 472 473 474
			return false;
		}
		PQclear(results);
		committed = 0;
	}

475
	ECPGlog("ECPGexecute line %d: QUERY: %s\n", stmt->lineno, copiedquery);
476
	results = PQexec(actual_connection->connection, copiedquery);
477 478 479 480
	free(copiedquery);

	if (results == NULL)
	{
481
		ECPGlog("ECPGexecute line %d: error: %s", stmt->lineno,
482
				PQerrorMessage(actual_connection->connection));
483
		register_error(ECPG_PGSQL, "Postgres error: %s line %d.",
484
					   PQerrorMessage(actual_connection->connection), stmt->lineno);
485 486
	}
	else
487 488
	{
		sqlca.sqlerrd[2] = 0;
489
		var = stmt->outlist;
490 491
		switch (PQresultStatus(results))
		{
492
				int			nfields, ntuples, act_tuple, act_field;
493 494

			case PGRES_TUPLES_OK:
495 496 497 498 499

				/*
				 * XXX Cheap Hack. For now, we see only the last group of
				 * tuples.	This is clearly not the right way to do things
				 * !!
500 501
				 */

502 503 504 505 506
				nfields = PQnfields(results);
				sqlca.sqlerrd[2] = ntuples = PQntuples(results);
				status = true;
				
				if (ntuples < 1)
507
				{
508 509 510
					ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d\n",
							stmt->lineno, ntuples);
					register_error(ECPG_NOT_FOUND, "Data not found line %d.", stmt->lineno);
511
					status = false;
512 513 514
					break;
				}

515 516 517 518 519
                                for (act_field = 0; act_field < nfields && status; act_field++)
                                {
                                     char	   *pval;
                                     char	   *scan_length;
                                             
520 521 522 523 524 525 526
                                     if (var == NULL)
                                     {
                                             ECPGlog("ECPGexecute line %d: Too few arguments.\n", stmt->lineno);
                                             register_error(ECPG_TOO_FEW_ARGUMENTS, "Too few arguments line %d.", stmt->lineno);
                                             return(false);
                                     }
                                     
527
                                     /* if we don't have enough space, we cannot read all tuples */
528
                                     if ((var->arrsize > 0 && ntuples > var->arrsize) || (var->ind_arrsize > 0 && ntuples > var->ind_arrsize))
529
                                     {
530 531 532
                                             ECPGlog("ECPGexecute line %d: Incorrect number of matches: %d don't fit into array of %d\n",
                                                             stmt->lineno, ntuples, var->arrsize);
                                             register_error(ECPG_TOO_MANY_MATCHES, "Too many matches line %d.", stmt->lineno);
533 534 535 536 537 538 539
                                             status = false;
                                             break;
                                     }
                                     for (act_tuple = 0; act_tuple < ntuples; act_tuple++)
                                     {
                                         pval = PQgetvalue(results, act_tuple, act_field);

540
                                         ECPGlog("ECPGexecute line %d: RESULT: %s\n", stmt->lineno, pval ? pval : "");
541

542 543
                                         /* Now the pval is a pointer to the var->value. */
                                         /* We will have to decode the var->value */
544
                                     
545 546
                                         /* check for null var->value and set indicator accordingly */
                                         switch (var->ind_type)
547 548 549
                                         {
                                                 case ECPGt_short:
                                                 case ECPGt_unsigned_short:
550
                                                         ((short *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
551 552 553
                                                         break;
                                                 case ECPGt_int:
                                                 case ECPGt_unsigned_int:
554
                                                         ((int *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
555 556 557
                                                         break;
                                                 case ECPGt_long:
                                                 case ECPGt_unsigned_long:
558
                                                         ((long *) var->ind_value)[act_tuple] = -PQgetisnull(results, act_tuple, act_field);
559 560 561 562 563
                                                         break;
                                                 default:
                                                         break;
                                         }
                                                                                 
564
                                         switch (var->type)
565 566 567 568 569 570 571 572 573 574 575 576 577 578
                                         {
                                                         long		res;
                                                         unsigned long ures;
                                                         double		dres;
    
                                                 case ECPGt_short:
                                                 case ECPGt_int:
                                                 case ECPGt_long:
                                                         if (pval)
                                                         {
                                                                 res = strtol(pval, &scan_length, 10);
                                                                 if (*scan_length != '\0')		/* Garbage left */
                                                                 {
                                                                         register_error(ECPG_INT_FORMAT, "Not correctly formatted int type: %s line %d.",
579
                                                                                                    pval, stmt->lineno);
580 581 582 583 584 585 586 587
                                                                         status = false;
                                                                         res = 0L;
                                                                 }
                                                         }
                                                         else
                                                                 res = 0L;
    
                                                         /* Again?! Yes */
588
                                                         switch (var->type)
589 590
                                                         {
                                                                 case ECPGt_short:
591
                                                                         ((short *) var->value)[act_tuple] = (short) res;
592 593
                                                                         break;
                                                                 case ECPGt_int:
594
                                                                         ((int *) var->value)[act_tuple] = (int) res;
595 596
                                                                         break;
                                                                 case ECPGt_long:
597
                                                                         ((long *) var->value)[act_tuple] = res;
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
                                                                         break;
                                                                 default:
                                                                         /* Cannot happen */
                                                                         break;
                                                         }
                                                         break;
    
                                                 case ECPGt_unsigned_short:
                                                 case ECPGt_unsigned_int:
                                                 case ECPGt_unsigned_long:
                                                         if (pval)
                                                         {
                                                                 ures = strtoul(pval, &scan_length, 10);
                                                                 if (*scan_length != '\0')		/* Garbage left */
                                                                 {
                                                                         register_error(ECPG_UINT_FORMAT, "Not correctly formatted unsigned type: %s line %d.",
614
                                                                                                    pval, stmt->lineno);
615 616 617 618 619 620 621 622
                                                                         status = false;
                                                                         ures = 0L;
                                                                 }
                                                         }
                                                         else
                                                                 ures = 0L;
    
                                                         /* Again?! Yes */
623
                                                         switch (var->type)
624 625
                                                         {
                                                                 case ECPGt_unsigned_short:
626
                                                                         ((unsigned short *) var->value)[act_tuple] = (unsigned short) ures;
627 628
                                                                         break;
                                                                 case ECPGt_unsigned_int:
629
                                                                         ((unsigned int *) var->value)[act_tuple] = (unsigned int) ures;
630 631
                                                                         break;
                                                                 case ECPGt_unsigned_long:
632
                                                                         ((unsigned long *) var->value)[act_tuple] = ures;
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648
                                                                         break;
                                                                 default:
                                                                         /* Cannot happen */
                                                                         break;
                                                         }
                                                         break;
    
    
                                                 case ECPGt_float:
                                                 case ECPGt_double:
                                                         if (pval)
                                                         {
                                                                 dres = strtod(pval, &scan_length);
                                                                 if (*scan_length != '\0')		/* Garbage left */
                                                                 {
                                                                         register_error(ECPG_FLOAT_FORMAT, "Not correctly formatted floating point type: %s line %d.",
649
                                                                                                    pval, stmt->lineno);
650 651 652 653 654 655 656 657
                                                                         status = false;
                                                                         dres = 0.0;
                                                                 }
                                                         }
                                                         else
                                                                 dres = 0.0;
    
                                                         /* Again?! Yes */
658
                                                         switch (var->type)
659 660
                                                         {
                                                                 case ECPGt_float:
661
                                                                         ((float *) var->value)[act_tuple] = dres;
662 663
                                                                         break;
                                                                 case ECPGt_double:
664
                                                                         ((double *) var->value)[act_tuple] = dres;
665 666 667 668 669 670 671 672 673 674 675 676
                                                                         break;
                                                                 default:
                                                                         /* Cannot happen */
                                                                         break;
                                                         }
                                                         break;
    
                                                 case ECPGt_bool:
                                                         if (pval)
                                                         {
                                                                 if (pval[0] == 'f' && pval[1] == '\0')
                                                                 {
677
                                                                         ((char *) var->value)[act_tuple] = false;
678 679 680 681
                                                                         break;
                                                                 }
                                                                 else if (pval[0] == 't' && pval[1] == '\0')
                                                                 {
682
                                                                         ((char *) var->value)[act_tuple] = true;
683 684 685 686 687 688
                                                                         break;
                                                                 }
                                                         }
    
                                                         register_error(ECPG_CONVERT_BOOL, "Unable to convert %s to bool on line %d.",
                                                                                    (pval ? pval : "NULL"),
689
                                                                                    stmt->lineno);
690 691 692 693 694 695
                                                         status = false;
                                                         break;
    
                                                 case ECPGt_char:
                                                 case ECPGt_unsigned_char:
                                                         {
696
                                                                 if (var->varcharsize == 0)
697 698
                                                                 {
                                                                         /* char* */
699 700
                                                                         strncpy(((char **) var->value)[act_tuple], pval, strlen(pval));
                                                                         (((char **) var->value)[act_tuple])[strlen(pval)] = '\0';
701 702 703
                                                                 }
                                                                 else
                                                                 {
704 705
                                                                         strncpy((char *) (var->value + var->offset * act_tuple), pval, var->varcharsize);
                                                                         if (var->varcharsize < strlen(pval))
706 707
                                                                         {
                                                                                 /* truncation */
708
                                                                                 switch (var->ind_type)
709 710 711
                                                                                 {
                                                                                         case ECPGt_short:
                                                                                         case ECPGt_unsigned_short:
712
                                                                                                 ((short *) var->ind_value)[act_tuple] = var->varcharsize;
713 714 715
                                                                                                 break;
                                                                                         case ECPGt_int:
                                                                                         case ECPGt_unsigned_int:
716
                                                                                                 ((int *) var->ind_value)[act_tuple] = var->varcharsize;
717 718 719
                                                                                                 break;
                                                                                         case ECPGt_long:
                                                                                         case ECPGt_unsigned_long:
720
                                                                                                 ((long *) var->ind_value)[act_tuple] = var->varcharsize;
721 722 723 724
                                                                                                 break;
                                                                                         default:
                                                                                                 break;
                                                                                 }
725
                                                                                 sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
726 727 728 729 730 731 732
                                                                         }
                                                                 }
                                                         }
                                                         break;
    
                                                 case ECPGt_varchar:
                                                         {
733 734
                                                                 struct ECPGgeneric_varchar *variable =
								 (struct ECPGgeneric_varchar *) (var->value + var->offset * act_tuple);
735
    
736 737
								 if (var->varcharsize == 0)
								   strncpy(variable->arr, pval, strlen(pval));
738
								 else
739
								   strncpy(variable->arr, pval, var->varcharsize);
740

741 742
                                                                 variable->len = strlen(pval);
                                                                 if (var->varcharsize > 0 && variable->len > var->varcharsize)
743 744
                                                                 {
                                                                         /* truncation */
745
                                                                         switch (var->ind_type)
746 747 748
                                                                         {
                                                                                 case ECPGt_short:
                                                                                 case ECPGt_unsigned_short:
749
                                                                                         ((short *) var->ind_value)[act_tuple] = var->varcharsize;
750 751 752
                                                                                         break;
                                                                                 case ECPGt_int:
                                                                                 case ECPGt_unsigned_int:
753
                                                                                         ((int *) var->ind_value)[act_tuple] = var->varcharsize;
754 755 756
                                                                                         break;
                                                                                 case ECPGt_long:
                                                                                 case ECPGt_unsigned_long:
757
                                                                                         ((long *) var->ind_value)[act_tuple] = var->varcharsize;
758 759 760 761
                                                                                         break;
                                                                                 default:
                                                                                         break;
                                                                         }
762
                                                                         sqlca.sqlwarn[0] = sqlca.sqlwarn[1] = 'W';
763
    
764
                                                                         variable->len = var->varcharsize;
765 766 767 768 769 770
                                                                 }
                                                         }
                                                         break;
    
                                                 default:
                                                         register_error(ECPG_UNSUPPORTED, "Unsupported type %s on line %d.",
771
                                                                                    ECPGtype_name(var->type), stmt->lineno);
772 773 774 775
                                                         status = false;
                                                         break;
                                         }
                                     }
776
				     var = var->next;
777 778
				}

779
				if (status && var != NULL)
780
				{
781
					register_error(ECPG_TOO_MANY_ARGUMENTS, "Too many arguments line %d.", stmt->lineno);
782
					status = false;
783 784 785 786 787 788
				}

				PQclear(results);
				break;
			case PGRES_EMPTY_QUERY:
				/* do nothing */
789
				register_error(ECPG_EMPTY, "Empty query line %d.", stmt->lineno);
790 791 792
				break;
			case PGRES_COMMAND_OK:
				status = true;
793
				sqlca.sqlerrd[2] = atol(PQcmdTuples(results));
794
				ECPGlog("ECPGexecute line %d Ok: %s\n", stmt->lineno, PQcmdStatus(results));
795 796 797 798
				break;
			case PGRES_NONFATAL_ERROR:
			case PGRES_FATAL_ERROR:
			case PGRES_BAD_RESPONSE:
799 800
				ECPGlog("ECPGexecute line %d: Error: %s",
						stmt->lineno, PQerrorMessage(actual_connection->connection));
801
				register_error(ECPG_PGSQL, "Error: %s line %d.",
802
							   PQerrorMessage(actual_connection->connection), stmt->lineno);
803
				status = false;
804 805
				break;
			case PGRES_COPY_OUT:
806
				ECPGlog("ECPGexecute line %d: Got PGRES_COPY_OUT ... tossing.\n", stmt->lineno);
807 808 809
				PQendcopy(results->conn);
				break;
			case PGRES_COPY_IN:
810
				ECPGlog("ECPGexecute line %d: Got PGRES_COPY_IN ... tossing.\n", stmt->lineno);
811 812 813
				PQendcopy(results->conn);
				break;
			default:
814 815 816
				ECPGlog("ECPGexecute line %d: Got something else, postgres error.\n",
						stmt->lineno);
				register_error(ECPG_PGSQL, "Postgres error line %d.", stmt->lineno);
817
				status = false;
818 819
				break;
		}
820
	}
821 822

	/* check for asynchronous returns */
823
	notify = PQnotifies(actual_connection->connection);
824 825
	if (notify)
	{
826 827
		ECPGlog("ECPGexecute line %d: ASYNC NOTIFY of '%s' from backend pid '%d' received\n",
				stmt->lineno, notify->relname, notify->be_pid);
828 829 830 831 832 833 834
		free(notify);
	}

	va_end(ap);
	return status;
}

835 836 837 838 839 840 841 842 843 844
bool
ECPGdo(int lineno, char *query, ...)
{
	va_list			args;
	struct statement	*stmt;
	                                                                                                                                                     
	va_start(args, query);
	if (create_statement(lineno, &stmt, query, args) == false)
		return(false);
	va_end(args);
845 846 847 848 849 850 851 852 853

	/* are we connected? */
	if (actual_connection == NULL || actual_connection->connection == NULL)
	{		
		ECPGlog("ECPGdo: not connected\n");
		register_error(ECPG_NOT_CONN, "Not connected in line %d", lineno);
		return false;
	}		

854 855 856
	return(ECPGexecute(stmt));
}

857 858

bool
859
ECPGtrans(int lineno, const char * transaction)
860 861 862
{
	PGresult   *res;

863
	ECPGlog("ECPGtrans line %d action = %s\n", lineno, transaction);
864
	if ((res = PQexec(actual_connection->connection, transaction)) == NULL)
865
	{
866
		register_error(ECPG_TRANS, "Error in transaction processing line %d.", lineno);
867 868 869
		return (FALSE);
	}
	PQclear(res);
870 871
	if (strcmp(transaction, "commit") == 0 || strcmp(transaction, "rollback") == 0)
		committed = 1;
872 873 874 875
	return (TRUE);
}

bool
876
ECPGsetconn(int lineno, const char *connection_name)
877
{
878
	struct connection *con = all_connections;
879 880

	ECPGlog("ECPGsetconn: setting actual connection to %s\n", connection_name);	
881
	
882
	for (; con && strcmp(connection_name, con->name) != 0; con=con->next);
883 884 885 886 887 888 889 890 891 892
	if (con)
	{
		actual_connection = con;
		return true;
	}
	else
	{
		register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
		return false;
	}
893 894 895
}

bool
896
ECPGconnect(int lineno, const char *dbname, const char *user, const char *passwd, const char * connection_name)
897
{
898
	struct connection *this = (struct connection *) ecpg_alloc(sizeof(struct connection), lineno);
899

900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
	if (!this)
		return false;
				
	if (dbname == NULL && connection_name == NULL)
		connection_name = "DEFAULT";
	
	/* add connection to our list */
	if (connection_name != NULL)
		this->name = strdup(connection_name);
	else
		this->name = strdup(dbname);
	
	if (all_connections == NULL)
		this->next = NULL;
	else
		this->next = all_connections;
916

917 918 919
	actual_connection = all_connections = this;
		
	ECPGlog("ECPGconnect: opening database %s %s%s\n", dbname ? dbname : "NULL", user ? "for user ": "", user ? user : "");
920

921
	sqlca.sqlcode = 0;
922

923 924 925
	this->connection = PQsetdbLogin(NULL, NULL, NULL, NULL, dbname, user, passwd);
        
	if (PQstatus(this->connection) == CONNECTION_BAD)
926
	{
927 928 929
		ECPGfinish(this);
                ECPGlog("connect: could not open database %s %s%s in line %d\n", dbname ? dbname : "NULL", user ? "for user ": "", user ? user : "", lineno);
		register_error(ECPG_CONNECT, "connect: could not open database %s.", dbname ? dbname : "NULL");
930 931
		return false;
	}
932
	
933 934 935 936
	return true;
}

bool
937
ECPGdisconnect(int lineno, const char *connection_name)
938
{
939 940 941 942 943
	struct connection *con;
	
	if (strcmp(connection_name, "CURRENT") == 0)
		ECPGfinish(actual_connection);
	else if (strcmp(connection_name, "ALL") == 0)
944
	{
945 946 947 948 949 950 951
		for (con = all_connections; con;)
		{
			struct connection *f = con;
			
			con = con->next;
			ECPGfinish(f);
		}
952
	}
953
	else 
954
	{
955
		for (con = all_connections; con && strcmp(con->name, connection_name) != 0;con = con->next);
956 957 958 959 960 961 962
		if (con == NULL)
		{		
			ECPGlog("disconnect: not connected to connection %s\n", connection_name);
			register_error(ECPG_NO_CONN, "No such connection %s in line %d", connection_name, lineno);
			return false;
		}
		else
963
		{
964
			ECPGfinish(con);
965
		}
966
	}
967
	
968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987
	return true;
}

void
ECPGdebug(int n, FILE *dbgs)
{
	simple_debug = n;
	debugstream = dbgs;
	ECPGlog("ECPGdebug: set to %d\n", simple_debug);
}

void
ECPGlog(const char *format,...)
{
	va_list		ap;

	if (simple_debug)
	{
		char	   *f = (char *) malloc(strlen(format) + 100);

988 989 990
		if (!f)
			return;
						
991 992 993 994 995 996 997 998 999
		sprintf(f, "[%d]: %s", getpid(), format);

		va_start(ap, format);
		vfprintf(debugstream, f, ap);
		va_end(ap);

		free(f);
	}
}
1000 1001

/* print out an error message */
1002 1003
void
sqlprint(void)
1004 1005
{
	sqlca.sqlerrm.sqlerrmc[sqlca.sqlerrm.sqlerrml] = '\0';
1006
	printf("sql error %s\n", sqlca.sqlerrm.sqlerrmc);
1007
}