Revision 661

View differences:

org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/pom.xml
1
<?xml version="1.0" encoding="UTF-8"?>
2

  
3
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4

  
5
    <modelVersion>4.0.0</modelVersion>
6
    <artifactId>org.gvsig.oracle.provider</artifactId>
7
    <packaging>jar</packaging>
8
    <name>${project.artifactId}</name>
9
    <description>DAL provider for PostgeSQL files</description>
10
    <parent>
11
        <groupId>org.gvsig</groupId>
12
        <artifactId>org.gvsig.oracle</artifactId>
13
        <version>2.0.104</version>
14
    </parent>
15

  
16
    <dependencies>
17
        <dependency>
18
            <groupId>com.googlecode.log4jdbc</groupId>
19
            <artifactId>log4jdbc</artifactId>
20
            <scope>compile</scope>
21
        </dependency>
22
        <dependency>
23
            <groupId>org.gvsig</groupId>
24
            <artifactId>org.gvsig.tools.lib</artifactId>
25
            <scope>compile</scope>
26
        </dependency>
27
        <dependency>
28
            <groupId>org.gvsig</groupId>
29
            <artifactId>org.gvsig.projection.api</artifactId>
30
            <scope>compile</scope>
31
        </dependency>
32
        <dependency>
33
            <groupId>org.gvsig</groupId>
34
            <artifactId>org.gvsig.fmap.dal.api</artifactId>
35
            <scope>compile</scope>
36
        </dependency>
37
    
38
        <dependency>
39
            <groupId>org.gvsig</groupId>
40
            <artifactId>org.gvsig.fmap.dal.db.jdbc</artifactId>
41
            <scope>compile</scope>
42
        </dependency>
43
        <dependency>
44
            <groupId>org.gvsig</groupId>
45
            <artifactId>org.gvsig.fmap.dal.db.jdbc</artifactId>
46
            <scope>test</scope>
47
            <type>test-jar</type>
48
        </dependency>
49

  
50
        <dependency>
51
            <groupId>org.gvsig</groupId>
52
            <artifactId>org.gvsig.fmap.dal.db.lib</artifactId>
53
            <scope>compile</scope>
54
        </dependency>
55
    
56
        <dependency>
57
            <groupId>org.gvsig</groupId>
58
            <artifactId>org.gvsig.fmap.dal.spi</artifactId>
59
            <scope>compile</scope>
60
        </dependency>
61
        <dependency>
62
            <groupId>org.gvsig</groupId>
63
            <artifactId>org.gvsig.metadata.lib.basic.api</artifactId>
64
            <scope>compile</scope>
65
        </dependency>
66
        <dependency>
67
            <groupId>org.gvsig</groupId>
68
            <artifactId>org.gvsig.fmap.geometry.api</artifactId>
69
            <scope>compile</scope>
70
        </dependency>
71
        <dependency>
72
            <groupId>org.gvsig</groupId>
73
            <artifactId>org.gvsig.expressionevaluator.lib.api</artifactId>
74
            <scope>compile</scope>
75
        </dependency>
76
        <dependency>
77
            <groupId>org.gvsig</groupId>
78
            <artifactId>org.gvsig.expressionevaluator.geometry.lib.api</artifactId>
79
            <scope>compile</scope>
80
        </dependency>
81
        <dependency>
82
            <groupId>org.gvsig</groupId>
83
            <artifactId>org.gvsig.timesupport.lib.api</artifactId>
84
            <scope>compile</scope>
85
        </dependency>  
86
        <dependency>
87
            <groupId>org.gvsig</groupId>
88
            <artifactId>org.gvsig.utils</artifactId>
89
            <scope>compile</scope>
90
        </dependency>
91

  
92
        <dependency>
93
            <groupId>com.oracle</groupId>
94
            <artifactId>ojdbc</artifactId>
95
            <scope>compile</scope>
96
        </dependency>
97

  
98
        <dependency>
99
            <groupId>commons-dbcp</groupId>
100
            <artifactId>commons-dbcp</artifactId>
101
            <scope>compile</scope>
102
        </dependency>
103
        <dependency>
104
            <groupId>commons-collections</groupId>
105
            <artifactId>commons-collections</artifactId>
106
            <scope>compile</scope>
107
        </dependency>
108

  
109

  
110
        <!-- TESTS -->
111
        <dependency>
112
            <groupId>org.gvsig</groupId>
113
            <artifactId>org.gvsig.fmap.dal.impl</artifactId>
114
            <scope>test</scope>
115
        </dependency>
116
        <dependency>
117
            <groupId>org.gvsig</groupId>
118
            <artifactId>${org.gvsig.fmap.geometry.impl}</artifactId>
119
            <scope>test</scope>
120
        </dependency>    
121
        <dependency>
122
            <groupId>org.gvsig</groupId>
123
            <artifactId>org.gvsig.tools.lib</artifactId>
124
            <type>test-jar</type>
125
            <scope>test</scope>
126
        </dependency>
127
        <dependency>
128
            <groupId>org.gvsig</groupId>
129
            <artifactId>org.gvsig.compat.se</artifactId>
130
            <scope>test</scope>
131
        </dependency>
132
        <dependency>
133
            <groupId>org.gvsig</groupId>
134
            <artifactId>org.gvsig.expressionevaluator.lib.impl</artifactId>
135
            <scope>test</scope>
136
        </dependency>
137
        <dependency>
138
            <groupId>org.gvsig</groupId>
139
            <artifactId>org.gvsig.expressionevaluator.geometry.lib.impl</artifactId>
140
            <scope>test</scope>
141
        </dependency>
142
        <dependency>
143
            <groupId>org.gvsig</groupId>
144
            <artifactId>${org.gvsig.proj.lib.impl}</artifactId>
145
            <scope>test</scope>
146
        </dependency>
147
    
148
        <!--    <dependency>
149
          <groupId>org.gvsig</groupId>
150
          <artifactId>org.gvsig.projection.cresques.impl</artifactId>
151
          <scope>test</scope>
152
        </dependency>-->
153
<!--        <dependency>
154
            <groupId>org.gvsig</groupId>
155
            <artifactId>org.gvsig.compat.se</artifactId>
156
            <scope>test</scope>
157
        </dependency>-->
158
        <dependency>
159
            <groupId>org.gvsig</groupId>
160
            <artifactId>org.gvsig.metadata.lib.basic.impl</artifactId>
161
            <scope>test</scope>
162
        </dependency>      
163
        <dependency>
164
            <groupId>org.gvsig</groupId>
165
            <artifactId>org.gvsig.timesupport.lib.impl</artifactId>
166
            <scope>test</scope>
167
        </dependency>   
168

  
169
        <dependency>
170
            <groupId>org.gvsig</groupId>
171
            <artifactId>org.gvsig.fmap.dal.file.csv</artifactId>
172
            <scope>test</scope>
173
        </dependency>
174
        <dependency>
175
            <groupId>org.gvsig</groupId>
176
            <artifactId>org.gvsig.fmap.dal.file.lib</artifactId>
