mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	From: Michael Meskes <meskes@topsystem.de>
And the next update. Now you can use only parts of a struct like this: exec sql select a into :struct.string from foo;
This commit is contained in:
		
							parent
							
								
									3e3477f5a4
								
							
						
					
					
						commit
						718430ea40
					
				| @ -142,3 +142,10 @@ Fri Apr 24 13:50:15 CEST 1998 | ||||
| 
 | ||||
| 	- Fixed some bugs. | ||||
| 	- Set version to 2.1.1 | ||||
| 
 | ||||
| Mon Apr 27 14:26:55 CEST 1998 | ||||
| 
 | ||||
| 	- Parser now able to understand and process syntax like :foo->bar | ||||
| 	  and :foo.bar as variables. | ||||
| 	- Set version to 2.2.0 | ||||
| 
 | ||||
|  | ||||
| @ -53,6 +53,3 @@ exec sql disconnect {current|default|all|connectionname|connection_hostvar}; | ||||
|  commit release|commit work release auch disconnect | ||||
| 
 | ||||
| It is not neccessary to check for "not found" after all commands. | ||||
| 
 | ||||
| It would be nice to be able to specify parts of a structure like :foo.bar or | ||||
| :foo->bar. | ||||
|  | ||||
| @ -18,7 +18,7 @@ | ||||
|  * Complex types: | ||||
|  * VARCHAR, VARCHAR2 - Strings with length (maxlen is given in the declaration) | ||||
|  * Arrays of simple types and of VARCHAR, VARCHAR2 (size given in declaration) | ||||
|  * Records build of simple types, arrays and other records. | ||||
|  * Records build of simple types, arrays and other structs. | ||||
|  * | ||||
|  * Complicating things: | ||||
|  * typedefs and struct names! | ||||
| @ -41,7 +41,7 @@ enum ECPGttype | ||||
| 	ECPGt_float, ECPGt_double, | ||||
| 	ECPGt_varchar, ECPGt_varchar2, | ||||
| 	ECPGt_array, | ||||
| 	ECPGt_record, | ||||
| 	ECPGt_struct, | ||||
| 	ECPGt_EOIT,					/* End of insert types. */ | ||||
| 	ECPGt_EORT,					/* End of result types. */ | ||||
| 	ECPGt_NO_INDICATOR				/* no indicator */ | ||||
|  | ||||
| @ -2,8 +2,8 @@ SRCDIR= ../../.. | ||||
| include $(SRCDIR)/Makefile.global | ||||
| 
 | ||||
| MAJOR_VERSION=2 | ||||
| MINOR_VERSION=1 | ||||
| PATCHLEVEL=1 | ||||
| MINOR_VERSION=2 | ||||
| PATCHLEVEL=0 | ||||
| 
 | ||||
| CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \
 | ||||
| 	-DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \
 | ||||
