package org.postgresql.jdbc;
import org.postgresql.core.BaseConnection;
import org.postgresql.core.BaseStatement;
import org.postgresql.core.Oid;
import org.postgresql.core.QueryExecutor;
import org.postgresql.core.ServerVersion;
import org.postgresql.core.TypeInfo;
import org.postgresql.util.GT;
import org.postgresql.util.PGobject;
import org.postgresql.util.PSQLException;
import org.postgresql.util.PSQLState;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class TypeInfoCache implements TypeInfo {
private Map<String, Integer> pgNameToSQLType;
private Map<String, String> pgNameToJavaClass;
private Map<Integer, String> oidToPgName;
private Map<String, Integer> pgNameToOid;
private Map<String, Class<? extends PGobject>> pgNameToPgObject;
private Map<Integer, Integer> pgArrayToPgType;
private Map<Integer, Character> arrayOidToDelimiter;
private BaseConnection conn;
private final int unknownLength;
private PreparedStatement getOidStatementSimple;
private PreparedStatement getOidStatementComplexNonArray;
private PreparedStatement getOidStatementComplexArray;
private PreparedStatement getNameStatement;
private PreparedStatement getArrayElementOidStatement;
private PreparedStatement getArrayDelimiterStatement;
private PreparedStatement getTypeInfoStatement;
private static final Object[][] types = {
{"int2", Oid.INT2, Types.SMALLINT, "java.lang.Integer", Oid.INT2_ARRAY},
{"int4", Oid.INT4, Types.INTEGER, "java.lang.Integer", Oid.INT4_ARRAY},
{"oid", Oid.OID, Types.BIGINT, "java.lang.Long", Oid.OID_ARRAY},
{"int8", Oid.INT8, Types.BIGINT, "java.lang.Long", Oid.INT8_ARRAY},
{"money", Oid.MONEY, Types.DOUBLE, "java.lang.Double", Oid.MONEY_ARRAY},
{"numeric", Oid.NUMERIC, Types.NUMERIC, "java.math.BigDecimal", Oid.NUMERIC_ARRAY},
{"float4", Oid.FLOAT4, Types.REAL, "java.lang.Float", Oid.FLOAT4_ARRAY},
{"float8", Oid.FLOAT8, Types.DOUBLE, "java.lang.Double", Oid.FLOAT8_ARRAY},
{"char", Oid.CHAR, Types.CHAR, "java.lang.String", Oid.CHAR_ARRAY},
{"bpchar", Oid.BPCHAR, Types.CHAR, "java.lang.String", Oid.BPCHAR_ARRAY},
{"varchar", Oid.VARCHAR, Types.VARCHAR, "java.lang.String", Oid.VARCHAR_ARRAY},
{"text", Oid.TEXT, Types.VARCHAR, "java.lang.String", Oid.TEXT_ARRAY},
{"name", Oid.NAME, Types.VARCHAR, "java.lang.String", Oid.NAME_ARRAY},
{"bytea", Oid.BYTEA, Types.BINARY, "[B", Oid.BYTEA_ARRAY},
{"bool", Oid.BOOL, Types.BIT, "java.lang.Boolean", Oid.BOOL_ARRAY},
{"bit", Oid.BIT, Types.BIT, "java.lang.Boolean", Oid.BIT_ARRAY},
{"date", Oid.DATE, Types.DATE, "java.sql.Date", Oid.DATE_ARRAY},
{"time", Oid.TIME, Types.TIME, "java.sql.Time", Oid.TIME_ARRAY},
{"timetz", Oid.TIMETZ, Types.TIME, "java.sql.Time", Oid.TIMETZ_ARRAY},
{"timestamp", Oid.TIMESTAMP, Types.TIMESTAMP, "java.sql.Timestamp", Oid.TIMESTAMP_ARRAY},
{"timestamptz", Oid.TIMESTAMPTZ, Types.TIMESTAMP, "java.sql.Timestamp",
Oid.TIMESTAMPTZ_ARRAY},
{"refcursor", Oid.REF_CURSOR, Types.REF_CURSOR, "java.sql.ResultSet", Oid.REF_CURSOR_ARRAY},
{"json", Oid.JSON, Types.OTHER, "org.postgresql.util.PGobject", Oid.JSON_ARRAY},
{"point", Oid.POINT, Types.OTHER, "org.postgresql.geometric.PGpoint", Oid.POINT_ARRAY}
};
private static final HashMap<String, String> typeAliases;
static {
typeAliases = new HashMap<String, String>();
typeAliases.put("smallint", "int2");
typeAliases.put("integer", "int4");
typeAliases.put("int", "int4");
typeAliases.put("bigint", "int8");
typeAliases.put("float", "float8");
typeAliases.put("boolean", "bool");
typeAliases.put("decimal", "numeric");
}
public TypeInfoCache(BaseConnection conn, int unknownLength) {
this.conn = conn;
this.unknownLength = unknownLength;
oidToPgName = new HashMap<Integer, String>((int) Math.round(types.length * 1.5));
pgNameToOid = new HashMap<String, Integer>((int) Math.round(types.length * 1.5));
pgNameToJavaClass = new HashMap<String, String>((int) Math.round(types.length * 1.5));
pgNameToPgObject = new HashMap<String, Class<? extends PGobject>>((int) Math.round(types.length * 1.5));
pgArrayToPgType = new HashMap<Integer, Integer>((int) Math.round(types.length * 1.5));
arrayOidToDelimiter = new HashMap<Integer, Character>((int) Math.round(types.length * 2.5));
pgNameToSQLType = Collections.synchronizedMap(new HashMap<String, Integer>((int) Math.round(types.length * 1.5)));
for (Object[] type : types) {
String pgTypeName = (String) type[0];
Integer oid = (Integer) type[1];
Integer sqlType = (Integer) type[2];
String javaClass = (String) type[3];
Integer arrayOid = (Integer) type[4];
addCoreType(pgTypeName, oid, sqlType, javaClass, arrayOid);
}
pgNameToJavaClass.put("hstore", Map.class.getName());
}
public synchronized void addCoreType(String pgTypeName, Integer oid, Integer sqlType,
String javaClass, Integer arrayOid) {
pgNameToJavaClass.put(pgTypeName, javaClass);
pgNameToOid.put(pgTypeName, oid);
oidToPgName.put(oid, pgTypeName);
pgArrayToPgType.put(arrayOid, oid);
pgNameToSQLType.put(pgTypeName, sqlType);
Character delim = ',';
arrayOidToDelimiter.put(oid, delim);
arrayOidToDelimiter.put(arrayOid, delim);
String pgArrayTypeName = pgTypeName + "[]";
pgNameToJavaClass.put(pgArrayTypeName, "java.sql.Array");
pgNameToSQLType.put(pgArrayTypeName, Types.ARRAY);
pgNameToOid.put(pgArrayTypeName, arrayOid);
pgArrayTypeName = "_" + pgTypeName;
if (!pgNameToJavaClass.containsKey(pgArrayTypeName)) {
pgNameToJavaClass.put(pgArrayTypeName, "java.sql.Array");
pgNameToSQLType.put(pgArrayTypeName, Types.ARRAY);
pgNameToOid.put(pgArrayTypeName, arrayOid);
oidToPgName.put(arrayOid, pgArrayTypeName);
}
}
public synchronized void addDataType(String type, Class<? extends PGobject> klass)
throws SQLException {
pgNameToPgObject.put(type, klass);
pgNameToJavaClass.put(type, klass.getName());
}
public Iterator<String> getPGTypeNamesWithSQLTypes() {
return pgNameToSQLType.keySet().iterator();
}
public int getSQLType(int oid) throws SQLException {
return getSQLType(getPGType(oid));
}
public synchronized int getSQLType(String pgTypeName) throws SQLException {
if (pgTypeName.endsWith("[]")) {
return Types.ARRAY;
}
Integer i = pgNameToSQLType.get(pgTypeName);
if (i != null) {
return i;
}
if (getTypeInfoStatement == null) {
String sql;
sql = "SELECT typinput='array_in'::regproc, typtype "
+ " FROM pg_catalog.pg_type "
+ " LEFT "
+ " JOIN (select ns.oid as nspoid, ns.nspname, r.r "
+ " from pg_namespace as ns "
+ " join ( select s.r, (current_schemas(false))[s.r] as nspname "
+ " from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r "
+ " using ( nspname ) "
+ " ) as sp "
+ " ON sp.nspoid = typnamespace "
+ " WHERE typname = ? "
+ " ORDER BY sp.r, pg_type.oid DESC LIMIT 1;";
getTypeInfoStatement = conn.prepareStatement(sql);
}
getTypeInfoStatement.setString(1, pgTypeName);
if (!((BaseStatement) getTypeInfoStatement)
.executeWithFlags(QueryExecutor.QUERY_SUPPRESS_BEGIN)) {
throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA);
}
ResultSet rs = getTypeInfoStatement.getResultSet();
Integer type = null;
if (rs.next()) {
boolean isArray = rs.getBoolean(1);
String typtype = rs.getString(2);
if (isArray) {
type = Types.ARRAY;
} else if ("c".equals(typtype)) {
type = Types.STRUCT;
} else if ("d".equals(typtype)) {
type = Types.DISTINCT;
} else if ("e".equals(typtype)) {
type = Types.VARCHAR;
}
}
if (type == null) {
type = Types.OTHER;
}
rs.close();
pgNameToSQLType.put(pgTypeName, type);
return type;
}
private PreparedStatement getOidStatement(String pgTypeName) throws SQLException {
boolean isArray = pgTypeName.endsWith("[]");
boolean hasQuote = pgTypeName.contains("\"");
int dotIndex = pgTypeName.indexOf('.');
if (dotIndex == -1 && !hasQuote && !isArray) {
if (getOidStatementSimple == null) {
String sql;
sql = "SELECT pg_type.oid, typname "
+ " FROM pg_catalog.pg_type "
+ " LEFT "
+ " JOIN (select ns.oid as nspoid, ns.nspname, r.r "
+ " from pg_namespace as ns "
+ " join ( select s.r, (current_schemas(false))[s.r] as nspname "
+ " from generate_series(1, array_upper(current_schemas(false), 1)) as s(r) ) as r "
+ " using ( nspname ) "
+ " ) as sp "
+ " ON sp.nspoid = typnamespace "
+ " WHERE typname = ? "
+ " ORDER BY sp.r, pg_type.oid DESC LIMIT 1;";
getOidStatementSimple = conn.prepareStatement(sql);
}
String lcName = pgTypeName.toLowerCase();
getOidStatementSimple.setString(1, lcName);
return getOidStatementSimple;
}
PreparedStatement oidStatementComplex;
if (isArray) {
if (getOidStatementComplexArray == null) {
String sql;
if (conn.haveMinimumServerVersion(ServerVersion.v8_3)) {
sql = "SELECT t.typarray, arr.typname "
+ " FROM pg_catalog.pg_type t"
+ " JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid"
+ " JOIN pg_catalog.pg_type arr ON arr.oid = t.typarray"
+ " WHERE t.typname = ? AND (n.nspname = ? OR ? AND n.nspname = ANY (current_schemas(true)))"
+ " ORDER BY t.oid DESC LIMIT 1";
} else {
sql = "SELECT t.oid, t.typname "
+ " FROM pg_catalog.pg_type t"
+ " JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid"
+ " WHERE t.typelem = (SELECT oid FROM pg_catalog.pg_type WHERE typname = ?)"
+ " AND substring(t.typname, 1, 1) = '_' AND t.typlen = -1"
+ " AND (n.nspname = ? OR ? AND n.nspname = ANY (current_schemas(true)))"
+ " ORDER BY t.typelem DESC LIMIT 1";
}
getOidStatementComplexArray = conn.prepareStatement(sql);
}
oidStatementComplex = getOidStatementComplexArray;
} else {
if (getOidStatementComplexNonArray == null) {
String sql = "SELECT t.oid, t.typname "
+ " FROM pg_catalog.pg_type t"
+ " JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid"
+ " WHERE t.typname = ? AND (n.nspname = ? OR ? AND n.nspname = ANY (current_schemas(true)))"
+ " ORDER BY t.oid DESC LIMIT 1";
getOidStatementComplexNonArray = conn.prepareStatement(sql);
}
oidStatementComplex = getOidStatementComplexNonArray;
}
String fullName = isArray ? pgTypeName.substring(0, pgTypeName.length() - 2) : pgTypeName;
String schema;
String name;
if (dotIndex == -1) {
schema = null;
name = fullName;
} else {
if (fullName.startsWith("\"")) {
if (fullName.endsWith("\"")) {
String[] parts = fullName.split("\"\\.\"");
schema = parts.length == 2 ? parts[0] + "\"" : null;
name = parts.length == 2 ? "\"" + parts[1] : parts[0];
} else {
int lastDotIndex = fullName.lastIndexOf('.');
name = fullName.substring(lastDotIndex + 1);
schema = fullName.substring(0, lastDotIndex);
}
} else {
schema = fullName.substring(0, dotIndex);
name = fullName.substring(dotIndex + 1);
}
}
if (schema != null && schema.startsWith("\"") && schema.endsWith("\"")) {
schema = schema.substring(1, schema.length() - 1);
} else if (schema != null) {
schema = schema.toLowerCase();
}
if (name.startsWith("\"") && name.endsWith("\"")) {
name = name.substring(1, name.length() - 1);
} else {
name = name.toLowerCase();
}
oidStatementComplex.setString(1, name);
oidStatementComplex.setString(2, schema);
oidStatementComplex.setBoolean(3, schema == null);
return oidStatementComplex;
}
public synchronized int getPGType(String pgTypeName) throws SQLException {
Integer oid = pgNameToOid.get(pgTypeName);
if (oid != null) {
return oid;
}
PreparedStatement oidStatement = getOidStatement(pgTypeName);
if (!((BaseStatement) oidStatement).executeWithFlags(QueryExecutor.QUERY_SUPPRESS_BEGIN)) {
throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA);
}
oid = Oid.UNSPECIFIED;
ResultSet rs = oidStatement.getResultSet();
if (rs.next()) {
oid = (int) rs.getLong(1);
String internalName = rs.getString(2);
oidToPgName.put(oid, internalName);
pgNameToOid.put(internalName, oid);
}
pgNameToOid.put(pgTypeName, oid);
rs.close();
return oid;
}
public synchronized String getPGType(int oid) throws SQLException {
if (oid == Oid.UNSPECIFIED) {
return null;
}
String pgTypeName = oidToPgName.get(oid);
if (pgTypeName != null) {
return pgTypeName;
}
if (getNameStatement == null) {
String sql;
sql = "SELECT n.nspname = ANY(current_schemas(true)), n.nspname, t.typname "
+ "FROM pg_catalog.pg_type t "
+ "JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.oid = ?";
getNameStatement = conn.prepareStatement(sql);
}
getNameStatement.setInt(1, oid);
if (!((BaseStatement) getNameStatement).executeWithFlags(QueryExecutor.QUERY_SUPPRESS_BEGIN)) {
throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA);
}
ResultSet rs = getNameStatement.getResultSet();
if (rs.next()) {
boolean onPath = rs.getBoolean(1);
String schema = rs.getString(2);
String name = rs.getString(3);
if (onPath) {
pgTypeName = name;
pgNameToOid.put(schema + "." + name, oid);
} else {
pgTypeName = "\"" + schema + "\".\"" + name + "\"";
if (schema.equals(schema.toLowerCase()) && schema.indexOf('.') == -1
&& name.equals(name.toLowerCase()) && name.indexOf('.') == -1) {
pgNameToOid.put(schema + "." + name, oid);
}
}
pgNameToOid.put(pgTypeName, oid);
oidToPgName.put(oid, pgTypeName);
}
rs.close();
return pgTypeName;
}
public int getPGArrayType(String elementTypeName) throws SQLException {
elementTypeName = getTypeForAlias(elementTypeName);
return getPGType(elementTypeName + "[]");
}
protected synchronized int convertArrayToBaseOid(int oid) {
Integer i = pgArrayToPgType.get(oid);
if (i == null) {
return oid;
}
return i;
}
public synchronized char getArrayDelimiter(int oid) throws SQLException {
if (oid == Oid.UNSPECIFIED) {
return ',';
}
Character delim = arrayOidToDelimiter.get(oid);
if (delim != null) {
return delim;
}
if (getArrayDelimiterStatement == null) {
String sql;
sql = "SELECT e.typdelim FROM pg_catalog.pg_type t, pg_catalog.pg_type e "
+ "WHERE t.oid = ? and t.typelem = e.oid";
getArrayDelimiterStatement = conn.prepareStatement(sql);
}
getArrayDelimiterStatement.setInt(1, oid);
if (!((BaseStatement) getArrayDelimiterStatement)
.executeWithFlags(QueryExecutor.QUERY_SUPPRESS_BEGIN)) {
throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA);
}
ResultSet rs = getArrayDelimiterStatement.getResultSet();
if (!rs.next()) {
throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA);
}
String s = rs.getString(1);
delim = s.charAt(0);
arrayOidToDelimiter.put(oid, delim);
rs.close();
return delim;
}
public synchronized int getPGArrayElement(int oid) throws SQLException {
if (oid == Oid.UNSPECIFIED) {
return Oid.UNSPECIFIED;
}
Integer pgType = pgArrayToPgType.get(oid);
if (pgType != null) {
return pgType;
}
if (getArrayElementOidStatement == null) {
String sql;
sql = "SELECT e.oid, n.nspname = ANY(current_schemas(true)), n.nspname, e.typname "
+ "FROM pg_catalog.pg_type t JOIN pg_catalog.pg_type e ON t.typelem = e.oid "
+ "JOIN pg_catalog.pg_namespace n ON t.typnamespace = n.oid WHERE t.oid = ?";
getArrayElementOidStatement = conn.prepareStatement(sql);
}
getArrayElementOidStatement.setInt(1, oid);
if (!((BaseStatement) getArrayElementOidStatement)
.executeWithFlags(QueryExecutor.QUERY_SUPPRESS_BEGIN)) {
throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA);
}
ResultSet rs = getArrayElementOidStatement.getResultSet();
if (!rs.next()) {
throw new PSQLException(GT.tr("No results were returned by the query."), PSQLState.NO_DATA);
}
pgType = (int) rs.getLong(1);
boolean onPath = rs.getBoolean(2);
String schema = rs.getString(3);
String name = rs.getString(4);
pgArrayToPgType.put(oid, pgType);
pgNameToOid.put(schema + "." + name, pgType);
String fullName = "\"" + schema + "\".\"" + name + "\"";
pgNameToOid.put(fullName, pgType);
if (onPath && name.equals(name.toLowerCase())) {
oidToPgName.put(pgType, name);
pgNameToOid.put(name, pgType);
} else {
oidToPgName.put(pgType, fullName);
}
rs.close();
return pgType;
}
public synchronized Class<? extends PGobject> getPGobject(String type) {
return pgNameToPgObject.get(type);
}
public synchronized String getJavaClass(int oid) throws SQLException {
String pgTypeName = getPGType(oid);
String result = pgNameToJavaClass.get(pgTypeName);
if (result != null) {
return result;
}
if (getSQLType(pgTypeName) == Types.ARRAY) {
result = "java.sql.Array";
pgNameToJavaClass.put(pgTypeName, result);
}
return result;
}
public String getTypeForAlias(String alias) {
String type = typeAliases.get(alias);
if (type != null) {
return type;
}
if (alias.indexOf('"') == -1) {
type = typeAliases.get(alias.toLowerCase());
if (type != null) {
return type;
}
}
return alias;
}
public int getPrecision(int oid, int typmod) {
oid = convertArrayToBaseOid(oid);
switch (oid) {
case Oid.INT2:
return 5;
case Oid.OID:
case Oid.INT4:
return 10;
case Oid.INT8:
return 19;
case Oid.FLOAT4:
return 8;
case Oid.FLOAT8:
return 17;
case Oid.NUMERIC:
if (typmod == -1) {
return 0;
}
return ((typmod - 4) & 0xFFFF0000) >> 16;
case Oid.CHAR:
case Oid.BOOL:
return 1;
case Oid.BPCHAR:
case Oid.VARCHAR:
if (typmod == -1) {
return unknownLength;
}
return typmod - 4;
case Oid.DATE:
case Oid.TIME:
case Oid.TIMETZ:
case Oid.INTERVAL:
case Oid.TIMESTAMP:
case Oid.TIMESTAMPTZ:
return getDisplaySize(oid, typmod);
case Oid.BIT:
return typmod;
case Oid.VARBIT:
if (typmod == -1) {
return unknownLength;
}
return typmod;
case Oid.TEXT:
case Oid.BYTEA:
default:
return unknownLength;
}
}
public int getScale(int oid, int typmod) {
oid = convertArrayToBaseOid(oid);
switch (oid) {
case Oid.FLOAT4:
return 8;
case Oid.FLOAT8:
return 17;
case Oid.NUMERIC:
if (typmod == -1) {
return 0;
}
return (typmod - 4) & 0xFFFF;
case Oid.TIME:
case Oid.TIMETZ:
case Oid.TIMESTAMP:
case Oid.TIMESTAMPTZ:
if (typmod == -1) {
return 6;
}
return typmod;
case Oid.INTERVAL:
if (typmod == -1) {
return 6;
}
return typmod & 0xFFFF;
default:
return 0;
}
}
public boolean isCaseSensitive(int oid) {
oid = convertArrayToBaseOid(oid);
switch (oid) {
case Oid.OID:
case Oid.INT2:
case Oid.INT4:
case Oid.INT8:
case Oid.FLOAT4:
case Oid.FLOAT8:
case Oid.NUMERIC:
case Oid.BOOL:
case Oid.BIT:
case Oid.VARBIT:
case Oid.DATE:
case Oid.TIME:
case Oid.TIMETZ:
case Oid.TIMESTAMP:
case Oid.TIMESTAMPTZ:
case Oid.INTERVAL:
return false;
default:
return true;
}
}
public boolean isSigned(int oid) {
oid = convertArrayToBaseOid(oid);
switch (oid) {
case Oid.INT2:
case Oid.INT4:
case Oid.INT8:
case Oid.FLOAT4:
case Oid.FLOAT8:
case Oid.NUMERIC:
return true;
default:
return false;
}
}
public int getDisplaySize(int oid, int typmod) {
oid = convertArrayToBaseOid(oid);
switch (oid) {
case Oid.INT2:
return 6;
case Oid.INT4:
return 11;
case Oid.OID:
return 10;
case Oid.INT8:
return 20;
case Oid.FLOAT4:
return 15;
case Oid.FLOAT8:
return 25;
case Oid.CHAR:
return 1;
case Oid.BOOL:
return 1;
case Oid.DATE:
return 13;
case Oid.TIME:
case Oid.TIMETZ:
case Oid.TIMESTAMP:
case Oid.TIMESTAMPTZ:
int secondSize;
switch (typmod) {
case -1:
secondSize = 6 + 1;
break;
case 0:
secondSize = 0;
break;
case 1:
secondSize = 2 + 1;
break;
default:
secondSize = typmod + 1;
break;
}
switch (oid) {
case Oid.TIME:
return 8 + secondSize;
case Oid.TIMETZ:
return 8 + secondSize + 6;
case Oid.TIMESTAMP:
return 13 + 1 + 8 + secondSize;
case Oid.TIMESTAMPTZ:
return 13 + 1 + 8 + secondSize + 6;
}
case Oid.INTERVAL:
return 49;
case Oid.VARCHAR:
case Oid.BPCHAR:
if (typmod == -1) {
return unknownLength;
}
return typmod - 4;
case Oid.NUMERIC:
if (typmod == -1) {
return 131089;
}
int precision = (typmod - 4 >> 16) & 0xffff;
int scale = (typmod - 4) & 0xffff;
return 1 + precision + (scale != 0 ? 1 : 0);
case Oid.BIT:
return typmod;
case Oid.VARBIT:
if (typmod == -1) {
return unknownLength;
}
return typmod;
case Oid.TEXT:
case Oid.BYTEA:
return unknownLength;
default:
return unknownLength;
}
}
public int getMaximumPrecision(int oid) {
oid = convertArrayToBaseOid(oid);
switch (oid) {
case Oid.NUMERIC:
return 1000;
case Oid.TIME:
case Oid.TIMETZ:
return 6;
case Oid.TIMESTAMP:
case Oid.TIMESTAMPTZ:
case Oid.INTERVAL:
return 6;
case Oid.BPCHAR:
case Oid.VARCHAR:
return 10485760;
case Oid.BIT:
case Oid.VARBIT:
return 83886080;
default:
return 0;
}
}
public boolean requiresQuoting(int oid) throws SQLException {
int sqlType = getSQLType(oid);
return requiresQuotingSqlType(sqlType);
}
public boolean requiresQuotingSqlType(int sqlType) throws SQLException {
switch (sqlType) {
case Types.BIGINT:
case Types.DOUBLE:
case Types.FLOAT:
case Types.INTEGER:
case Types.REAL:
case Types.SMALLINT:
case Types.TINYINT:
case Types.NUMERIC:
case Types.DECIMAL:
return false;
}
return true;
}
}