177
            <scope>test</scope>
178
        </dependency>
179
        <dependency>
180
            <groupId>org.gvsig</groupId>
181
            <artifactId>org.gvsig.tools.util.impl</artifactId>
182
            <scope>test</scope>
183
        </dependency>
184

  
185
    </dependencies>
186

  
187
    <build>
188
        <plugins>
189

  
190
            <plugin>
191
                <groupId>org.apache.maven.plugins</groupId>
192
                <artifactId>maven-surefire-plugin</artifactId>
193
                <configuration>
194
                    <!-- Skip test execution ? -->
195
                    <skipTests>false</skipTests>
196
                    <!-- Ignore test execution failure ? -->
197
                    <testFailureIgnore>false</testFailureIgnore>
198
                    <excludes>
199
                        <exclude>**/TestCreate.java</exclude>
200
                    </excludes>
201
                </configuration>
202
            </plugin>
203
        
204
            <!-- Skip test compilation ? -->
205
            <plugin>
206
                <groupId>org.apache.maven.plugins</groupId>
207
                <artifactId>maven-compiler-plugin</artifactId>
208
                <executions>
209
                    <execution>
210
                        <id>default-testCompile</id>
211
                        <phase>process-test-sources</phase>
212
                        <goals>
213
                            <goal>testCompile</goal>
214
                        </goals>
215
                        <configuration>
216
                            <skip>false</skip>
217
                        </configuration>
218
                    </execution>
219
                </executions>
220
            </plugin>
221

  
222
        </plugins>
223
    </build>
224

  
225
</project>
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/resources/META-INF/services/org.gvsig.tools.library.Library
1
org.gvsig.oracle.dal.OracleLibrary
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/resources/srids/oracle2epsg.properties
1
81920=4202
2
81921=4203
3
81922=20248
4
81923=20348
5
81924=20249
6
81925=20349
7
81926=20250
8
81927=20350
9
81928=20251
10
81929=20351
11
81930=20252
12
81931=20352
13
81932=20253
14
81933=20353
15
81934=20254
16
81935=20354
17
81936=20255
18
81937=20355
19
81938=20256
20
81939=20356
21
81940=20257
22
81941=20357
23
81942=20258
24
81943=20358
25
82323=23028
26
82328=23029
27
82337=23030
28
82340=23031
29
82343=23032
30
82346=23033
31
82349=23034
32
82352=23035
33
82355=23036
34
82358=23037
35
82361=23038
36
524288=4326
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/resources/org/gvsig/oracle/dal/OracleMetadata.xml
1
<?xml version="1.0"?>
2
<definitions>
3
  <version>1.0.0</version>
4
  <classes>
5
    <class name="Oracle" namespace="Metadata">
6
      <extends>
7
      	<class name="JDBC2" namespace="Metadata"/>
8
      </extends>
9
      <description>Metadata of a Oracle store</description>
10
      <fields>
11
      </fields>
12
    </class>
13

  
14
  </classes>
15
</definitions>  
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/resources/org/gvsig/oracle/dal/OracleParameters.xml
1
<?xml version="1.0"?>
2
<definitions>
3
  <version>1.0.0</version>
4
  <classes>
5
    <class name="OracleResourceParameters">
6
      <extends>
7
        <class>JDBC2ResourceParameters</class>
8
      </extends>
9
      <fields>
10
        <field name="JDBCDriverClass" type="string" mandatory="true"
11
          defaultValue="oracle.jdbc.driver.OracleDriver" group="Advanced">
12
          <description>JDBC Driver class</description>
13
        </field>
14
        <field name="host" type="string" mandatory="false" 
15
            defaultValue="127.0.0.1" group="Connection">
16
          <description></description>
17
        </field>
18
	<field name="port" type="integer" mandatory="false"
19
          defaultValue="1521" group="Connection">
20
          <description></description>
21
        </field>
22
        
23
        <field name="mode" type="string" mandatory="false" defaultValue="SID" group="Connection">
24
          <description></description>
25
  	  <availableValues>
26
            <value label="Service">SERVICE</value>
27
            <value label="SID">SID</value>
28
          </availableValues>
29
        </field>
30
        
31
	<field name="LobPrefetchSize" type="String" mandatory="false"
32
          defaultValue="" group="Advanced">
33
          <description></description>
34
        </field>
35
	<field name="updateSpatialIndexAndMetadata" label="Update spatial index and metadata" type="boolean" mandatory="false"
36
          defaultValue="true" group="Advanced">
37
          <description></description>
38
        </field>
39
      </fields>
40
    </class>
41

  
42
    <class name="OracleStoreParameters">
43
      <extends>
44
        <class>JDBC2StoreParameters</class>
45
        <class>OracleResourceParameters</class>
46
      </extends>
47
      <fields/>
48
    </class>
49

  
50
    <class name="OracleNewStoreParameters">
51
      <extends>
52
        <class>JDBC2NewStoreParameters</class>
53
        <class>OracleResourceParameters</class>
54
      </extends>
55
      <fields/>
56
    </class>
57

  
58

  
59
    <class name="OracleServerExplorerParameters">
60
      <extends>
61
        <class>OracleResourceParameters</class>
62
        <class>JDBC2ServerExplorerParameters</class>
63
      </extends>
64
      <fields/>
65
    </class>
66

  
67

  
68
  </classes>
69
</definitions>  
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/java/org/gvsig/oracle/dal/OracleNewStoreParameters.java
1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22
package org.gvsig.oracle.dal;
23

  
24
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
25
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParametersBase;
26

  
27
public class OracleNewStoreParameters 
28
    extends 
29
        JDBCNewStoreParametersBase 
30
    implements 
31
        OracleConnectionParameters 
