OmniSciDB  dfae7c3b14
Db_vendor_types.java
Go to the documentation of this file.
1 package com.mapd.utility.db_vendors;
2 
3 import com.omnisci.thrift.server.TDatumType;
4 
5 import org.postgis.PGgeometry;
6 import org.postgresql.geometric.PGlseg;
7 import org.postgresql.geometric.PGpoint;
8 import org.postgresql.geometric.PGpolygon;
9 
10 import java.sql.*;
11 import java.util.Arrays;
12 import java.util.HashSet;
13 import java.util.Hashtable;
14 
15 abstract public class Db_vendor_types {
16  protected Db_vendor_types() {}
17  static protected HashSet<Integer> valid_srid =
18  new HashSet<>(Arrays.asList(4326, 900913));
19 
20  public static class GisType {
21  public String subtype;
22  public String type;
23  public int srid;
24  };
25 
26  public abstract boolean isAutoCommitDisabledRequired();
27  public abstract GisType find_gis_type(
28  Connection conn, ResultSetMetaData metadata, int column_number)
29  throws SQLException;
30  public abstract String get_wkt(ResultSet rs, int column_number, String gis_type_name)
31  throws SQLException;
33  String connection_str) {
34  if (connection_str.toLowerCase().contains("postgres"))
36  else if (connection_str.toLowerCase().contains("omnisci"))
38  return new com.mapd.utility.db_vendors.Other_types();
39  }
40  public static String gis_type_to_str(GisType type) {
41  StringBuffer column_sql_definition = new StringBuffer();
42  if (!type.subtype.isEmpty()) {
43  column_sql_definition.append(type.subtype + "(");
44  }
45  column_sql_definition.append(type.type);
46  if (type.srid != 0) {
47  column_sql_definition.append("," + type.srid);
48  }
49  if (!type.subtype.isEmpty()) {
50  column_sql_definition.append(")");
51  }
52  return column_sql_definition.toString();
53  }
54 }
55 
56 class Other_types extends com.mapd.utility.db_vendors.Db_vendor_types {
57  protected Other_types() {}
58  public boolean isAutoCommitDisabledRequired() {
59  return false;
60  }
62  Connection conn, ResultSetMetaData metadata, int column_number)
63  throws SQLException {
64  throw new SQLException("GEO types not supported");
65  }
66  public String get_wkt(ResultSet rs, int column_number, String gis_type_name)
67  throws SQLException {
68  throw new SQLException("GEO types not supported");
69  }
70 }
71 
72 class OmniSciGeo_types extends com.mapd.utility.db_vendors.Db_vendor_types {
73  protected OmniSciGeo_types() {}
74 
75  public boolean isAutoCommitDisabledRequired() {
76  return false;
77  }
78  private static final HashSet<String> geo_types =
79  new HashSet<>(Arrays.asList("point", "linestring", "polygon", "multipolygon"));
80 
81  // values from SqlTypes.h
82  // there seems to be no other way to access those, but IDs are expected NOT to change
83  static private Hashtable<Integer, String> subtypes = new Hashtable() {
84  {
85  put(23, "GEOMETRY");
86  put(24, "GEOGRAPHY");
87  }
88  };
89 
90  public String get_wkt(ResultSet rs, int column_number, String gis_type_name)
91  throws SQLException {
92  return rs.getString(column_number);
93  }
94 
96  Connection conn, ResultSetMetaData metadata, int column_number)
97  throws SQLException {
98  String column_name = metadata.getColumnName(column_number);
99  String column_type_name = metadata.getColumnTypeName(column_number);
100  if (!geo_types.contains(column_type_name.toLowerCase()))
101  throw new SQLException(
102  "type not supported: " + column_type_name + " for column " + column_name);
103  int srid = metadata.getScale(column_number);
104  if (!valid_srid.contains(srid) && srid != 0)
105  throw new SQLException(
106  "srid is not supported: " + srid + " for column " + column_name);
107  int subtype = metadata.getPrecision(column_number);
108  if (!subtypes.containsKey(subtype))
109  throw new SQLException(
110  "Subtype is not supported: " + subtype + " for column " + column_name);
111  GisType result = new GisType();
112  result.srid = srid;
113  result.subtype = subtypes.get(subtype);
114  result.type = column_type_name.toUpperCase();
115  return result;
116  }
117 }
118 
119 class PostGis_types extends com.mapd.utility.db_vendors.Db_vendor_types {
120  protected PostGis_types() {}
121  public boolean isAutoCommitDisabledRequired() {
122  return true;
123  }
124 
125  // Map postgis geom types to OmniSci geom types
126  static private Hashtable<String, String> extra_types = new Hashtable() {
127  {
128  put("point", "POINT");
129  put("lseg", "linestring");
130  put("linestring", "linestring");
131  put("polygon", "polygon");
132  put("multipolygon", "multipolygon");
133  }
134  };
135  private String wkt_point(PGpoint point) {
136  return new String("" + point.x + " " + point.y);
137  }
138 
139  public String get_wkt(ResultSet rs, int column_number, String gis_type_name)
140  throws SQLException {
141  if (gis_type_name.equalsIgnoreCase("geometry")
142  || gis_type_name.equalsIgnoreCase("geography")) {
143  Object gis_object = rs.getObject(column_number);
144  PGgeometry pGeometry = (PGgeometry) gis_object;
145  if (pGeometry == null) throw new SQLException("unknown type");
146  // Try and trim the front SRID=nnnn; value from the string returned from the db.
147  // If there isn't a SRID=nnnn; string (marked by the ';') then simply
148  // return the whole string
149  int semi_colon_indx = pGeometry.getValue().indexOf(';');
150  if (-1 != semi_colon_indx && semi_colon_indx < pGeometry.getValue().length()) {
151  return pGeometry.getValue().substring(semi_colon_indx + 1);
152  }
153  return pGeometry.getValue();
154  }
155  StringBuffer WKT_string = new StringBuffer();
156  if (gis_type_name.equalsIgnoreCase("point")) {
157  PGpoint point = (PGpoint) rs.getObject(column_number);
158  WKT_string.append(extra_types.get(gis_type_name) + "(" + wkt_point(point) + ")");
159 
160  } else if (gis_type_name.equalsIgnoreCase("polygon")) {
161  PGpolygon polygon = (PGpolygon) rs.getObject(column_number);
162  WKT_string.append(extra_types.get(gis_type_name) + "((");
163  for (PGpoint p : polygon.points) {
164  WKT_string.append(wkt_point(p) + ",");
165  }
166  WKT_string.replace(WKT_string.length() - 1, WKT_string.length(), "))");
167  } else if (gis_type_name.equalsIgnoreCase("lseg")) {
168  PGlseg lseg = (PGlseg) rs.getObject(column_number);
169  WKT_string.append(extra_types.get(gis_type_name) + "(");
170  for (PGpoint p : lseg.point) {
171  WKT_string.append(wkt_point(p) + ",");
172  }
173  WKT_string.replace(WKT_string.length() - 1, WKT_string.length(), ")");
174  }
175  return WKT_string.toString();
176  }
177 
179  Connection conn, ResultSetMetaData metadata, int column_number)
180  throws SQLException {
181  String column_name = metadata.getColumnName(column_number);
182  String column_type_name = metadata.getColumnTypeName(column_number);
183  if (column_type_name.equalsIgnoreCase("geography"))
184  return find_type_detail(
185  conn, "geography_columns", "f_geography_column", column_name);
186  else if (column_type_name.equalsIgnoreCase("geometry"))
187  return find_type_detail(conn, "geometry_columns", "f_geometry_column", column_name);
188  if (!extra_types.containsKey(column_type_name))
189  throw new SQLException(
190  "type not supported: " + column_type_name + " for column " + column_name);
191  GisType result = new GisType();
192  result.type = extra_types.get(column_type_name);
193  return result;
194  }
195 
196  private GisType find_type_detail(Connection conn,
197  String ref_table_name,
198  String ref_column_name,
199  String column_name) throws SQLException {
200  String omnisci_type = null;
201  Statement detail_st = conn.createStatement();
202  // Select for a specific column name from the ref table.
203  String select = "select type, srid from " + ref_table_name + " where "
204  + ref_column_name + " = '" + column_name + "'";
205  ResultSet rs = detail_st.executeQuery(select);
206  String ps_column_type = null;
207  int ps_srid = 0;
208  // The select statment above, can return multiple values qualified by schema/table.
209  // Unfortunately at this stage only the original postgres column name is known. If
210  // get mulitple returns with the same column name, but different types we will not be
211  // able to separate which specific column is which type. This loop checks for this
212  // condition and thows when detected.
213  while (rs.next()) {
214  String type = rs.getString(1);
215  int srid = rs.getInt(2);
216  // If multiple rows are returned with different geo types for a single coulmn name
217  // then throw.
218  if (ps_column_type != null
219  && (ps_column_type.equalsIgnoreCase(type) || srid != ps_srid)) {
220  throw new SQLException("multiple column definitions [" + ps_column_type + ":"
221  + type + "] found for column_name [" + column_name + "]");
222  }
223  ps_column_type = type;
224  ps_srid = srid;
225  }
226  if (!extra_types.containsKey(ps_column_type.toLowerCase()))
227  throw new SQLException("type not supported");
228  GisType result = new GisType();
229  result.subtype = "GEOMETRY";
230  result.srid = ps_srid;
231  result.type = extra_types.get(ps_column_type.toLowerCase()).toUpperCase();
232  return result;
233  }
234 }
static com.mapd.utility.db_vendors.Db_vendor_types Db_vendor_factory(String connection_str)
String get_wkt(ResultSet rs, int column_number, String gis_type_name)
GisType find_gis_type(Connection conn, ResultSetMetaData metadata, int column_number)
abstract GisType find_gis_type(Connection conn, ResultSetMetaData metadata, int column_number)
abstract String get_wkt(ResultSet rs, int column_number, String gis_type_name)
String get_wkt(ResultSet rs, int column_number, String gis_type_name)
boolean isAutoCommitDisabledRequired()
GisType find_gis_type(Connection conn, ResultSetMetaData metadata, int column_number)
String wkt_point(PGpoint point)
PostGis_types()
GisType find_gis_type(Connection conn, ResultSetMetaData metadata, int column_number)
GisType find_type_detail(Connection conn, String ref_table_name, String ref_column_name, String column_name)
String get_wkt(ResultSet rs, int column_number, String gis_type_name)
static String gis_type_to_str(GisType type)