Обсуждение: 32-bit ints on 64-bit linux
Greetings,
I am having a problem in running some code in 64 bit unix. I'm running
unixODBC and psqlodbc-08.00.0005 on SuSE 9.1 x86-64.
If I bind a 32 bit integer using SQL_INTEGER/SQL_C_LONG and pass a value
of -1, the insert fails with an 'integer out of range' error. The
reason this happens is the sprintf near line 2658 of convert.c.
case SQL_C_SLONG:
case SQL_C_LONG:
sprintf(param_string, "%ld",
*((SDWORD *) buffer));
break;
How should this be fixed? Should SQL_C_LONG/SQL_C_SLONG be identified
with the native C long of the compiler? On Linux/GCC long is 64 bits.
On Windows 64, I believe a long will remain 32 bits.
It seems nicer to me to reserve SQL_C_LONG/SLONG for 32 bit ints and use
SQL_C_SBIGINT/SQL_C_UBIGINT for 64 bit ints.
An alternative approach would be to use:
ipdopts->parameters[param_number].column_size
to select an appropriate sprintf.
What do you ODBC experts consider an appropriate approach.
-K
Replying to my own message...
Kelly Burkhart wrote:
> Greetings,
>
> I am having a problem in running some code in 64 bit unix. I'm running
> unixODBC and psqlodbc-08.00.0005 on SuSE 9.1 x86-64.
>
> If I bind a 32 bit integer using SQL_INTEGER/SQL_C_LONG and pass a value
> of -1, the insert fails with an 'integer out of range' error. The
> reason this happens is the sprintf near line 2658 of convert.c.
>
> case SQL_C_SLONG:
> case SQL_C_LONG:
> sprintf(param_string, "%ld",
> *((SDWORD *) buffer));
> break;
It appears that SQL_C_LONG does correspond to a 32-bit integer and not
the native long.
I'm attaching a patch which fixes this, and some other questionable
sprintf format strings in convert.c.
-K
--- psqlodbc-08.00.0005/convert.c 2005-01-17 04:12:52.000000000 -0600
+++ psqlodbc-08.00.0005.patch/convert.c 2005-03-03 08:26:38.443591978 -0600
@@ -180,18 +180,31 @@
#ifdef WIN32
#define ATOI64 _atoi64
#define ATOI64U _atoi64
-#define FORMATI64 "%I64d"
-#define FORMATI64U "%I64u"
#elif defined(HAVE_STRTOLL)
#define ATOI64(val) strtoll(val, NULL, 10)
#define ATOI64U(val) strtoull(val, NULL, 10)
-#define FORMATI64 "%lld"
-#define FORMATI64U "%llu"
#else /* HAVE_STRTOLL */
#endif /* WIN32 */
#endif /* ODBCINT64 */
/*
+ * sprintf formats
+ */
+#define FORMATI8 "%hhd"
+#define FORMATI8U "%hhu"
+#define FORMATI16 "%hd"
+#define FORMATI16U "%hu"
+#define FORMATI32 "%d"
+#define FORMATI32U "%u"
+#ifdef WIN32
+# define FORMATI64 "%I64d"
+# define FORMATI64U "%I64u"
+#else
+# define FORMATI64 "%lld"
+# define FORMATI64U "%llu"
+#endif
+
+/*
* TIMESTAMP <-----> SIMPLE_TIME
* precision support since 7.2.
* time zone support is unavailable(the stuff is unreliable)
@@ -2655,7 +2668,7 @@
case SQL_C_SLONG:
case SQL_C_LONG:
- sprintf(param_string, "%ld",
+ sprintf(param_string, FORMATI32,
*((SDWORD *) buffer));
break;
@@ -2673,28 +2686,28 @@
#endif /* ODBCINT64 */
case SQL_C_SSHORT:
case SQL_C_SHORT:
- sprintf(param_string, "%d",
+ sprintf(param_string, FORMATI16,
*((SWORD *) buffer));
break;
case SQL_C_STINYINT:
case SQL_C_TINYINT:
- sprintf(param_string, "%d",
+ sprintf(param_string, FORMATI8,
*((SCHAR *) buffer));
break;
case SQL_C_ULONG:
- sprintf(param_string, "%lu",
+ sprintf(param_string, FORMATI32U,
*((UDWORD *) buffer));
break;
case SQL_C_USHORT:
- sprintf(param_string, "%u",
+ sprintf(param_string, FORMATI16U,
*((UWORD *) buffer));
break;
case SQL_C_UTINYINT:
- sprintf(param_string, "%u",
+ sprintf(param_string, FORMATI8U,
*((UCHAR *) buffer));
break;
Kelly Burkhart <kelly@kkcsm.net> writes: > Replying to my own message... > > Kelly Burkhart wrote: > > Greetings, > > I am having a problem in running some code in 64 bit unix. I'm > > running unixODBC and psqlodbc-08.00.0005 on SuSE 9.1 x86-64. > > If I bind a 32 bit integer using SQL_INTEGER/SQL_C_LONG and pass a > > value of -1, the insert fails with an 'integer out of range' error. > > The reason this happens is the sprintf near line 2658 of convert.c. > > case SQL_C_SLONG: > > case SQL_C_LONG: > > sprintf(param_string, "%ld", > > *((SDWORD *) buffer)); > > break; > > It appears that SQL_C_LONG does correspond to a 32-bit integer and not > the native long. > > I'm attaching a patch which fixes this, and some other questionable > sprintf format strings in convert.c. Just a note on this. There are already standardized format string defines (when including inttypes.h) for different sizes: PRId8, PRId16, PRId32, PRId64, PRIu8, PRIu16, PRIu32, PRIu64, ... It may be better to use those. However, I don't know if they are available in Windows. Greetings, Tomas
Am Donnerstag, 3. März 2005 16:05 schrieb Kelly Burkhart: > I'm attaching a patch which fixes this, and some other questionable > sprintf format strings in convert.c. Do we have any evidence that the other ones are broken? -- Peter Eisentraut http://developer.postgresql.org/~petere/
On Fri, 2005-03-18 at 09:25, Peter Eisentraut wrote:
> Am Donnerstag, 3. März 2005 16:05 schrieb Kelly Burkhart:
> > I'm attaching a patch which fixes this, and some other questionable
> > sprintf format strings in convert.c.
>
> Do we have any evidence that the other ones are broken?
No, I do not.
I suggested that the other format strings were questionable based on a
reading of the glibc printf man page. Aside from the 32-bit integer
problem the other formats work fine in the unmodified form on the three
platforms I use.
Can anyone with a better understanding of the libc standard comment on
the "correctness" of the following lines?
int8_t i1;
int16_t i2;
printf("%d", i1);
printf("%d", i2);
vs:
printf("%hhd", i1);
printf("%hd", i2);
-K
Kelly Burkhart <kelly@tradebotsystems.com> writes:
> Can anyone with a better understanding of the libc standard comment on
> the "correctness" of the following lines?
> int8_t i1;
> int16_t i2;
> printf("%d", i1);
> printf("%d", i2);
That's perfectly correct, unless int is narrower than 16 bits on your
platform ;-). Anything narrower than int is implicitly coerced to int
when it's passed to printf. The existence of the h modifier in the
printf format syntax is for scanf, not printf; scanf does have to
know the difference between int and narrower-than-int variables.
regards, tom lane
Kelly Burkhart wrote: > I suggested that the other format strings were questionable based on > a reading of the glibc printf man page. Aside from the 32-bit > integer problem the other formats work fine in the unmodified form on > the three platforms I use. Given the information provided by Tom Lane, would you submit an updated patch? Thanks. -- Peter Eisentraut http://developer.postgresql.org/~petere/
On Wed, 2005-03-30 at 12:02, Peter Eisentraut wrote: > Kelly Burkhart wrote: > > I suggested that the other format strings were questionable based on > > a reading of the glibc printf man page. Aside from the 32-bit > > integer problem the other formats work fine in the unmodified form on > > the three platforms I use. > > Given the information provided by Tom Lane, would you submit an updated > patch? Thanks. Certainly. Here it is. -K