32
    {
33

  
34
    private final OracleConnectionParametersHelper helper;
35
    
36
    public OracleNewStoreParameters() {
37
        super(
38
            OracleLibrary.NAME + "NewStoreParameters", 
39
            OracleLibrary.NAME
40
        );
41
        this.helper = new OracleConnectionParametersHelper(this);
42
    }
43

  
44
    @Override
45
    public String getUrl() {
46
        return this.helper.getUrl();
47
    }
48
    
49
    @Override
50
    public void validate() throws ValidateDataParametersException {
51
        this.helper.validate();
52
    }
53

  
54
    @Override
55
    public void setTable(String table) {
56
        super.setTable(table.toUpperCase());
57
    }
58

  
59
    @Override
60
    public String getMode() {
61
        return this.helper.getMode();
62
    }
63

  
64
    @Override
65
    public void setMode(String mode) {
66
        this.helper.setMode(mode);
67
    }    
68
    public Integer getLobPrefetchSize() {
69
        return this.helper.getLobPrefetchSize();
70
    }
71

  
72
    public void setLobPrefetchSize(Integer size) {
73
        this.helper.setLobPrefetchSize(size);
74
    }
75

  
76
    @Override
77
    public boolean getUpdateSpatialIndexAndMetadata() {
78
        return this.helper.getUpdateSpatialIndexAndMetadata();
79
    }
80

  
81
    @Override
82
    public void setUpdateSpatialIndexAndMetadata(boolean updateSpatialIndexAndMetadata) {
83
        this.helper.setUpdateSpatialIndexAndMetadata(updateSpatialIndexAndMetadata);
84
    }
85
}
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/java/org/gvsig/oracle/dal/OracleStoreProviderFactory.java
1

  
2
package org.gvsig.oracle.dal;
3

  
4
import org.gvsig.fmap.dal.DataParameters;
5
import org.gvsig.fmap.dal.exception.InitializeException;
6
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
7
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
8
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParametersBase;
9
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
10
import org.gvsig.fmap.dal.store.jdbc2.JDBCStoreProvider;
11
import org.gvsig.fmap.dal.store.jdbc2.impl.JDBCStoreProviderFactoryBase;
12
import org.slf4j.Logger;
13
import org.slf4j.LoggerFactory;
14

  
15

  
16
public class OracleStoreProviderFactory extends JDBCStoreProviderFactoryBase {
17
    
18
    private static final Logger LOGGER = LoggerFactory.getLogger(OracleStoreProviderFactory.class);
19

  
20
    public OracleStoreProviderFactory() {
21
        super(
22
                OracleLibrary.NAME, 
23
                OracleLibrary.NAME + " store"
24
        );
25
    }
26

  
27
    @Override
28
    public JDBCStoreProvider createProvider(
29
            DataParameters parameters,
30
            DataStoreProviderServices providerServices
31
    ) throws InitializeException {
32
        JDBCHelper helper = new OracleHelper((JDBCConnectionParameters) parameters);
33
        JDBCStoreProvider provider = null;
34
        try {
35
	        provider = helper.createProvider((JDBCStoreParametersBase) parameters, 
36
	                providerServices
37
	        );
38
        }
39
        catch (Exception exc) {
40
            LOGGER.trace("Can't create Oracle provider (this could be correct)", exc);
41
        }
42
        return provider;
43
    }
44

  
45
    @Override
46
    public JDBCStoreParametersBase createParameters() {
47
        JDBCStoreParametersBase params = new OracleStoreParameters();
48
        return params;
49
    }
50
    
51
    public boolean preferNotToUseNonNullRestrictions() {
52
    	return true;
53
    }
54
    
55
}
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/java/org/gvsig/oracle/dal/OracleSRSSolver.java
1
/*
2
 * To change this license header, choose License Headers in Project Properties.
3
 * To change this template file, choose Tools | Templates
4
 * and open the template in the editor.
5
 */
6
package org.gvsig.oracle.dal;
7

  
8
import java.io.IOException;
9
import java.io.InputStream;
10
import java.util.Objects;
11
import java.util.Properties;
12
import org.gvsig.fmap.dal.store.jdbc2.JDBCConnection;
13
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
14
import org.gvsig.fmap.dal.store.jdbc2.spi.SRSSolverBase;
15

  
16
/**
17
 *
18
 * @author fdiaz
19
 */
