diff --git a/jdbc-tibero/review.txt b/jdbc-tibero/review.txt index d867289..5467a9b 100644 --- a/jdbc-tibero/review.txt +++ b/jdbc-tibero/review.txt @@ -1,14 +1,14 @@ ================================================ 티베로 설치 후 SYSGIS에서 사용하는 법 -Tibero_6_FS06_win_64_20170310.exe ================================================ + 최초 접속시 SYS로 접속하여 다음과 같이 SYSGIS 계정의 비밀번호를 설정한다. > tbsql sys/tibero SQL> ALTER USER SYSGIS IDENTIFIED BY tibero; - > tbsql sysgis/tibero + 만약 다른 사용자에서 Spatial Extension을 사용하려면 다음의 sql문을 실행한다. -"C:\Tibero\tibero5\scripts\create_gis.sql" +"$TB_HOME\scripts\create_gis.sql" tibero_spatial_ref_sys_base.sql 문을 실행한다. 기본 사용자의 테이블이 "SYSGIS"."SPATIAL_REF_SYS_BASE" 이므로 SYSGIS 사용자가 아닐 경우 수정해서 사용 @@ -18,6 +18,7 @@ select count(*) from "admin_sgg" where ST_Intersects("the_geom", st_geomfromtext 테이블 생성 예 - road + DELETE FROM GEOMETRY_COLUMNS_BASE WHERE F_TABLE_SCHEMA = 'SYSGIS' AND F_TABLE_NAME = 'road' AND F_GEOMETRY_COLUMN = 'the_geom' INSERT INTO GEOMETRY_COLUMNS_BASE VALUES ('SYSGIS','road','the_geom',2,5174,'MULTILINESTRING', '') @@ -39,22 +40,57 @@ SELECT count(*) FROM "SYSGIS"."road" WHERE ST_Intersects("the_geom", ST_GEOMFROM SELECT count(*) FROM "SYSGIS"."road" WHERE ST_Distance("the_geom",ST_GEOMFROMTEXT('POINT (193825.86844999995 444954.60259999987)')) <= 300.0; + +※ tibero 7 이후 (또는 227917패치 및 224094패치 적용 이후) 버전의 경우 + + +(1) spatial_ref_sys_base update + +SYSGIS 계정이 아닌 다른 사용자가 Spatial Extension을 사용하려면 다음의 sql문을 실행한다. +@$TB_HOME/scripts/create_gis.sql + +기본 사용자의 테이블이 "SYSGIS"."SPATIAL_REF_SYS_BASE" 이므로 SYSGIS 사용자가 아닐 경우 다음 스크립트를 수정해서 사용한다. +@$TB_HOME/scripts/gis_register_default_srs.sql + +수동으로 SPATIAL_REF_SYS_BASE에 추가하기 위해서 REGISTER_SRS 프로시저를 사용할 수 있다. +EXEC REGISTER_SRS(102001, 'ESRI', 102001, 'PROJCS["Canada_Albers_Equal_Area_Conic",GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]],PROJECTION["Albers_Conic_Equal_Area"],PARAMETER["latitude_of_center",40],PARAMETER["longitude_of_center",-96],PARAMETER["standard_parallel_1",50],PARAMETER["standard_parallel_2",70],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH],AUTHORITY["ESRI","102001"]]', '+proj=aea +lat_0=40 +lon_0=-96 +lat_1=50 +lat_2=70 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs +type=crs'); + +SPATIAL_REF_SYS_BASE에 정보를 삭제하기 위해서 UNREGISTER_SRS 프로시저를 사용할 수 있다. +EXEC UNREGISTER_SRS('ESRI', 102001); + + +(2) 테이블 생성 예 - road + +CREATE TABLE "ROAD" (ID NUMBER, GEOM GEOMETRY); +ALTER TABLE "ROAD" ADD CONSTRAINTS "ROAD_GEOM_TYPE" CHECK (ST_GEOMETRYTYPE(GEOM) = 'MULTILINESTRING'); +ALTER TABLE "ROAD" ADD CONSTRAINTS "ROAD_GEOM_SRID" CHECK (ST_SRID(GEOM) = 4326); +INSERT INTO "ROAD" (ID, GEOM) VALUES (1, ST_GEOMFROMTEXT('MULTILINESTRING ((193908.37799999956 445507.9530999996, 193899.96140000038 445682.7842999995))', 4326)); + + +(3) feature 조회 + +SELECT TYPE FROM USER_GEOMETRY_COLUMNS WHERE F_TABLE_NAME = 'ROAD' AND F_GEOMETRY_COLUMN = 'GEOM'; +SELECT GEOMETRY_TYPE FROM USER_GEOMETRY_COLUMNS WHERE F_TABLE_NAME = 'ROAD' AND F_GEOMETRY_COLUMN = 'GEOM'; + +각 번호에 해당하는 타입은 다음과 같다. +0 - GEOMETRY +1 - POINT +2 - LINESTRING +3 - POLYGON +4 - MULTIPOINT +5 - MULTILINESTRING +6 - MULTIPOLYGON +7 - GEOMETRYCOLLECTION + +SELECT SRID FROM USER_GEOMETRY_COLUMNS WHERE F_TABLE_NAME = 'ROAD' AND F_GEOMETRY_COLUMN = 'GEOM'; +SELECT COORD_DIMENSION FROM USER_GEOMETRY_COLUMNS WHERE F_TABLE_NAME = 'ROAD' AND F_GEOMETRY_COLUMN = 'GEOM'; + + ================================================ 티베로 서비스 시작시 오류 ================================================ > tbdown clean -================================================ -import shapefile -================================================ -Tibero 4에서 gisLoader는 linux에만 사용할 수 있으나, 5 버전부터는 Windows 가능 -http://technet.tmax.co.kr/kr/inquiry/qna/tibero/readBoardForm.do?bbsCode=qna_tibero&fc=inquiry&sc=inquiry_qna&tc=inquiry_qna_tibero¤tPage=1&seqNo=49602&categoryId=&productCode=&range=10&searchType=ALL&searchText=GIS - -gisLoader seoul_pop_flow.shp seoul_pop_flow -tbloader userid=tibero/manager control=seoul_pop_flow.ctl - -gisloader FishnetOp.shp fishnet -tbloader userid=tibero/manager control=FishnetOp.ctl ================================================ geotools TiberoNGDataStoreFactory diff --git a/jdbc-tibero/src/main/java/org/geotools/data/tibero/TiberoDialect.java b/jdbc-tibero/src/main/java/org/geotools/data/tibero/TiberoDialect.java index 308f07e..e5e476f 100644 --- a/jdbc-tibero/src/main/java/org/geotools/data/tibero/TiberoDialect.java +++ b/jdbc-tibero/src/main/java/org/geotools/data/tibero/TiberoDialect.java @@ -65,6 +65,30 @@ public class TiberoDialect extends BasicSQLDialect { Version version; + // for compatibility + boolean isOldDBVersion = false; + + private static final String SYS_GIS = "SYSGIS"; + + // gis view/table + private enum GisTable { + // spatial ref sys metadata + SPATIAL_REF_SYS_BASE, + SPATIAL_REF_SYS, + + // geometry columns metadata + GEOMETRY_COLUMNS_BASE, + GEOMETRY_COLUMNS, + ALL_GEOMETRY_COLUMNS, + USER_GEOMETRY_COLUMNS, + + // units of measure + UNITS_OF_MEASURE, + AREA_UNITS, + DIST_UNITS, + ANGLE_UNITS; + } + @SuppressWarnings({ "rawtypes", "serial" }) final static Map TYPE_TO_CLASS_MAP = new HashMap() { { @@ -130,33 +154,49 @@ public boolean isAggregatedSortSupported(String function) { @Override public void initializeConnection(Connection cx) throws SQLException { super.initializeConnection(cx); + + /** + * as DB version upgraded, + * SYSGIS.GEOMETRY_COLUMNS_BASE table + * and F_GEOMETRY_TYPE column of SYSGIS.ALL_GEOMETRY_COLUMNS view + * was deleted + */ + isOldDBVersion = doesTableExist(cx, SYS_GIS, GisTable.GEOMETRY_COLUMNS_BASE.name()) + && doesColumnExist(cx, SYS_GIS, GisTable.ALL_GEOMETRY_COLUMNS.name(), "F_GEOMETRY_TYPE"); + } + + private boolean doesTableExist(Connection cx, String schemaName, String tableName) throws SQLException { + DatabaseMetaData metaData = cx.getMetaData(); + try (ResultSet rs = metaData.getTables(null, schemaName, tableName, null)) { + return rs.next(); + } + } + + private boolean doesColumnExist(Connection cx, String schemaName, String tableName, String columnName) throws SQLException { + DatabaseMetaData metaData = cx.getMetaData(); + try (ResultSet rs = metaData.getColumns(null, schemaName, tableName, columnName)){ + return rs.next(); + } } @Override public boolean includeTable(String schemaName, String tableName, Connection cx) throws SQLException { - if (tableName.equalsIgnoreCase("GEOMETRY_COLUMNS_BASE")) { - return false; - } else if (tableName.equalsIgnoreCase("SPATIAL_REF_SYS_BASE")) { - return false; - } else if (tableName.equalsIgnoreCase("GEOMETRY_COLUMNS")) { - return false; - } else if (tableName.equalsIgnoreCase("SPATIAL_REF_SYS")) { - return false; - } else if (tableName.equalsIgnoreCase("ALL_GEOMETRY_COLUMNS")) { - return false; - } else if (tableName.equalsIgnoreCase("USER_GEOMETRY_COLUMNS")) { - return false; + // check if related to gis view/table + for (GisTable gisTable : GisTable.values()) { + if (tableName.equalsIgnoreCase(gisTable.name())) { + return false; + } } // tables in geometry_columns if (schemaName == null || schemaName.isEmpty()) { - schemaName = "SYSGIS"; + schemaName = SYS_GIS; } StringBuffer sql = new StringBuffer(); - sql.append("SELECT F_TABLE_NAME FROM GEOMETRY_COLUMNS_BASE WHERE "); - sql.append(" F_TABLE_SCHEMA = '").append(schemaName).append("' "); + sql.append("SELECT F_TABLE_NAME FROM ").append(GisTable.GEOMETRY_COLUMNS.name()); + sql.append(" WHERE F_TABLE_SCHEMA = '").append(schemaName).append("'"); sql.append(" AND F_TABLE_NAME = '").append(tableName).append("'"); Statement statement = null; @@ -257,9 +297,9 @@ public List getOptimizedBounds(String schema, SimpleFeatureT GeometryDescriptor att = featureType.getGeometryDescriptor(); String geometryField = att.getName().getLocalPart(); - // ==================Support: Tibero 5====================== + // ===================Support: Tibero 5, 6, 7======================== // SELECT MIN(ST_MINX(OBJ)), MIN(ST_MINY(OBJ)), MAX(ST_MAXX(OBJ)), MAX(ST_MAXY(OBJ)) FROM ROAD; - // ========================================================= + // ================================================================== StringBuffer sql = new StringBuffer(); sql.append("SELECT "); @@ -267,9 +307,7 @@ public List getOptimizedBounds(String schema, SimpleFeatureT sql.append(", MIN(ST_MINY(\"").append(geometryField).append("\"))"); sql.append(", MAX(ST_MAXX(\"").append(geometryField).append("\"))"); sql.append(", MAX(ST_MAXY(\"").append(geometryField).append("\"))"); - sql.append(" FROM \""); - sql.append(tableName); - sql.append("\""); + sql.append(" FROM \"").append(tableName).append("\""); rs = st.executeQuery(sql.toString()); if (rs.next()) { @@ -330,7 +368,7 @@ public Class getMapping(ResultSet columnMetaData, Connection cx) throws SQLEx String gType = null; if ("geometry".equalsIgnoreCase(typeName)) { - gType = lookupGeometryType(columnMetaData, cx, "geometry_columns", "f_geometry_column"); + gType = lookupGeometryType(columnMetaData, cx, GisTable.GEOMETRY_COLUMNS.name(), "F_GEOMETRY_COLUMN"); } else { return null; } @@ -361,7 +399,9 @@ String lookupGeometryType(ResultSet columnMetaData, Connection cx, String gTable ResultSet result = null; try { - String sqlStatement = "SELECT F_GEOMETRY_TYPE FROM " + gTableName + " WHERE " // + String typeStr = (isOldDBVersion)? "F_GEOMETRY_TYPE" : "TYPE"; + + String sqlStatement = "SELECT " + typeStr + " FROM " + gTableName + " WHERE " // + "F_TABLE_SCHEMA = '" + schemaName + "' " // + "AND F_TABLE_NAME = '" + tableName + "' " // + "AND " + gColumnName + " = '" + columnName + "'"; @@ -384,13 +424,10 @@ String lookupGeometryType(ResultSet columnMetaData, Connection cx, String gTable @Override public void handleUserDefinedType(ResultSet columnMetaData, ColumnMetadata metadata, Connection cx) throws SQLException { - String tableName = columnMetaData.getString("TABLE_NAME"); - String columnName = columnMetaData.getString("COLUMN_NAME"); String schemaName = columnMetaData.getString("TABLE_SCHEM"); - String sql = "SELECT udt_name FROM information_schema.columns " + " WHERE table_schema = '" - + schemaName + "' " + " AND table_name = '" + tableName + "' " - + " AND column_name = '" + columnName + "' "; + String sql = "SELECT type_name FROM all_types " + " WHERE owner = '" + schemaName; + LOGGER.fine(sql); Statement st = cx.createStatement(); @@ -492,6 +529,10 @@ public String getSequenceForColumn(String schemaName, String tableName, String c return "seq_" + tableName + "_" + columnName; } + private String getSpatialIdxName(String tableName, String columnName) { + return "SPATIAL_" + tableName + "_" + columnName; + } + @Override public Object getNextSequenceValue(String schemaName, String sequenceName, Connection cx) throws SQLException { @@ -636,6 +677,8 @@ public void postCreateTable(String schemaName, SimpleFeatureType featureType, Co if (att instanceof GeometryDescriptor) { GeometryDescriptor gd = (GeometryDescriptor) att; + String columnName = gd.getLocalName(); + // lookup or reverse engineer the srid int srid = 101; // default value @@ -654,7 +697,7 @@ public void postCreateTable(String schemaName, SimpleFeatureType featureType, Co } } - // assume 2 dimensions, but ease future customisation + // assume 2 dimensions, but ease future customization int dimensions = 2; if (gd.getUserData().get(Hints.COORDINATE_DIMENSION) != null) { dimensions = (Integer) gd.getUserData().get(Hints.COORDINATE_DIMENSION); @@ -666,34 +709,46 @@ public void postCreateTable(String schemaName, SimpleFeatureType featureType, Co geomType = "GEOMETRY"; } - // register the geometry type, first remove and eventual - // leftover, then write out the real one - String sql = "DELETE FROM GEOMETRY_COLUMNS_BASE" + " WHERE F_TABLE_SCHEMA = '" - + schemaName + "'" // - + " AND F_TABLE_NAME = '" + tableName + "'" // - + " AND F_GEOMETRY_COLUMN = '" + gd.getLocalName() + "'"; + String sql = ""; + if (isOldDBVersion) { + // register the geometry type, first remove and eventual + // leftover, then write out the real one + sql = "DELETE FROM " + SYS_GIS + "." + GisTable.GEOMETRY_COLUMNS_BASE.name() // + + " WHERE F_TABLE_SCHEMA = '" + schemaName + "'" // + + " AND F_TABLE_NAME = '" + tableName + "'" // + + " AND F_GEOMETRY_COLUMN = '" + columnName + "'"; + LOGGER.fine(sql); + st.execute(sql); - LOGGER.fine(sql); - st.execute(sql); + sql = "INSERT INTO " + SYS_GIS + "." + GisTable.GEOMETRY_COLUMNS_BASE.name() + " VALUES (" // + + "'" + schemaName + "'," // + + "'" + tableName + "'," // + + "'" + columnName + "'," // + + dimensions + "," // + + srid + "," // + + "'" + geomType + "', '')"; + LOGGER.fine(sql); + st.execute(sql); + } - sql = "INSERT INTO GEOMETRY_COLUMNS_BASE VALUES (" // - + "'" + schemaName + "'," // - + "'" + tableName + "'," // - + "'" + gd.getLocalName() + "'," // - + dimensions + "," // - + srid + "," // - + "'" + geomType + "', '')"; + // drop spatial index + // DROP INDEX INDEX_NAME; + String idxName = getSpatialIdxName(tableName, columnName); + sql = "DROP INDEX \"" + idxName + "\""; LOGGER.fine(sql); - st.execute(sql); + try { + st.execute(sql); + } catch (Exception e) { + LOGGER.fine(e.getMessage()); + } // add the spatial index // CREATE INDEX IDX_STORES_GEOMETRY ON SYSGIS.STORES("the_geom") RTREE; - sql = "CREATE INDEX \"SPATIAL_" + tableName // - + "_" + gd.getLocalName() + "\""// + sql = "CREATE INDEX \"" + idxName + "\"" // + " ON " // + "\"" + tableName + "\"" // + " (" // - + "\"" + gd.getLocalName() + "\"" // + + "\"" + columnName + "\"" // + ") RTREE"; LOGGER.fine(sql); st.execute(sql); @@ -701,6 +756,7 @@ public void postCreateTable(String schemaName, SimpleFeatureType featureType, Co // create sequence String sequenceName = getSequenceForColumn(schemaName, tableName, "fid", cx); sql = "DROP SEQUENCE \"" + sequenceName + "\""; + LOGGER.fine(sql); try { st.execute(sql); } catch (Exception e) { @@ -710,8 +766,8 @@ public void postCreateTable(String schemaName, SimpleFeatureType featureType, Co // CREATE SEQUENCE seq_building_fid START WITH 1 INCREMENT BY 1 MINVALUE 1 // NOMAXVALUE // INSERT INTO SEQTBL VALUES(seq1.NEXTVAL); - sql = "CREATE SEQUENCE \"" + sequenceName - + "\" START WITH 1 INCREMENT BY 1 MINVALUE 1 NOMAXVALUE"; + sql = "CREATE SEQUENCE \"" + sequenceName + "\"" // + + " START WITH 1 INCREMENT BY 1 MINVALUE 1 NOMAXVALUE"; LOGGER.fine(sql); st.execute(sql); } @@ -726,13 +782,17 @@ public void postCreateTable(String schemaName, SimpleFeatureType featureType, Co public void postDropTable(String schemaName, SimpleFeatureType featureType, Connection cx) throws SQLException { Statement st = cx.createStatement(); + try { - String tableName = featureType.getTypeName(); - // remove all the geometry_column entries - String sql = "DELETE FROM GEOMETRY_COLUMNS_BASE" + " WHERE F_TABLE_SCHEMA = '" - + schemaName + "'" + " AND F_TABLE_NAME = '" + tableName + "'"; - LOGGER.fine(sql); - st.execute(sql); + if (isOldDBVersion) { + String tableName = featureType.getTypeName(); + // remove all the geometry_column entries + String sql = "DELETE FROM " + SYS_GIS + "." + GisTable.GEOMETRY_COLUMNS_BASE.name() // + + " WHERE F_TABLE_SCHEMA = '" + schemaName + "'" // + + " AND F_TABLE_NAME = '" + tableName + "'"; + LOGGER.fine(sql); + st.execute(sql); + } } finally { dataStore.closeSafe(st); } @@ -771,16 +831,16 @@ public void applyLimitOffset(StringBuffer sql, int limit, int offset) { // see http://progcookbook.blogspot.com/2006/02/using-rownum-properly-for-pagination.html // and http://www.oracle.com/technology/oramag/oracle/07-jan/o17asktom.html // to understand why we are going thru such hoops in order to get it working - // The same techinique is used in Hibernate to support pagination + // The same technique is used in Hibernate to support pagination if (offset == 0) { sql.insert(0, "SELECT * FROM ("); - sql.append(") WHERE ROWNUM <= " + limit); + sql.append(") WHERE ROWNUM <= ").append(limit); } else { long max = (limit == Integer.MAX_VALUE ? Long.MAX_VALUE : limit + offset); sql.insert(0, "SELECT * FROM (SELECT A.*, ROWNUM RNUM FROM ( "); - sql.append(") A WHERE ROWNUM <= " + max + ")"); - sql.append("WHERE RNUM > " + offset); + sql.append(") A WHERE ROWNUM <= ").append(max).append(")"); + sql.append("WHERE RNUM > ").append(offset); } }