|  | ||||
| @ -306,6 +306,7 @@ sql     [sS][qQ][lL] | ||||
| 					return (yytext[0]); | ||||
| 				} | ||||
| <SQL>{self}				{ 	return (yytext[0]); } | ||||
| <SQL>"->"                      { return S_STRUCTPOINTER; } | ||||
| <SQL>{operator}/-[\.0-9]	{ | ||||
| 					yylval.str = strdup((char*)yytext); | ||||
| 					return (Op); | ||||
|  | ||||
| @ -17,8 +17,8 @@ static int      QueryIsRule = 0; | ||||
| static enum ECPGttype actual_type[128]; | ||||
| static char     *actual_storage[128]; | ||||
| 
 | ||||
| /* temporarily store record members while creating the data structure */ | ||||
| struct ECPGrecord_member *record_member_list[128] = { NULL }; | ||||
| /* temporarily store struct members while creating the data structure */ | ||||
| struct ECPGstruct_member *struct_member_list[128] = { NULL }; | ||||
| 
 | ||||
| /* keep a list of cursors */ | ||||
| struct cursor *cur = NULL; | ||||
| @ -89,26 +89,6 @@ int braces_open; | ||||
| static struct variable * allvariables = NULL; | ||||
| 
 | ||||
| static struct variable * | ||||
| find_variable(char * name) | ||||
| { | ||||
|     struct variable * p; | ||||
|     char * errorstring = (char *) mm_alloc(strlen(name) + 100); | ||||
| 
 | ||||
|     for (p = allvariables; p; p = p->next) | ||||
|     { | ||||
|         if (strcmp(p->name, name) == 0) | ||||
| 	    return p; | ||||
|     } | ||||
| 
 | ||||
|     sprintf(errorstring, "The variable %s is not declared", name); | ||||
|     yyerror(errorstring); | ||||
|     free (errorstring); | ||||
| 
 | ||||
|     return NULL; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void | ||||
| new_variable(const char * name, struct ECPGtype * type) | ||||
| { | ||||
|     struct variable * p = (struct variable*) mm_alloc(sizeof(struct variable)); | ||||
| @ -119,6 +99,97 @@ new_variable(const char * name, struct ECPGtype * type) | ||||
| 
 | ||||
|     p->next = allvariables; | ||||
|     allvariables = p; | ||||
| 
 | ||||
|     return(p); | ||||
| } | ||||
| 
 | ||||
| static struct variable * find_variable(char * name); | ||||
| 
 | ||||
| static struct variable * | ||||
| find_struct_member(char *name, char *str, struct ECPGstruct_member *members) | ||||
| { | ||||
|     char *next = strpbrk(++str, ".-"), c = '\0'; | ||||
| 
 | ||||
|     if (next != NULL) | ||||
|     { | ||||
| 	c = *next; | ||||
| 	*next = '\0'; | ||||
|     } | ||||
| 
 | ||||
|     for (; members; members = members->next) | ||||
|     { | ||||
|         if (strcmp(members->name, str) == 0) | ||||
| 	{ | ||||
| 		if (c == '\0') | ||||
| 		{ | ||||
| 			/* found the end */ | ||||
| 			switch (members->typ->typ) | ||||
| 			{ | ||||
| 			   case ECPGt_struct: | ||||
| 				return(new_variable(name, ECPGmake_struct_type(members->typ->u.members))); | ||||
| 			   case ECPGt_varchar: | ||||
| 				return(new_variable(name, ECPGmake_varchar_type(members->typ->typ, members->typ->size))); | ||||
| 			   default: | ||||
| 				return(new_variable(name, ECPGmake_simple_type(members->typ->typ, members->typ->size))); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			*next = c; | ||||
| 			if (c == '-') next++; | ||||
| 			return(find_struct_member(name, next, members->typ->u.members)); | ||||
| 		} | ||||
| 	} | ||||
|     } | ||||
| 
 | ||||
|     return(NULL); | ||||
| } | ||||
| 
 | ||||
| static struct variable * | ||||
| find_struct(char * name, char *next) | ||||
| { | ||||
|     struct variable * p; | ||||
|     char c = *next; | ||||
| 
 | ||||
|     /* first get the mother structure entry */ | ||||
|     *next = '\0'; | ||||
|     p = find_variable(name); | ||||
| 
 | ||||
|     /* restore the name, we will need it later on */ | ||||
|     *next = c; | ||||
|     if (*next == '-') next++; | ||||
| 
 | ||||
|     return (find_struct_member(name, next, p->type->u.members)); | ||||
| } | ||||
| 
 | ||||
| static struct variable * | ||||
| find_simple(char * name) | ||||
| { | ||||
|     struct variable * p; | ||||
| 
 | ||||
|     for (p = allvariables; p; p = p->next) | ||||
|     { | ||||
|         if (strcmp(p->name, name) == 0) | ||||
| 	    return p; | ||||
|     } | ||||
| 
 | ||||
|     return(NULL); | ||||
| } | ||||
| 
 | ||||
| static struct variable * | ||||
| find_variable(char * name) | ||||
| { | ||||
|     char * next; | ||||
|     struct variable * p = | ||||
|     	((next = strpbrk(name, ".-")) != NULL) ? find_struct(name, next) : find_simple(name); | ||||
| 
 | ||||
|     if (p == NULL) | ||||
|     { | ||||
| 	sprintf(errortext, "The variable %s is not declared", name); | ||||
| 	yyerror(errortext); | ||||
|     } | ||||
| 
 | ||||
|     return(p); | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| @ -215,7 +286,7 @@ check_indicator(struct ECPGtype *var) | ||||
| 	/* make sure this is a valid indicator variable */ | ||||
| 	switch (var->typ) | ||||
| 	{ | ||||
| 		struct ECPGrecord_member *p; | ||||
| 		struct ECPGstruct_member *p; | ||||
| 
 | ||||
| 		case ECPGt_short: | ||||
| 		case ECPGt_int: | ||||
| @ -225,7 +296,7 @@ check_indicator(struct ECPGtype *var) | ||||
| 		case ECPGt_unsigned_long: | ||||
| 			break; | ||||
| 
 | ||||
| 		case ECPGt_record: | ||||
| 		case ECPGt_struct: | ||||
| 			for (p = var->u.members; p; p = p->next) | ||||
| 				check_indicator(p->typ); | ||||
| 			break; | ||||
| @ -392,8 +463,8 @@ output_statement(const char * stmt) | ||||
| /* C token */ | ||||
| %token		S_ANYTHING S_AUTO S_BOOL S_CHAR S_CONST S_DOUBLE S_EXTERN | ||||
| %token		S_FLOAT S_INT | ||||
| %token		S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT S_UNSIGNED | ||||
| %token		S_VARCHAR | ||||
| %token		S_LONG S_REGISTER S_SHORT S_SIGNED S_STATIC S_STRUCT  | ||||
| %token		S_STRUCTPOINTER S_UNSIGNED S_VARCHAR | ||||
| 
 | ||||
| /* I need this and don't know where it is defined inside the backend */ | ||||
| %token		TYPECAST | ||||
| @ -3704,7 +3775,7 @@ declaration: storage_clause type | ||||
| 	{ | ||||
| 		actual_storage[struct_level] = $1; | ||||
| 		actual_type[struct_level] = $2; | ||||
| 		if ($2 != ECPGt_varchar && $2 != ECPGt_record) | ||||
| 		if ($2 != ECPGt_varchar && $2 != ECPGt_struct) | ||||
| 			fprintf(yyout, "%s %s", $1, ECPGtype_name($2)); | ||||
| 	} | ||||
| 	variable_list ';' { fputc(';', yyout); } | ||||
| @ -3723,11 +3794,13 @@ type: simple_type | ||||
| struct_type: s_struct '{' variable_declarations '}' | ||||
| 	{ | ||||
| 	    struct_level--; | ||||
| 	    $$ = actual_type[struct_level] = ECPGt_record; | ||||
| 	    fputs("} ", yyout); | ||||
| 	    $$ = ECPGt_struct; | ||||
| 	} | ||||
| 
 | ||||
| s_struct : S_STRUCT symbol | ||||
| 	{ | ||||
| 		struct_member_list[struct_level] = NULL; | ||||
| 		struct_level++; | ||||
| 		fprintf(yyout, "struct %s {", $2); | ||||
| 	} | ||||
| @ -3764,14 +3837,13 @@ variable: opt_pointer symbol opt_index opt_initializer | ||||
| 
 | ||||
| 			switch (actual_type[struct_level]) | ||||
| 			{ | ||||
| 			   case ECPGt_record: | ||||
| 			   case ECPGt_struct: | ||||
| 				if (struct_level == 0) | ||||
| 					new_variable($2, ECPGmake_record_type(record_member_list[struct_level])); | ||||
| 					new_variable($2, ECPGmake_struct_type(struct_member_list[struct_level])); | ||||
| 				else | ||||
| 				        ECPGmake_record_member($2, ECPGmake_record_type(record_member_list[struct_level]), &(record_member_list[struct_level-1])); | ||||
| 				        ECPGmake_struct_member($2, ECPGmake_struct_type(struct_member_list[struct_level]), &(struct_member_list[struct_level-1])); | ||||
| 
 | ||||
| 				record_member_list[struct_level] = NULL; | ||||
| 		 		fprintf(yyout, "} %s%s%s%s", $1, $2, $3.str, $4); | ||||
| 		 		fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4); | ||||
| 
 | ||||
| 				break; | ||||
| 			   case ECPGt_varchar: | ||||
| @ -3781,7 +3853,7 @@ variable: opt_pointer symbol opt_index opt_initializer | ||||
| 				if (struct_level == 0)  | ||||
| 					new_variable($2, ECPGmake_varchar_type(actual_type[struct_level], length)); | ||||
| 				else | ||||
| 				        ECPGmake_record_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(record_member_list[struct_level-1])); | ||||
| 				        ECPGmake_struct_member($2, ECPGmake_varchar_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1])); | ||||
| 				 | ||||
| 				if (length > 0) | ||||
| 					fprintf(yyout, "%s struct varchar_%s { int len; char arr[%d]; } %s", actual_storage[struct_level], $2, length, $2); | ||||
| @ -3794,7 +3866,7 @@ variable: opt_pointer symbol opt_index opt_initializer | ||||
| 				if (struct_level == 0) | ||||
| 					new_variable($2, ECPGmake_simple_type(actual_type[struct_level], length)); | ||||
| 				else | ||||
| 				        ECPGmake_record_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(record_member_list[struct_level-1])); | ||||
| 				        ECPGmake_struct_member($2, ECPGmake_simple_type(actual_type[struct_level], length), &(struct_member_list[struct_level-1])); | ||||
| 
 | ||||
| 				fprintf(yyout, "%s%s%s%s", $1, $2, $3.str, $4); | ||||
| 
 | ||||
| @ -4230,15 +4302,15 @@ civariableonly : cvariable name { | ||||
| } | ||||
| 
 | ||||
| cvariable: CVARIABLE			{ $$ = $1; } | ||||
| 	| CVARIABLE '.' identlist	{ $$ = $1; } | ||||
| 	| CVARIABLE '-' '>' identlist	{ $$ = $1; } | ||||
| 	| CVARIABLE '.' identlist	{ $$ = cat3_str($1, ".", $3); } | ||||
| 	| CVARIABLE S_STRUCTPOINTER identlist	{ $$ = cat3_str($1, "->", $3); } | ||||
| 
 | ||||
| identlist: IDENT			{ $$ = $1; } | ||||
| 	| IDENT '.' identlist		{ $$ = $1; } | ||||
| 	| IDENT '-' '>' identlist   { $$ = $1; } | ||||
| 	| IDENT '.' identlist		{ $$ = cat3_str($1, ".", $3); } | ||||
| 	| IDENT S_STRUCTPOINTER identlist   { $$ = cat3_str($1, "->", $3); } | ||||
| 
 | ||||
| indicator: /* empty */			{ $$ = NULL; } | ||||
| 	| cvariable		 	{ check_indicator((find_variable($1))->type); $$ = $1; } | ||||
| 	| cvariable		 	{ printf("## %s\n", $1); check_indicator((find_variable($1))->type); $$ = $1; } | ||||
| 	| SQL_INDICATOR cvariable 	{ check_indicator((find_variable($2))->type); $$ = $2; } | ||||
| 	| SQL_INDICATOR name		{ check_indicator((find_variable($2))->type); $$ = $2; } | ||||
| 
 | ||||
|  | ||||
| @ -40,12 +40,12 @@ mm_realloc(void *ptr, size_t size) | ||||
|  */ | ||||
| 
 | ||||
| /* The NAME argument is copied. The type argument is preserved as a pointer. */ | ||||
| struct ECPGrecord_member * | ||||
| ECPGmake_record_member(char *name, struct ECPGtype * type, struct ECPGrecord_member ** start) | ||||
| struct ECPGstruct_member * | ||||
| ECPGmake_struct_member(char *name, struct ECPGtype * type, struct ECPGstruct_member ** start) | ||||
| { | ||||
| 	struct ECPGrecord_member *ptr, | ||||
| 	struct ECPGstruct_member *ptr, | ||||
| 			   *ne = | ||||
| 	(struct ECPGrecord_member *) mm_alloc(sizeof(struct ECPGrecord_member)); | ||||
| 	(struct ECPGstruct_member *) mm_alloc(sizeof(struct ECPGstruct_member)); | ||||
| 
 | ||||
| 	ne->name = strdup(name); | ||||
| 	ne->typ = type; | ||||
| @ -94,9 +94,9 @@ ECPGmake_array_type(struct ECPGtype * typ, long siz) | ||||
| } | ||||
| 
 | ||||
| struct ECPGtype * | ||||
| ECPGmake_record_type(struct ECPGrecord_member * rm) | ||||
| ECPGmake_struct_type(struct ECPGstruct_member * rm) | ||||
| { | ||||
| 	struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_record, 1); | ||||
| 	struct ECPGtype *ne = ECPGmake_simple_type(ECPGt_struct, 1); | ||||
| 
 | ||||
| 	ne->u.members = rm; | ||||
| 
 | ||||
| @ -116,14 +116,14 @@ ECPGmake_record_type(struct ECPGrecord_member * rm) | ||||
|    reference-to-variable can be a reference to a struct element. | ||||
|    arrsize is the size of the array in case of array fetches. Otherwise 0. | ||||
|    size is the maxsize in case it is a varchar. Otherwise it is the size of | ||||
|    the variable (required to do array fetches of records). | ||||
|    the variable (required to do array fetches of structs). | ||||
|  */ | ||||
| void | ||||
| ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, | ||||
| 				  long varcharsize, | ||||
| 				  long arrsiz, const char *siz, const char *prefix); | ||||
| void | ||||
| ECPGdump_a_record(FILE *o, const char *name, const char *ind_name, long arrsiz, | ||||
| ECPGdump_a_struct(FILE *o, const char *name, const char *ind_name, long arrsiz, | ||||
| 		  struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offset, const char *prefix, const char * ind_prefix); | ||||
| 
 | ||||
| 
 | ||||
| @ -154,19 +154,19 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in | ||||
| 		{ | ||||
| 			abort();			/* Array of array, */ | ||||
| 		} | ||||
| 		else if (typ->u.element->typ == ECPGt_record) | ||||
| 		else if (typ->u.element->typ == ECPGt_struct) | ||||
| 		{ | ||||
| 			/* Array of records. */ | ||||
| 			ECPGdump_a_record(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix); | ||||
| 			/* Array of structs. */ | ||||
| 			ECPGdump_a_struct(o, name, ind_name, typ->size, typ->u.element, ind_typ->u.element, 0, prefix, ind_prefix); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			abort(); | ||||
| 		} | ||||
| 	} | ||||
| 	else if (typ->typ == ECPGt_record) | ||||
| 	else if (typ->typ == ECPGt_struct) | ||||
| 	{ | ||||
| 		ECPGdump_a_record(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix); | ||||
| 		ECPGdump_a_struct(o, name, ind_name, 0, typ, ind_typ, 0, prefix, ind_prefix); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @ -176,7 +176,7 @@ ECPGdump_a_type(FILE *o, const char *name, struct ECPGtype * typ, const char *in | ||||
| 
 | ||||
| 
 | ||||
| /* If siz is NULL, then the offset is 0, if not use siz as a
 | ||||
|    string, it represents the offset needed if we are in an array of records. */ | ||||
|    string, it represents the offset needed if we are in an array of structs. */ | ||||
| void | ||||
| ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, | ||||
| 				  long varcharsize, | ||||
| @ -189,66 +189,66 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, | ||||
| 	{ | ||||
| 			case ECPGt_char: | ||||
| 			if (varcharsize == 0)		/* pointer */ | ||||
| 				fprintf(o, "\n\tECPGt_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, | ||||
| 				fprintf(o, "\n\tECPGt_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, | ||||
| 						siz == NULL ? "sizeof(char)" : siz); | ||||
| 			else | ||||
| 				fprintf(o, "\n\tECPGt_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, | ||||
| 				fprintf(o, "\n\tECPGt_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, | ||||
| 						siz == NULL ? "sizeof(char)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_unsigned_char: | ||||
| 			if (varcharsize == 0)		/* pointer */ | ||||
| 				fprintf(o, "\n\tECPGt_unsigned_char,%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, | ||||
| 				fprintf(o, "\n\tECPGt_unsigned_char,(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, | ||||
| 						siz == NULL ? "sizeof(char)" : siz); | ||||
| 			else | ||||
| 				fprintf(o, "\n\tECPGt_unsigned_char,&%s%s,%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, | ||||
| 				fprintf(o, "\n\tECPGt_unsigned_char,&(%s%s),%ldL,%ldL,%s, ", prefix ? prefix : "", name, varcharsize, arrsiz, | ||||
| 						siz == NULL ? "sizeof(unsigned char)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_short: | ||||
| 			fprintf(o, "\n\tECPGt_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 			fprintf(o, "\n\tECPGt_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(short)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_unsigned_short: | ||||
| 			fprintf(o, | ||||
| 					"\n\tECPGt_unsigned_short,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					"\n\tECPGt_unsigned_short,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(unsigned short)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_int: | ||||
| 			fprintf(o, "\n\tECPGt_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 			fprintf(o, "\n\tECPGt_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(int)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_unsigned_int: | ||||
| 			fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 			fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(unsigned int)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_long: | ||||
| 			fprintf(o, "\n\tECPGt_long,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 			fprintf(o, "\n\tECPGt_long,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(long)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_unsigned_long: | ||||
| 			fprintf(o, "\n\tECPGt_unsigned_int,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 			fprintf(o, "\n\tECPGt_unsigned_int,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(unsigned int)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_float: | ||||
| 			fprintf(o, "\n\tECPGt_float,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 			fprintf(o, "\n\tECPGt_float,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(float)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_double: | ||||
| 			fprintf(o, "\n\tECPGt_double,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 			fprintf(o, "\n\tECPGt_double,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(double)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_bool: | ||||
| 			fprintf(o, "\n\tECPGt_bool,&%s%s,0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 			fprintf(o, "\n\tECPGt_bool,&(%s%s),0L,%ldL,%s, ", prefix ? prefix : "", name, arrsiz, | ||||
| 					siz == NULL ? "sizeof(bool)" : siz); | ||||
| 			break; | ||||
| 		case ECPGt_varchar: | ||||
| 		case ECPGt_varchar2: | ||||
| 			if (siz == NULL) | ||||
| 				fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,sizeof(struct varchar_%s), ", | ||||
| 				fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,sizeof(struct varchar_%s), ", | ||||
| 						prefix ? prefix : "", name, | ||||
| 						varcharsize, | ||||
| 						arrsiz, name); | ||||
| 			else | ||||
| 				fprintf(o, "\n\tECPGt_varchar,&%s%s,%ldL,%ldL,%s, ", | ||||
| 				fprintf(o, "\n\tECPGt_varchar,&(%s%s),%ldL,%ldL,%s, ", | ||||
| 						prefix ? prefix : "", name, | ||||
| 						varcharsize, | ||||
| 						arrsiz, siz); | ||||
| @ -263,17 +263,17 @@ ECPGdump_a_simple(FILE *o, const char *name, enum ECPGttype typ, | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /* Penetrate a record and dump the contents. */ | ||||
| /* Penetrate a struct and dump the contents. */ | ||||
| void | ||||
| ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix) | ||||
| ECPGdump_a_struct(FILE *o, const char *name, const char * ind_name, long arrsiz, struct ECPGtype * typ, struct ECPGtype * ind_typ, const char *offsetarg, const char *prefix, const char *ind_prefix) | ||||
| { | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * If offset is NULL, then this is the first recursive level. If not | ||||
| 	 * then we are in a record in a record and the offset is used as | ||||
| 	 * then we are in a struct in a struct and the offset is used as | ||||
| 	 * offset. | ||||
| 	 */ | ||||
| 	struct ECPGrecord_member *p, *ind_p = NULL; | ||||
| 	struct ECPGstruct_member *p, *ind_p = NULL; | ||||
| 	char		obuf[BUFSIZ]; | ||||
| 	char		pbuf[BUFSIZ], ind_pbuf[BUFSIZ]; | ||||
| 	const char *offset; | ||||
| @ -306,18 +306,19 @@ ECPGdump_a_record(FILE *o, const char *name, const char * ind_name, long arrsiz, | ||||
| /* Freeing is not really that important. Since we throw away the process
 | ||||
|    anyway. Lets implement that last! */ | ||||
| 
 | ||||
| void | ||||
| ECPGfree_record_member(struct ECPGrecord_member * rm) | ||||
| /* won't work anymore because a list of members may appear in several locations */ | ||||
| /*void
 | ||||
| ECPGfree_struct_member(struct ECPGstruct_member * rm) | ||||
| { | ||||
| 	while (rm) | ||||
| 	{ | ||||
| 		struct ECPGrecord_member *p = rm; | ||||
| 		struct ECPGstruct_member *p = rm; | ||||
| 
 | ||||
| 		rm = rm->next; | ||||
| 		free(p->name); | ||||
| 		free(p); | ||||
| 	} | ||||
| } | ||||
| }*/ | ||||
| 
 | ||||
| void | ||||
| ECPGfree_type(struct ECPGtype * typ) | ||||
| @ -330,15 +331,17 @@ ECPGfree_type(struct ECPGtype * typ) | ||||
| 				free(typ->u.element); | ||||
| 			else if (typ->u.element->typ == ECPGt_array) | ||||
| 				abort();		/* Array of array, */ | ||||
| 			else if (typ->u.element->typ == ECPGt_record) | ||||
| 				/* Array of records. */ | ||||
| 				ECPGfree_record_member(typ->u.members); | ||||
| 			else if (typ->u.element->typ == ECPGt_struct) | ||||
| 				/* Array of structs. */ | ||||
| 				free(typ->u.members); | ||||
| 				/* ECPGfree_struct_member(typ->u.members);*/ | ||||
| 			else | ||||
| 				abort(); | ||||
| 		} | ||||
| 		else if (typ->typ == ECPGt_record) | ||||
| 		else if (typ->typ == ECPGt_struct) | ||||
| 		{ | ||||
| 			ECPGfree_record_member(typ->u.members); | ||||
| 			free(typ->u.members); | ||||
| 			/* ECPGfree_struct_member(typ->u.members);*/ | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| #include <ecpgtype.h> | ||||
| 
 | ||||
| struct ECPGtype; | ||||
| struct ECPGrecord_member | ||||
| struct ECPGstruct_member | ||||
| { | ||||
| 	char	   *name; | ||||
| 	struct ECPGtype *typ; | ||||
| 	struct ECPGrecord_member *next; | ||||
| 	struct ECPGstruct_member *next; | ||||
| }; | ||||
| 
 | ||||
| struct ECPGtype | ||||
| @ -19,20 +19,20 @@ struct ECPGtype | ||||
| 		struct ECPGtype *element;		/* For an array this is the type
 | ||||
| 										 * of the element */ | ||||
| 
 | ||||
| 		struct ECPGrecord_member *members; | ||||
| 		struct ECPGstruct_member *members; | ||||
| 		/* A pointer to a list of members. */ | ||||
| 	}			u; | ||||
| }; | ||||
| 
 | ||||
| /* Everything is malloced. */ | ||||
| struct ECPGrecord_member *ECPGmake_record_member(char *, struct ECPGtype *, struct ECPGrecord_member **); | ||||
| struct ECPGstruct_member *ECPGmake_struct_member(char *, struct ECPGtype *, struct ECPGstruct_member **); | ||||
| struct ECPGtype *ECPGmake_simple_type(enum ECPGttype, long); | ||||
| struct ECPGtype *ECPGmake_varchar_type(enum ECPGttype, long); | ||||
| struct ECPGtype *ECPGmake_array_type(struct ECPGtype *, long); | ||||
| struct ECPGtype *ECPGmake_record_type(struct ECPGrecord_member *); | ||||
| struct ECPGtype *ECPGmake_struct_type(struct ECPGstruct_member *); | ||||
| 
 | ||||
| /* Frees a type. */ | ||||
| void		ECPGfree_record_member(struct ECPGrecord_member *); | ||||
| void		ECPGfree_struct_member(struct ECPGstruct_member *); | ||||
| void		ECPGfree_type(struct ECPGtype *); | ||||
| 
 | ||||
| /* Dump a type.
 | ||||
| @ -43,7 +43,7 @@ void		ECPGfree_type(struct ECPGtype *); | ||||
|    reference-to-variable can be a reference to a struct element. | ||||
|    arrsize is the size of the array in case of array fetches. Otherwise 0. | ||||
|    size is the maxsize in case it is a varchar. Otherwise it is the size of | ||||
| 	   the variable (required to do array fetches of records). | ||||
| 	   the variable (required to do array fetches of structs). | ||||
|  */ | ||||
| void		ECPGdump_a_type(FILE *, const char *, struct ECPGtype *,  const char *, struct ECPGtype *, const char *, const char *); | ||||
| 
 | ||||
|  | ||||
| @ -60,7 +60,7 @@ exec sql end declare section; | ||||
| 
 | ||||
| 	while (not_found == 0) { | ||||
| 		strcpy(msg, "fetch"); | ||||
| 		exec sql fetch cur into :personal:ind_personal, :married:ind_married, :personal.birth.born; | ||||
| 		exec sql fetch cur into :personal:ind_personal, :married:ind_married; | ||||
| 		if (not_found == 0) | ||||
| 			printf ("%8.8s was born %d (age = %d) %s%s\n", personal.name.arr, personal.birth.born, personal.birth.age, ind_married ? "" : "and married ", ind_married ? "" : married); | ||||
| 	} | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user