if ( schema )
{
- sprintf(query, "SELECT a.attname, a.atttypid, a.attlen FROM "
+ sprintf(query, "SELECT a.attname, a.atttypid, a.attlen, "
+ "a.atttypmod FROM "
"pg_attribute a, pg_class c, pg_namespace n WHERE "
"n.nspname = '%s' AND a.attrelid = c.oid AND "
"n.oid = c.relnamespace AND "
}
else
{
- sprintf(query, "SELECT a.attname, a.atttypid, a.attlen FROM "
+ sprintf(query, "SELECT a.attname, a.atttypid, a.attlen, "
+ "a.atttypmod FROM "
"pg_attribute a, pg_class c WHERE "
"a.attrelid = c.oid and a.attnum > 0 AND "
"a.atttypid != 0 AND "
for (i=0; i<PQntuples(res); i++)
{
int j;
- int type, size;
+ int type, size, mod;
char *fname; // pgsql attribute name
char *ptr;
char field_name[32]; // dbf version of field name
fname = PQgetvalue(res, i, 0);
type = atoi(PQgetvalue(res, i, 1));
size = atoi(PQgetvalue(res, i, 2));
+ mod = atoi(PQgetvalue(res, i, 3));
//printf( "A: %s, T: %d, S: %d\n", fname, type, size);
/*
* Find appropriate type of dbf attributes
*/
- /* integer type */
- if(type == 20 || type == 21 || type == 23)
+ /* int2 type */
+ if ( type == 21 )
{
- if(DBFAddField(dbf, field_name, FTInteger,16,0) == -1)
+ /*
+ * Longest text representation for
+ * an int2 type (16bit) is 6 bytes
+ * (-32768)
+ */
+ if ( DBFAddField(dbf, field_name, FTInteger,
+ 6, 0) == -1 )
+ {
+ printf( "error - Field could not "
+ "be created.\n");
+ return 0;
+ }
+ type_ary[mainscan_nflds]=1;
+ mainscan_flds[mainscan_nflds++] = fname;
+ continue;
+ }
+
+ /* int4 type */
+ if ( type == 23 )
+ {
+ /*
+ * Longest text representation for
+ * an int4 type (32bit) is 11 bytes
+ * (-2147483648)
+ */
+ if ( DBFAddField(dbf, field_name, FTInteger,
+ 11, 0) == -1 )
+ {
+ printf( "error - Field could not "
+ "be created.\n");
+ return 0;
+ }
+ type_ary[mainscan_nflds]=1;
+ mainscan_flds[mainscan_nflds++] = fname;
+ continue;
+ }
+
+ /* int8 type */
+ if ( type == 20 )
+ {
+ /*
+ * Longest text representation for
+ * an int8 type (64bit) is 20 bytes
+ * (-9223372036854775808)
+ */
+ if ( DBFAddField(dbf, field_name, FTInteger,
+ 20, 0) == -1 )
{
printf( "error - Field could not "
"be created.\n");
continue;
}
- /* double type */
+ /*
+ * double or numeric types:
+ * 700: float4
+ * 701: float8
+ * 1700: numeric
+ *
+ *
+ * TODO: stricter handling of sizes
+ */
if(type == 700 || type == 701 || type == 1700 )
{
if(DBFAddField(dbf, field_name,FTDouble,32,10) == -1)
}
/*
- * For variable-sized fields we'll use max size in table
- * as dbf field size
+ * For variable-sized fields we'll use either
+ * maximum allowed size (atttypmod) or max actual
+ * attribute value in table.
*/
else if(size == -1)
{
- size = getMaxFieldSize(conn, schema, table, fname);
- if ( size == -1 ) return 0;
- if ( ! size ) size = 32; // might 0 be a good size ?
+ /*
+ * 1042 is bpchar, 1043 is varchar
+ * mod is maximum allowed size, including
+ * header which contains *real* size.
+ */
+ if ( (type == 1042 || type == 1043) && mod != -1 )
+ {
+ size = mod-4; // 4 is header size
+ }
+ else
+ {
+ size = getMaxFieldSize(conn, schema,
+ table, fname);
+ if ( size == -1 ) return 0;
+ if ( ! size ) size = 32;
+ // might 0 be a good size ?
+ }
}
//printf( "FIELD_NAME: %s, SIZE: %d\n", field_name, size);
/**********************************************************************
* $Log$
+ * Revision 1.74.2.5 2005/10/24 11:31:27 strk
+ * Backported stricter STRING and INTEGER attributes handling.
+ *
+ * Revision 1.79 2005/10/03 18:08:55 strk
+ * Stricter string attributes lenght handling. DBF header will be used
+ * to set varchar maxlenght, (var)char typmod will be used to set DBF header
+ * len.
+ *
* Revision 1.74.2.4 2005/07/22 19:20:49 strk
* Fixed bug in {get,pop}{int,double} for 64bit archs
*
field_width = widths[j];
field_precision = precisions[j];
- printf(", \"%s\" ", field_names[j]);
+ printf(",\n\"%s\" ", field_names[j]);
if(hDBFHandle->pachFieldType[j] == 'D' ) /* Date field */
{
if(type == FTString)
{
- printf ("varchar");
+ // use DBF attribute size as maximum width
+ printf ("varchar(%d)", field_width);
}
else if(type == FTInteger)
{
- if ( forceint4 || field_width <= 9 )
+ if ( forceint4 )
{
printf ("int4");
}
- else if( field_width > 18 )
+ else if ( field_width <= 6 )
{
- printf("numeric(%d,0)",
- field_width);
+ printf ("int2");
}
- else
+ else if ( field_width <= 11 )
+ {
+ printf ("int4");
+ }
+ else if ( field_width <= 20 )
{
printf ("int8");
}
+ else
+ {
+ printf("numeric(%d,0)",
+ field_width);
+ }
}
else if(type == FTDouble)
{
/**********************************************************************
* $Log$
+ * Revision 1.88.2.11 2005/10/24 11:31:27 strk
+ * Backported stricter STRING and INTEGER attributes handling.
+ *
+ * Revision 1.99 2005/10/03 18:08:55 strk
+ * Stricter string attributes lenght handling. DBF header will be used
+ * to set varchar maxlenght, (var)char typmod will be used to set DBF header
+ * len.
+ *
* Revision 1.88.2.10 2005/10/21 11:34:25 strk
* Applied patch by Lars Roessiger handling numerical values with a trailing decima
* l dot