Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3b7ab43

Browse filesBrowse files
author
Michael Meskes
committed
Add Oracle like handling of char arrays.
In some cases Oracle Pro*C handles char array differently than ECPG. This patch adds a Oracle compatibility mode to make ECPG behave like Pro*C. Patch by David Rader <davidr@openscg.com>
1 parent db2fc80 commit 3b7ab43
Copy full SHA for 3b7ab43

File tree

Expand file treeCollapse file tree

12 files changed

+513
-5
lines changed
Filter options
Expand file treeCollapse file tree

12 files changed

+513
-5
lines changed

‎src/interfaces/ecpg/ecpglib/data.c

Copy file name to clipboardExpand all lines: src/interfaces/ecpg/ecpglib/data.c
+47-2Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,7 +464,45 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
464464

465465
if (varcharsize == 0 || varcharsize > size)
466466
{
467-
strncpy(str, pval, size + 1);
467+
/* compatibility mode, blank pad and null terminate char array */
468+
if (ORACLE_MODE(compat) && (type == ECPGt_char || type == ECPGt_unsigned_char))
469+
{
470+
memset(str, ' ', varcharsize);
471+
memcpy(str, pval, size);
472+
str[varcharsize-1] = '\0';
473+
474+
/* compatiblity mode empty string gets -1 indicator but no warning */
475+
if (size == 0) {
476+
/* truncation */
477+
switch (ind_type)
478+
{
479+
case ECPGt_short:
480+
case ECPGt_unsigned_short:
481+
*((short *) (ind + ind_offset * act_tuple)) = -1;
482+
break;
483+
case ECPGt_int:
484+
case ECPGt_unsigned_int:
485+
*((int *) (ind + ind_offset * act_tuple)) = -1;
486+
break;
487+
case ECPGt_long:
488+
case ECPGt_unsigned_long:
489+
*((long *) (ind + ind_offset * act_tuple)) = -1;
490+
break;
491+
#ifdef HAVE_LONG_LONG_INT
492+
case ECPGt_long_long:
493+
case ECPGt_unsigned_long_long:
494+
*((long long int *) (ind + ind_offset * act_tuple)) = -1;
495+
break;
496+
#endif /* HAVE_LONG_LONG_INT */
497+
default:
498+
break;
499+
}
500+
}
501+
}
502+
else
503+
{
504+
strncpy(str, pval, size + 1);
505+
}
468506
/* do the rtrim() */
469507
if (type == ECPGt_string)
470508
{
@@ -481,7 +519,14 @@ ecpg_get_data(const PGresult *results, int act_tuple, int act_field, int lineno,
481519
{
482520
strncpy(str, pval, varcharsize);
483521

484-
if (varcharsize < size)
522+
/* compatibility mode, null terminate char array */
523+
if (ORACLE_MODE(compat) && (varcharsize - 1) < size)
524+
{
525+
if (type == ECPGt_char || type == ECPGt_unsigned_char)
526+
str[varcharsize-1] = '\0';
527+
}
528+
529+
if (varcharsize < size || (ORACLE_MODE(compat) && (varcharsize - 1) < size))
485530
{
486531
/* truncation */
487532
switch (ind_type)

‎src/interfaces/ecpg/ecpglib/extern.h

Copy file name to clipboardExpand all lines: src/interfaces/ecpg/ecpglib/extern.h
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@
1515

1616
enum COMPAT_MODE
1717
{
18-
ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE
18+
ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE, ECPG_COMPAT_ORACLE
1919
};
2020

2121
extern bool ecpg_internal_regression_mode;
2222

2323
#define INFORMIX_MODE(X) ((X) == ECPG_COMPAT_INFORMIX || (X) == ECPG_COMPAT_INFORMIX_SE)
24+
#define ORACLE_MODE(X) ((X) == ECPG_COMPAT_ORACLE)
2425

2526
enum ARRAY_TYPE
2627
{

‎src/interfaces/ecpg/preproc/ecpg.c

Copy file name to clipboardExpand all lines: src/interfaces/ecpg/preproc/ecpg.c
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ help(const char *progname)
4141
printf(_(" -c automatically generate C code from embedded SQL code;\n"
4242
" this affects EXEC SQL TYPE\n"));
4343
printf(_(" -C MODE set compatibility mode; MODE can be one of\n"
44-
" \"INFORMIX\", \"INFORMIX_SE\"\n"));
44+
" \"INFORMIX\", \"INFORMIX_SE\", \"ORACLE\"\n"));
4545
#ifdef YYDEBUG
4646
printf(_(" -d generate parser debug output\n"));
4747
#endif
@@ -208,6 +208,10 @@ main(int argc, char *const argv[])
208208
snprintf(informix_path, MAXPGPATH, "%s/informix/esql", pkginclude_path);
209209
add_include_path(informix_path);
210210
}
211+
else if (strncmp(optarg, "ORACLE", strlen("ORACLE")) == 0)
212+
{
213+
compat = ECPG_COMPAT_ORACLE;
214+
}
211215
else
212216
{
213217
fprintf(stderr, _("Try \"%s --help\" for more information.\n"), argv[0]);

‎src/interfaces/ecpg/preproc/extern.h

Copy file name to clipboardExpand all lines: src/interfaces/ecpg/preproc/extern.h
+3-1Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,12 @@ extern int filtered_base_yylex(void);
122122

123123
enum COMPAT_MODE
124124
{
125-
ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE
125+
ECPG_COMPAT_PGSQL = 0, ECPG_COMPAT_INFORMIX, ECPG_COMPAT_INFORMIX_SE, ECPG_COMPAT_ORACLE
126126
};
127127
extern enum COMPAT_MODE compat;
128128

129129
#define INFORMIX_MODE (compat == ECPG_COMPAT_INFORMIX || compat == ECPG_COMPAT_INFORMIX_SE)
130+
#define ORACLE_MODE (compat == ECPG_COMPAT_ORACLE)
131+
130132

131133
#endif /* _ECPG_PREPROC_EXTERN_H */

‎src/interfaces/ecpg/test/Makefile

Copy file name to clipboardExpand all lines: src/interfaces/ecpg/test/Makefile
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ all install installdirs uninstall distprep:
3030
$(MAKE) -C pgtypeslib $@
3131
$(MAKE) -C preproc $@
3232
$(MAKE) -C compat_informix $@
33+
$(MAKE) -C compat_oracle $@
3334
$(MAKE) -C thread $@
3435

3536
clean distclean maintainer-clean:
@@ -38,6 +39,7 @@ clean distclean maintainer-clean:
3839
$(MAKE) -C pgtypeslib $@
3940
$(MAKE) -C preproc $@
4041
$(MAKE) -C compat_informix $@
42+
$(MAKE) -C compat_oracle $@
4143
$(MAKE) -C thread $@
4244
rm -rf tmp_check results log
4345
rm -f pg_regress regression.diffs regression.out pg_regress_ecpg.o $(WIN32RES)
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/char_array
2+
/char_array.c
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
subdir = src/interfaces/ecpg/test/compat_oracle
2+
top_builddir = ../../../../..
3+
include $(top_builddir)/src/Makefile.global
4+
include $(top_srcdir)/$(subdir)/../Makefile.regress
5+
6+
# Use special oracle compatibility switch for all tests in this directory
7+
ECPG += -C ORACLE
8+
9+
TESTS = char_array char_array.c
10+
11+
all: $(TESTS)
+66Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
5+
EXEC SQL INCLUDE ../regression;
6+
7+
static void warn();
8+
9+
/* Compatible handling of char array to retrieve varchar field to char array
10+
should be fixed-length, blank-padded, then null-terminated.
11+
Conforms to the ANSI Fixed Character type. */
12+
13+
int main() {
14+
15+
ECPGdebug(1, stderr);
16+
EXEC SQL CONNECT TO REGRESSDB1;
17+
18+
EXEC SQL WHENEVER SQLWARNING do warn();
19+
EXEC SQL WHENEVER SQLERROR SQLPRINT;
20+
21+
const char *ppppp = "XXXXX";
22+
23+
EXEC SQL BEGIN DECLARE SECTION;
24+
char shortstr[5];
25+
char bigstr[11];
26+
short shstr_ind = 0;
27+
short bigstr_ind = 0;
28+
EXEC SQL END DECLARE SECTION;
29+
30+
EXEC SQL CREATE TABLE strdbase (strval varchar(10));
31+
EXEC SQL INSERT INTO strdbase values ('');
32+
EXEC SQL INSERT INTO strdbase values ('AB');
33+
EXEC SQL INSERT INTO strdbase values ('ABCD');
34+
EXEC SQL INSERT INTO strdbase values ('ABCDE');
35+
EXEC SQL INSERT INTO strdbase values ('ABCDEF');
36+
EXEC SQL INSERT INTO strdbase values ('ABCDEFGHIJ');
37+
38+
EXEC SQL declare C cursor for select strval, strval from strdbase;
39+
EXEC SQL OPEN C;
40+
41+
EXEC SQL WHENEVER NOT FOUND DO BREAK;
42+
43+
printf("Full Str. : Short Ind.\n");
44+
while(1) {
45+
strncpy(shortstr, ppppp, sizeof shortstr);
46+
memset(bigstr, 0, sizeof bigstr);
47+
EXEC SQL FETCH C into :bigstr :bigstr_ind, :shortstr :shstr_ind;
48+
printf("\"%s\": \"%s\" %d\n", bigstr, shortstr, shstr_ind);
49+
}
50+
51+
EXEC SQL close cstr;
52+
EXEC SQL DROP TABLE strdbase;
53+
54+
printf("\nGOOD-BYE!!\n\n");
55+
56+
EXEC SQL COMMIT WORK;
57+
58+
EXEC SQL DISCONNECT ALL;
59+
60+
return 0;
61+
}
62+
63+
static void warn(void)
64+
{
65+
fprintf(stderr, "Warning: At least one column was truncated\n");
66+
}

‎src/interfaces/ecpg/test/ecpg_schedule

Copy file name to clipboardExpand all lines: src/interfaces/ecpg/test/ecpg_schedule
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ test: compat_informix/sqlda
77
test: compat_informix/describe
88
test: compat_informix/test_informix
99
test: compat_informix/test_informix2
10+
test: compat_oracle/char_array
1011
test: connect/test2
1112
test: connect/test3
1213
test: connect/test4

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.