20
public class OracleSRSSolver extends SRSSolverBase{
21

  
22
    private static Properties translations;
23
    
24
    public OracleSRSSolver(JDBCHelper helper) {
25
        super(helper);
26
    }
27
    
28
    @Override
29
    protected Object searchDatabaseCode(JDBCConnection connection, String applicationAbbrev) {
30
        try {
31
            String[] s = applicationAbbrev.split(":");
32
            String code_s = s[1].trim();
33
            try {
34
                int code_i = Integer.parseInt(code_s);
35
                return code_i;
36
            } catch(NumberFormatException e) {
37
                
38
            }
39
            return 0;
40
        } catch (Throwable ex) {
41
            throw new RuntimeException("Problems searching database code from '"+applicationAbbrev+"'.",ex);
42
        }
43
    }
44

  
45
    @Override
46
    protected String searchApplicationAbbrev(JDBCConnection connection, Integer databaseCode) {
47
        try {
48
            String s = Objects.toString(databaseCode,"0");
49
            String trans = getTranslation(s, null);
50
            if(trans == null){
51
                return null;
52
            }
53
            return "EPSG:" + trans;
54
        } catch (Throwable ex) {
55
            throw new RuntimeException("Problems searching application abbrev from '"+databaseCode+"'.",ex);
56
        }
57
    }    
58
    
59
    private String getTranslation(String databaseCode, String defaultValue) {
60
        if (translations == null) {
61
            InputStream inStream = this.getClass().getClassLoader().getResourceAsStream("/srids/oracle2epsg.properties");
62
            if (inStream != null) {
63
                translations = new Properties();
64
                try {
65
                    translations.load(inStream);
66
                } catch (IOException ex) {
67
                    logger.warn("Can't load srid translations", ex);
68
                }
69

  
70
            }
71
        }
72
        if( this.translations==null ) {
73
            return defaultValue;
74
        }
75
        return translations.getProperty(databaseCode, defaultValue);
76
    }
77

  
78
}
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/java/org/gvsig/oracle/dal/OracleLibrary.java
1

  
2
package org.gvsig.oracle.dal;
3

  
4
import org.gvsig.fmap.dal.DALLibrary;
5
import org.gvsig.fmap.dal.DALLocator;
6
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
7
import org.gvsig.fmap.dal.store.db.DBHelper;
8
import org.gvsig.fmap.dal.store.jdbc2.JDBCLibrary;
9
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCStoreProviderBase;
10
import org.gvsig.json.Json;
11
import org.gvsig.metadata.exceptions.MetadataException;
12
import org.gvsig.tools.library.AbstractLibrary;
13
import org.gvsig.tools.library.LibraryException;
14

  
15

  
16
public class OracleLibrary extends AbstractLibrary {
17

  
18
    public static final String NAME = "Oracle";
19

  
20
    @Override
21
    public void doRegistration() {
22
        registerAsServiceOf(DALLibrary.class);
23
        require(JDBCLibrary.class);
24
    }
25

  
26
    @Override
27
    protected void doInitialize() throws LibraryException {
28
    }
29

  
30
    @Override
31
    protected void doPostInitialize() throws LibraryException {
32
        LibraryException ex = null;
33

  
34
        DataManagerProviderServices dataman = 
35
                (DataManagerProviderServices) DALLocator.getDataManager();
36

  
37
        try {
38
            Class.forName(OracleHelper.ORACLE_JDBC_DRIVER);
39
        } catch(Throwable th) {
40
            OracleHelper.LOGGER.warn("Can't load Oracle JDBC Driver.",th);
41
        }
42
        
43
        DBHelper.registerParametersDefinition(
44
                NAME + "StoreParameters",
45
                OracleStoreParameters.class,
46
                dataman.getResourceAsStream(this, NAME + "Parameters.xml")
47
        );
48
        DBHelper.registerParametersDefinition(
49
                NAME + "NewStoreParameters",
50
                OracleNewStoreParameters.class,
51
                dataman.getResourceAsStream(this, NAME + "Parameters.xml")
52
        );
53
        DBHelper.registerParametersDefinition(
54
                NAME + "ServerExplorerParameters",
55
                OracleExplorerParameters.class,
56
                dataman.getResourceAsStream(this, NAME + "Parameters.xml")
57
        );
58
        try {
59
            DBHelper.registerMetadataDefinition(
60
                NAME,
61
                JDBCStoreProviderBase.class,
62
                dataman.getResourceAsStream(this, NAME + "Metadata.xml")
63
            );
64
        } catch (MetadataException e) {
65
            ex = new LibraryException(this.getClass(), e);
66
        }
67

  
68
        if (!dataman.getStoreProviderRegister().exits(NAME)) {
69
            dataman.registerStoreProviderFactory(new OracleStoreProviderFactory());
70
        }
71

  
72
        if (!dataman.getServerExplorerRegister().exits(NAME)) {
73
            dataman.registerServerExplorerFactory(new OracleExplorerFactory());
74
        }
75

  
76
        Json.registerSerializer(OracleExplorerParameters.class);
77

  
78
        if (ex != null) {
79
            throw ex;
80
        }
81
    }
82

  
83
}
org.gvsig.oracle/tags/org.gvsig.oracle-2.0.104/org.gvsig.oracle.provider/src/main/java/org/gvsig/oracle/dal/OracleSQLBuilder.java
1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.oracle.dal;
25

  
26
import java.io.ByteArrayInputStream;
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.io.OutputStream;
30
import java.sql.Connection;
31
import java.sql.PreparedStatement;
32
import java.sql.SQLException;
33
import java.sql.Time;
34
import java.sql.Timestamp;
35
import java.text.MessageFormat;
36
import java.util.ArrayList;
37
import java.util.List;
38
import java.util.Objects;
39
import oracle.sql.BLOB;
40
import org.apache.commons.dbcp.DelegatingConnection;
41
import org.apache.commons.lang3.BooleanUtils;
42
import org.apache.commons.lang3.StringUtils;
43
import org.apache.commons.lang3.tuple.Pair;
44
import org.gvsig.expressionevaluator.DelegatedGeometryExpressionBuilder;
45
import org.gvsig.expressionevaluator.ExpressionBuilder;
46
import static org.gvsig.expressionevaluator.ExpressionBuilder.PARAMETER_TYPE_CONSTANT;
47
import static org.gvsig.expressionevaluator.ExpressionBuilder.PARAMETER_TYPE_VARIABLE;
48
import static org.gvsig.expressionevaluator.ExpressionBuilder.VALUE_NULL;
49
import org.gvsig.expressionevaluator.ExpressionUtils;
50
import org.gvsig.expressionevaluator.Formatter;
51
import org.gvsig.expressionevaluator.GeometryExpressionBuilder;
52
import org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType;
53
import static org.gvsig.expressionevaluator.GeometryExpressionBuilderHelper.GeometrySupportType.WKT;
54
import org.gvsig.fmap.dal.DataTypes;
55
import org.gvsig.fmap.dal.SQLBuilder;
56
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
57
import org.gvsig.fmap.dal.feature.FeatureType;
58
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
59
import org.gvsig.fmap.dal.store.jdbc.JDBCConnectionParameters;
60
import org.gvsig.fmap.dal.store.jdbc2.JDBCHelper;
61
import org.gvsig.fmap.dal.store.jdbc2.spi.JDBCSQLBuilderBase;
62
import org.gvsig.fmap.geom.Geometry;
63
import org.gvsig.fmap.geom.GeometryUtils;
64
import org.gvsig.fmap.geom.primitive.Envelope;
65
import org.gvsig.oracle.dal.expressionbuilderformatter.OracleFormatter;
66
import static org.gvsig.oracle.dal.expressionbuilderformatter.OracleGeometryParameter.ORACLE_GEOMETRY_PARAMETER;
67
import org.gvsig.tools.ToolsLocator;
68
import org.gvsig.tools.dataTypes.Coercion;
69
import org.gvsig.tools.dataTypes.DataType;
70
import org.gvsig.tools.dataTypes.DataTypeUtils;
71
import org.gvsig.tools.dataTypes.DataTypesManager;
72
import org.gvsig.tools.dispose.Disposable;
73

  
74
public class OracleSQLBuilder extends JDBCSQLBuilderBase {
75

  
76
    protected static final String ADD_SERIAL_COLUMN_SEQUENCE_QUERY = "CREATE SEQUENCE \"{0}\"";
77
    protected static final String ADD_SERIAL_COLUMN_TRIGGER_QUERY = "CREATE OR REPLACE TRIGGER \"{0}\" BEFORE INSERT ON {1} FOR EACH ROW "
78
            + "BEGIN SELECT \"{3}\".NEXTVAL INTO :new.\"{2}\" FROM dual; END;";
79
    protected static final String DELETE_FROM_OGIS_GEOMETRY_COLUMNS_QUERY = "DELETE FROM MDSYS.OGIS_GEOMETRY_COLUMNS "
80
            + "WHERE F_TABLE_SCHEMA = ''{0}'' AND F_TABLE_NAME = ''{1}'' AND F_GEOMETRY_COLUMN = ''{2}''";
81
    protected static final String INSERT_OGIS_GEOMETRY_COLUMNS_QUERY = "INSERT INTO MDSYS.OGIS_GEOMETRY_COLUMNS "
82
            + "(F_TABLE_SCHEMA, F_TABLE_NAME, F_GEOMETRY_COLUMN, GEOMETRY_TYPE) VALUES "
83
            + "(''{0}'', ''{1}'', ''{2}'', {3})";
84
    private final String quote_for_identifiers;
85
    private final String quote_for_strings;
86
    public static final String ST_GEOMFROMTEXT = "SDO_GEOMETRY(({0}), ({1}))";
87
    public static final String ST_GEOMFROMWKB = "SDO_GEOMETRY(({0}), ({1}))";
88
    public static final String ST_GEOMFROMEWKB = "SDO_GEOMETRY(({0}), ({1}))";
89
    public static final String FORMAT_OPERATOR_NOTISNULL = "( (({0}) IS NOT NULL) )";
90
    public static final String FORMAT_OPERATOR_AND = "( ({0}) AND ({1}) )";
91
    public static final String FORMAT_OPERATOR_OR = "( ({0}) OR ({1}) )";
92
    public static final String FORMAT_OPERATOR_NE = "( ({0}) != ({1}) )";
93
    public static final String FORMAT_OPERATOR_ILIKE = "( LOWER({0}) LIKE LOWER({1}) )";
94
    public static final String FORMAT_OPERATOR_CONCAT = "{0} + {1}";
95

  
96
    public static final int BOOLEAN_STRING_DEFAULT_LENGTH = 1;
97

  
98
    private static final Geometry EMPTY_POINT = GeometryUtils.createPoint(0, 0);
99

  
100
    protected Formatter formatter = null;
101

  
102
    public OracleSQLBuilder(JDBCHelper helper) {
103
        super(helper);
104

  
105
        this.defaultSchema = "";
106
        this.allowAutomaticValues = true;
107
        this.geometrySupportType = this.helper.getGeometrySupportType();
108
        this.hasSpatialFunctions = this.helper.hasSpatialFunctions();
109
        this.constant_true = "TRUE";
110
        this.constant_false = "FALSE";
111
        this.quote_for_identifiers = "\"";
112
        this.quote_for_strings = "\'";
113

  
114
        this.type_boolean = "CHAR(1)";
115
        this.type_byte = "NUMBER(" + (DataType.BYTE_MAX_PRECISION) + ",0)";
116
        this.type_bytearray = "BLOB";
117
        this.type_geometry = "SDO_GEOMETRY";
118
        this.type_char = "CHAR(1)";
119
        this.type_date = "DATE";
120
        this.type_double = "BINARY_DOUBLE"; //float con 53 bits de mantisa = float(54)
121
        this.type_decimal_p = "NUMBER({0})";
122
        this.type_decimal_ps = "NUMBER({0},{1})";
123
//        this.type_bigdecimal = "NUMBER({0},{1})";
124
        this.type_float = "BINARY_FLOAT"; //float con 24 bits de mantisa = float(24)
125
        this.type_int = "NUMBER(" + (DataType.INT_MAX_PRECISION - 1) + ",0)";
126
        this.type_long = "NUMBER(" + (DataType.LONG_MAX_PRECISION - 1) + ",0)";
127
        this.type_string = "NCLOB";
128
        this.type_string_p = "NVARCHAR2({0})";
129
        this.type_time = "TIMESTAMP";
130
        this.type_timestamp = "TIMESTAMP";
131
        this.type_version = "VARCHAR2(30)";
132
        this.type_URI = "NVARCHAR2(2048)";
133
        this.type_URL = "NVARCHAR2(2048)";
134
        this.type_FILE = "NVARCHAR2(2048)";
135
        this.type_FOLDER = "NVARCHAR2(2048)";
136

  
137
        STMT_DELETE_FROM_table_WHERE_expresion = "DELETE FROM {0} WHERE {1}";
138
        STMT_DELETE_FROM_table = "DELETE FROM {0}";
139
        STMT_INSERT_INTO_table_columns_VALUES_values = "INSERT INTO {0} ( {1} ) VALUES ( {2} )";
140
        STMT_UPDATE_TABLE_STATISTICS_table = "VACUUM ANALYZE {0}"; // FIXME: ALTER INDEX [schema.]index REBUILD  INDEXTYPE IS MDSYS.SPATIAL_INDEX PARAMETERS (''LAYER_GTYPE={3}'';
141
//        config.remove_functionality(SQLConfig.UPDATE_TABLE_STATISTICS_table; // FIXME
142
        STMT_DROP_TABLE_table = "DROP TABLE {0}";
143
        STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_table = null;
144
        STMT_DELETE_GEOMETRY_COLUMN_FROM_TABLE_schema_table = null;
145
        STMT_UPDATE_table_SET_columnsAndValues_WHERE_expresion = "UPDATE {0} SET {1} WHERE {2}";
146
        STMT_UPDATE_table_SET_columnsAndValues = "UPDATE {0} SET {1}";
147
        STMT_GRANT_privileges_ON_table_TO_role = "GRANT {0} ON {1} TO {2}";
148

  
149
    }
150

  
151
    @Override
152
    public Formatter formatter() {
153
        if (this.formatter == null) {
154
            this.formatter = new OracleFormatter(this);
155
        }
156
        return this.formatter;
157
    }
158

  
159
    private class OracleGeometryExpressionBuilder extends DelegatedGeometryExpressionBuilder {
160

  
161
        public OracleGeometryExpressionBuilder(GeometryExpressionBuilder expressionBuilder) {
162
            super(expressionBuilder);
163
        }
164

  
165
        @Override
166
        public Formatter<Value> formatter() {
167
            return OracleSQLBuilder.this.formatter();
168
        }
169

  
170
    }
171

  
172
    private OracleGeometryExpressionBuilder oracleExpressionBuilder = null;
173

  
174
    @Override
175
    public GeometryExpressionBuilder expression() {
176
        if (this.oracleExpressionBuilder == null) {
177
            this.oracleExpressionBuilder = new OracleGeometryExpressionBuilder(super.expression());
178
        }
179
        return this.oracleExpressionBuilder;
180
    }
181

  
182
    @Override
183
    public String default_schema() {
184
        JDBCConnectionParameters params = this.helper.getConnectionParameters();
185
        if (params != null) {
186
            if (StringUtils.isBlank(params.getSchema())) {
187
                if ((StringUtils.isNotBlank(params.getUser()))) {
188
                    return params.getUser();
189
                }
190
            } else {
191
                return params.getSchema();
192
            }
193
        }
194
        return this.defaultSchema;
195
    }
196

  
197
    public class OracleUpdateTableStatisticsBuilderBase extends UpdateTableStatisticsBuilderBase {
198

  
199
        @Override
200
        public List<String> toStrings() {
201
            List<String> sqls = new ArrayList<>();
202

  
203
            String name = as_identifier(this.table.getName());
204
            if (table.has_schema()) {
205
                name = as_identifier(this.table.getSchema()) + "." + name;
206
            }
207
            String sql = MessageFormat.format(
208
                    "ANALYZE TABLE {0} COMPUTE STATISTICS",
209
                    name
210
            );
211
            if (!StringUtils.isEmpty(sql)) {
212
                sqls.add(sql);
213
            }
214

  
215
            return sqls;
216
        }
217
    }
218

  
219
    public String getSerialSequenceName(String tableName, String columnName) {
220
        return ("GVSEQ_" + tableName + "_" + columnName).toUpperCase();
221
    }
222

  
223
    public String getSerialTriggerName(String tableName, String columnName) {
224
        return ("GVSER_" + tableName + "_" + columnName).toUpperCase();
225
    }
226

  
227
    protected class OracleCreateTableBuilder extends CreateTableBuilderBase {
228

  
229
        @Override
230
        public List<String> toStrings(Formatter formatter) {
231

  
232
            List<String> sqls = new ArrayList<>();
233
            StringBuilder builder = new StringBuilder();
234

  
235
            builder.append("CREATE TABLE ");
236
            builder.append(getFullTableName(this.table()));
237
            builder.append(" (");
238
            boolean first = true;
239

  
240
            ArrayList<String> pks = new ArrayList<>();
241
            boolean automaticPrimaryKey = false;
242

  
243
            for (ColumnDescriptor column : columns) {
244
                if (first) {
245
                    first = false;
246
                } else {
247
                    builder.append(", ");
248
                }
249
                if (column.isGeometry()) {
250
                    builder.append(as_identifier(column.getName())); //.toUpperCase()));
251
                    builder.append(" ");
252
                    builder.append(" SDO_GEOMETRY");
253
                    if (!column.allowNulls()) {
254
                        builder.append(" NOT NULL");
255
                    }
256
                } else {
257
                    builder.append(as_identifier(column.getName()));
258
                    builder.append(" ");
259
                    builder.append(sqltype(
260
                            column.getType(),
261
                            column.getSize(),
262
                            column.getPrecision(),
263
                            column.getScale(),
264
                            column.getGeometryType(),
265
                            column.getGeometrySubtype()));
266

  
267
//                    if (column.getDefaultValue() == null) {
268
//                        if (column.allowNulls()) {
269
//                            builder.append(" DEFAULT NULL");
270
//                        }
271
//                    } else {
272
//                        builder.append(" DEFAULT '");
273
//                        builder.append(column.getDefaultValue().toString());
274
//                        builder.append("'");
275
//                    }
276
//                    if (column.allowNulls()) {
277
//                        builder.append(" NULL");
278
//                    } else {
279
//                        builder.append(" NOT NULL");
280
//                    }
281
                }
282
                if (column.isPrimaryKey()) {
283
                    if (column.isAutomatic()) {
284
                        // if the pk is automatic, ignore any other PK
285
                        automaticPrimaryKey = true;
286
                        pks.clear();
287
                        pks.add(column.getName());
288
                    } else if (!automaticPrimaryKey) {
289
                        pks.add(column.getName());
290
                    }
291
                } else {
292
                    if (column.isAutomatic()) {
293
//                        builder.append(" AUTO_INCREMENT");
294
                        builder.append(" GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1)");
295
                    }
296
                    if (column.getDefaultValue() == null
297
                            || ExpressionUtils.isDynamicText(Objects.toString(column.getDefaultValue(), null))) {
298
                        if (column.allowNulls()) {
299
                            builder.append(" DEFAULT NULL");
300
                        }
301
                    } else {
302
                        switch (column.getType()) {
303
                            case DataTypes.TIMESTAMP:
304
                                builder.append(" DEFAULT ( TIMESTAMP '");
305
                                Timestamp dtimestamp = (Timestamp) DataTypeUtils.toTimestamp(column.getDefaultValue());
306
                                builder.append(MessageFormat.format("{0,date,yyyy-MM-dd HH:mm:ss.S}", dtimestamp));
307
                                builder.append("' )");
308
                                break;
309
                            case DataTypes.TIME:
310
                                builder.append(" DEFAULT ( TIME '");
311
                                Time dtime = (Time) DataTypeUtils.toTime(column.getDefaultValue());
312
                                builder.append(MessageFormat.format("{0,date,HH:mm:ss}", dtime));
313
                                builder.append("' )");
314
                                break;
315
                            case DataTypes.DATE:
316
                                builder.append(" DEFAULT ( DATE '");
317
                                java.sql.Date ddate = (java.sql.Date) DataTypeUtils.toDate(column.getDefaultValue());
318
                                builder.append(MessageFormat.format("{0,date,yyyy-MM-dd}", ddate));
319
                                builder.append("' )");
320
                                break;
321
                            default:
322
                                builder.append(" DEFAULT '");
323
                                builder.append(Objects.toString(column.getDefaultValue(), ""));
324
                                builder.append("'");
325
                        }
326
                    }
327
                }
328
            }
329
            builder.append(" )");
330
            sqls.add(builder.toString());
331

  
332
            if (pks.size() > 0) {
333
                builder = new StringBuilder("ALTER TABLE ");
334
                builder.append(getFullTableName(this.table()));
335
                builder.append(" ADD PRIMARY KEY (");
336
                for (int i = 0; i < pks.size(); i++) {
337
                    if (i != 0) {
338
                        builder.append(", ");
339
                    }
340
                    builder.append(as_identifier(pks.get(i)));
341
                }
342
                builder.append(")");
343
                sqls.add(builder.toString());
344
            }
345

  
346
            for (ColumnDescriptor column : columns) {
347
                if (column.isAutomatic()) {
348
                    String sequenceName = getSerialSequenceName(this.table.getName(), column.getName());
349
                    String sql = MessageFormat.format(
350
                            ADD_SERIAL_COLUMN_SEQUENCE_QUERY,
351
                            sequenceName
352
                    );
353
                    sqls.add(sql);
354
                    String autoTriggerName = getSerialTriggerName(this.table.getName(), column.getName());
355
                    sql = MessageFormat.format(
356
                            ADD_SERIAL_COLUMN_TRIGGER_QUERY,
357
                            autoTriggerName,
358
                            getFullTableName(this.table()),
359
                            column.getName(),
360
                            sequenceName
361
                    );
362
                    sqls.add(sql);
363
                }
364
            }
365

  
366
            for (ColumnDescriptor column : columns) {
367
                if (column.isGeometry()) {
368
                    /**
369
                     * Inserting the geomtype and column on
370
                     * OGIS_GEOMETRY_COLUMNS.
371
                     *
372
                     * It is useful to retrieve the geometry type when the
373
                     * spatial index can't be defined (for instance users
374
                     * creating tables on a different schema).
375
                     *
376
                     * Note: We don't insert the SRID because it is unusable as
377
                     * defined on OGIS_GEOMETRY_COLUMNS, as it must reference an
378
                     * existing SRID on OGIS_SPATIAL_REFERENCE_SYSTEM.
379
                     * OGIS_SPATIAL_REFERENCE_SYSTEM is empty and it has a
380
                     * trigger that duplicates on SDO_COORD_REF_SYS any SRID
381
                     * inserted on OGIS_SPATIAL_REFERENCE_SYSTEM.
382
                     * SDO_COORD_REF_SYS is not empty and we don't want to
383
                     * duplicate the SRID definitions!!
384
                     */
385
                    int gvsigType = column.getGeometryType();
386
                    int gvsigSubtype = column.getGeometrySubtype(); //.getGeometryType();
387
                    String sql = MessageFormat.format( // delete before inserting to avoid creating duplicates
388
                            DELETE_FROM_OGIS_GEOMETRY_COLUMNS_QUERY,
389
                            this.table().getSchema(),
390
                            this.table().getName().toUpperCase(),
391
                            column.getName() //.toUpperCase());
392
                    );
393
                    sqls.add(sql);
394
                    sql = MessageFormat.format(
395
                            INSERT_OGIS_GEOMETRY_COLUMNS_QUERY,
396
                            this.table().getSchema(),
397
                            this.table().getName().toUpperCase(),
398
                            column.getName(), //.toUpperCase(),
399
                            Integer.toString(GeometryTypeUtils.toSFSGeometryTypeCode(gvsigType, gvsigSubtype))
400
                    );
401
                    sqls.add(sql);
402
                    Envelope tablebbox = column.getTableBBox();
403
                    if (tablebbox != null) {
404
                        sql = SpatialIndexUtils.getSQLDeleteUserMetadata(
405
                                this.table().getSchema(),
406
                                this.table().getName(),
407
                                column.getName()
408
                        );
409
                        sqls.add(sql);
410
                        sql = SpatialIndexUtils.getSQLInsertUserMetadata(
411
                                this.table().getName(),
412
                                tablebbox,
413
                                column.getName(),
414
                                (int) column.getGeometrySRSId()
415
                        );
416
                        sqls.add(sql);
417
                        sql = SpatialIndexUtils.getSQLCreateSpatialIndex(
418
                                this.table().getName(),
419
                                column.getName(),
420
                                column.getGeometryType()
421
                        );
422
                        sqls.add(sql);
423
                    }
424
                }
425
            }
426
            return sqls;
427
        }
428
    }
429

  
430
    private String getFullTableName(TableNameBuilder table) {
431
        if (table.has_database()) {
432
            if (table.has_schema()) {
433
                return as_identifier(table.getDatabase()) + "."
434
                        + as_identifier(table.getSchema()) + "."
435
                        + as_identifier(table.getName().toUpperCase());
436
            }
437
        } else {
438
            if (table.has_schema()) {
439
                return as_identifier(table.getSchema()) + "."
440
                        + as_identifier(table.getName().toUpperCase());
441
            }
442
        }
443
        return as_identifier(table.getName().toUpperCase());
444
    }
445

  
446
    public class OracleSelectBuilder extends SelectBuilderBase {
447

  
448
        @Override
449
        public String toString(Formatter<ExpressionBuilder.Value> formatter) {
450
            StringBuilder builder = new StringBuilder();
451
            if (!isValid(builder)) {
452
                throw new IllegalStateException(builder.toString());
453
            }
454
            boolean involveWithLimitOrOffset = ((this.has_offset() || this.has_limit())
455
                    && (this.has_aggregate_functions() || this.has_group_by() || this.has_order_by()));
456

  
457
            if (involveWithLimitOrOffset) {
458
                /**
459
                 * Using ROWNUM for limit & offset, compatible with any Oracle
460
                 * version This requires wrapping the original query as shown in
461
                 * the example: select * from ( select a.*, ROWNUM rnum from (
462
                 * <select statement with order by clause>
463
                 * ) a where ROWNUM <= MAX_ROW
464
                 *     ) where rnum >= MIN_ROW because ROWNUM is considered before
465
                 * applying order by and group by
466
                 */
467
                builder.append("SELECT * FROM ( ");
468
                if (this.has_offset()) {
469
                    builder.append("SELECT a.*, ROWNUM rnum FROM ( ");
470
                }
471
            }
472

  
473
            builder.append("SELECT ");
474
            if (this.distinct) {
475
                builder.append("DISTINCT ");
476
            }
477
            boolean first = true;
478
            for (SelectColumnBuilder column : columns) {
479
                if (first) {
480
                    first = false;
481
                } else {
482
                    builder.append(", ");
483
                }
484
                builder.append(column.toString(formatter));
485
            }
486

  
487
            if (this.has_from()) {
488
                builder.append(" FROM ");
489
                builder.append(this.from.toString(formatter));
490
            }
491
            if (this.has_where()) {
492
                builder.append(" WHERE ");
493
                builder.append(this.where.toString(formatter));
494
            }
495

  
496
            if (!involveWithLimitOrOffset) {
497
                if (this.has_limit() || this.has_offset()) {
498
                    if (this.has_where()) {
499
                        builder.append(" AND ");
500
                    } else {
501
                        builder.append(" WHERE ");
502
                    }
503
                }
504

  
505
                if (this.has_limit()) {
506
                    builder.append(" ROWNUM <= ");
507
                    if (this.has_offset()) {
508
                        builder.append(this.offset + this.limit);
509
                    } else {
510
                        builder.append(this.limit);
511
                    }
512
                }
513
                if (this.has_offset()) {
514
                    builder.append(" AND rnum > ");
515
                    builder.append(this.offset);
516
                }
517

  
518
                if (this.has_group_by()) {
519
                    builder.append(" GROUP BY ");
520
                    builder.append(this.groupColumn.get(0).toString(formatter));
521
                    for (int i = 1; i < groupColumn.size(); i++) {
522
                        builder.append(", ");
523
                        builder.append(this.groupColumn.get(i).toString(formatter));
524
                    }
525
                }
526

  
527
                if (this.has_order_by()) {
528
                    builder.append(" ORDER BY ");
529
                    first = true;
530
                    for (OrderByBuilder item : this.order_by) {
531
                        if (first) {
532
                            first = false;
533
                        } else {
534
                            builder.append(", ");
535
                        }
536
                        builder.append(item.toString(formatter));
537
                    }
538
                }
539

  
540
            }
541

  
542
            if (involveWithLimitOrOffset) {
543
                if (this.has_order_by()) {
544
                    builder.append(" ORDER BY ");
545
                    first = true;
546
                    for (OrderByBuilder item : this.order_by) {
547
                        if (first) {
548
                            first = false;
549
                        } else {
550
                            builder.append(", ");
551
                        }
552
                        builder.append(item.toString(formatter));
553
                    }
554
                }
555
                builder.append(") a");
556
                if (this.has_limit()) {
557
                    builder.append(" WHERE ROWNUM <= ");
558
                    if (this.has_offset()) {
559
                        builder.append(this.offset + this.limit);
560
                    } else {
561
                        builder.append(this.limit);
562
                    }
563
                }
564
                if (this.has_offset()) {
565
                    builder.append(" )");
566
                    builder.append(" WHERE rnum > ");
567
                    builder.append(this.offset);
568
                }
569

  
570
            }
571
            return builder.toString();
572
        }
573

  
574
    }
575

  
576
    @Override
577
    public TableNameBuilder createTableNameBuilder() {
578
        return new OracleTableNameBuilder();
579
    }
580

  
581
    @Override
582
    protected CreateTableBuilder createCreateTableBuilder() {
583
        return new OracleCreateTableBuilder();
584
    }
585

  
586
    @Override
587
    public SelectBuilder createSelectBuilder() {
588
        return new OracleSelectBuilder();
589
    }
590

  
591
    @Override
592
    protected FromBuilder createFromBuilder() {
593
        return new OracleFromBuilder();
594
    }
595

  
596
    @Override
597
    protected UpdateTableStatisticsBuilder createUpdateTableStatisticsBuilder() {
598
        return new OracleUpdateTableStatisticsBuilderBase();
599
    }
600

  
601
    protected class OracleTableNameBuilder extends TableNameBuilderBase {
602

  
603
        @Override
604
        public boolean has_database() {
605
            return false;
606
        }
607

  
608
        @Override
609
        public String toString() {
610
            return this.toString(formatter());
611
        }
612

  
613
        @Override
614
        public String toString(Formatter<ExpressionBuilder.Value> formatter) {
615
            if (formatter != null && formatter.canApply(this)) {
616
                return formatter.format(this);
617
            }
618
            if (this.has_schema()) {
619
                return as_identifier(this.schemaName) + "."
620
                        + as_identifier(this.tableName);
621
            }
622

  
623
            JDBCConnectionParameters params = helper.getConnectionParameters();
624
            if (params != null) {
625
                if ((StringUtils.isNotBlank(params.getUser()))) {
626
                    return as_identifier(params.getUser()) + "."
627
                            + as_identifier(this.tableName);
628
                }
629
            }
630
            return as_identifier(this.tableName);
631
        }
632
    }
633

  
634
    public class OracleFromBuilder extends FromBuilderBase {
635

  
636
        @Override
637
        public String toString(Formatter<ExpressionBuilder.Value> formatter) {
638
            if (formatter != null && formatter.canApply(this)) {
639
                return formatter.format(this);
640
            }
641
            if (!StringUtils.isEmpty(passthrough)) {
642
                return passthrough;
643
            }
644
            if (!StringUtils.isEmpty(subquery)) {
645
                return "( " + this.subquery + ") " + quote_for_identifiers() + "_subquery_alias_" + quote_for_identifiers() + " ";
646
            }
647
            if (this.joins == null || this.joins.isEmpty()) {
648
                return this.tableName.toString(formatter);
649
            }
650
            StringBuilder builder = new StringBuilder();
651
            builder.append(this.tableName.toString(formatter));
652
            for (JoinBuilder join : this.joins) {
653
                builder.append(" ");
654
                builder.append(join.toString(formatter));
655
            }
656
            return builder.toString();
657
        }
658
    }
659

  
660
    public class DisposableBlobs implements Disposable {
661

  
662
        private final ArrayList<BLOB> blobList = new ArrayList<>();
663

  
664
        public void add(BLOB blob) {
665
            blobList.add(blob);
666
        }
667

  
668
        @Override
669
        public void dispose() {
670
            blobList.forEach((blob) -> {
671
                try {
672
                    blob.freeTemporary();
673
                } catch (SQLException ex) {
674
                    LOGGER.warn("Can't dispose blob " + blob.toString(), ex);
675
                }
676
            });
677
        }
678

  
679
    }
680

  
681
    protected void setBlob(PreparedStatement st, int columnIndex,
682
            byte[] bytes, DisposableBlobs blobList) throws SQLException, IOException {
683
        Connection conn = st.getConnection();
684
        if (conn instanceof DelegatingConnection) {
685
            conn = ((DelegatingConnection) conn).getInnermostDelegate();
686
        }
687
        BLOB blob = BLOB.createTemporary(conn, false, BLOB.DURATION_SESSION);
688
        blobList.add(blob);
689
        InputStream inputStream;
690
        try (OutputStream outputStream = blob.setBinaryStream(0L)) {
691
            inputStream = new ByteArrayInputStream(bytes);
692
            byte[] buffer = new byte[blob.getBufferSize()];
693
            int byteread;
694
            while ((byteread = inputStream.read(buffer)) != -1) {
695
                outputStream.write(buffer, 0, byteread);
696
            }
697
        }
698
        inputStream.close();
699
        st.setBlob(columnIndex, blob);
700
    }
701

  
702
    @Override
703
    public Disposable setStatementParameters(
704
            PreparedStatement st,
705
            List values,
706
            List<Integer> types, //Can be null
707
            GeometrySupportType geometrySupportType) throws SQLException {
708

  
709
        DisposableBlobs blobList = new DisposableBlobs();
710
        if (values == null) {
711
            return blobList;
712
        }
713
        try {
714
            byte[] bytes;
715
            int columnIndex = 1;
716
            for (Object value : values) {
717
                if (value instanceof Geometry) {
718
                    switch (geometrySupportType) {
719
                        case WKT:
720
                            value = ((Geometry) value).convertToWKT();
721
                            st.setObject(columnIndex, value);
722
                            break;
723
                        case NATIVE:
724
                        case WKB:
725
                            bytes = ((Geometry) value).convertToWKB();
726
                            setBlob(st, columnIndex, bytes, blobList);
727
                            break;
728
                        case EWKB:
729
                            bytes = ((Geometry) value).convertToEWKB();
730
                            setBlob(st, columnIndex, bytes, blobList);
731
                            break;
732
                    }
733
                } else {
734
                    if (types == null) {
735
                        st.setObject(columnIndex, value);
736
                    } else {
737
                        this.setStatementValue(st, columnIndex, types.get(columnIndex - 1), value);
738
                    }
739
                }
740
                columnIndex++;
741
            }
742
        } catch (Exception ex) {
743
            throw new SQLException("Can't set values for the prepared statement.", ex);
744
        }
745
        return blobList;
746
    }
747

  
748
    @Override
749
    public List<Object> getParameters(FeatureProvider feature) {
750
        return getParameters(feature, null);
751
    }
752

  
753
    public List<Object> getParameters(FeatureProvider feature, List<Integer> types) {
754
        try {
755
            FeatureType type = feature.getType();
756
            FeatureType providerType = this.getHelper().getProviderFeatureType();
757
            List<Object> values = new ArrayList<>();
758
            Object value;
759
            DataTypesManager dataTypesManager = ToolsLocator.getDataTypesManager();
760
            for (ExpressionBuilder.Parameter parameter : this.parameters()) {
761
                if (parameter.is_constant()) {
762
                    value = parameter.value();
763
                    values.add(value);
764
                    if (types != null) {
765
                        if (value == null) {
766
                            if (values.get(values.size() - 2) == EMPTY_POINT) {
767
                                types.add(DataTypes.INTEGER);
768
                            } else {
769
                                types.add(DataTypes.OBJECT);
770
                            }
771
                        } else {
772
                            DataType dataType = dataTypesManager.getDataType(value.getClass());
773
                            types.add(dataType.getType());
774
                        }
775
                    }
776
                } else {
777
                    String name = parameter.name();
778
                    value = feature.get(name);
779
                    FeatureAttributeDescriptor attrDesc = type.getAttributeDescriptor(name);
780
                    Coercion convert = null;
781
                    if (providerType != null) {
782
                        FeatureAttributeDescriptor attrDescProvider = providerType.getAttributeDescriptor(name);
783
                        if (attrDescProvider != null && attrDescProvider.getType() != attrDesc.getType()) {
784
                            convert = attrDescProvider.getDataType().getCoercion();
785
                        }
786
                    }
787
                    switch (attrDesc.getType()) {
788
                        case org.gvsig.fmap.dal.DataTypes.GEOMETRY:
789
                            Geometry geom = this.forceGeometryType(
790
                                    attrDesc.getGeomType(),
791
                                    (Geometry) value
792
                            );
793
                            if (BooleanUtils.isTrue((Boolean) parameter.getProperty(ORACLE_GEOMETRY_PARAMETER))) {
794
                                //Es muy guarro pero es para evitar un error de NullPointerException en Oracle
795
                                if (geom == null) {
796
                                    //NVL2((NULL),SDO_GEOMETRY((EMPTY_POINT), (?)),NULL)
797
                                    values.add(null);
798
                                    values.add(EMPTY_POINT);
799
                                } else {
800
                                    //NVL2((1),SDO_GEOMETRY((WKB), (?)),NULL)
801
                                    values.add(1);
802
                                    values.add(geom);
803
                                }
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff