Revision 9736

View differences:

trunk/extensions/extJDBC/src/com/iver/cit/gvsig/fmap/drivers/jdbc/mysql/MySqlWriter.java
1
/*
2
 * Created on 15-ene-2007
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
*
46
* $Id$
47
* $Log$
48
* Revision 1.1  2007-01-15 20:15:35  azabala
49
* *** empty log message ***
50
*
51
*
52
*/
53
package com.iver.cit.gvsig.fmap.drivers.jdbc.mysql;
54
import java.io.IOException;
55
import java.sql.Connection;
56
import java.sql.ResultSet;
57
import java.sql.SQLException;
58
import java.sql.Statement;
59
import java.sql.Types;
60

  
61
import com.iver.cit.gvsig.fmap.DriverException;
62
import com.iver.cit.gvsig.fmap.core.FShape;
63
import com.iver.cit.gvsig.fmap.core.IFeature;
64
import com.iver.cit.gvsig.fmap.drivers.DBLayerDefinition;
65
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
66
import com.iver.cit.gvsig.fmap.drivers.ITableDefinition;
67
import com.iver.cit.gvsig.fmap.edition.EditionException;
68
import com.iver.cit.gvsig.fmap.edition.IFieldManager;
69
import com.iver.cit.gvsig.fmap.edition.IRowEdited;
70
import com.iver.cit.gvsig.fmap.edition.ISpatialWriter;
71
import com.iver.cit.gvsig.fmap.edition.fieldmanagers.JdbcFieldManager;
72
import com.iver.cit.gvsig.fmap.edition.writers.AbstractWriter;
73

  
74
public class MySqlWriter extends AbstractWriter 
75
		implements ISpatialWriter, IFieldManager {
76

  
77
	private int numRows;
78

  
79
	private DBLayerDefinition lyrDef;
80

  
81
	private Connection conex;
82

  
83
	private Statement st;
84

  
85
	/**
86
	 * flag to mark if writer must create the table or it must
87
	 * add records to an existing one
88
	 * 
89
	 */
90
	private boolean bCreateTable;
91

  
92
	private boolean bWriteAll;
93
	
94
	private MySql mySql = new MySql();
95
	
96
	/*
97
	 * TODO
98
	 * Ver si en MySQL los tipos de datos (numeric, etc.)
99
	 * se nombran as? tambi?n
100
	 * */
101
	private JdbcFieldManager fieldManager;
102
	
103
	/**
104
	 * 
105
	 * Call setFile before using this
106
	 * function
107
	 * 
108
	 * @param lyrDef
109
	 * @throws IOException
110
	 * @throws DriverException
111
	 */
112
	public void initialize(ITableDefinition lyrD) throws EditionException {
113
		super.initialize(lyrD);
114
		this.lyrDef = (DBLayerDefinition) lyrD;
115
		conex = lyrDef.getConnection();
116

  
117
		try {
118
			st = conex.createStatement();
119
			
120
			/*
121
			 * y en caso de que sea false usar "CREATE TABLE IF NOT EXISTS" en el 
122
			 * else
123
			 * (AZO)
124
			 * 
125
			 * */
126
			if (bCreateTable) {
127
				try {
128
					st.execute("DROP TABLE " + lyrDef.getTableName() + ";");
129
				} catch (SQLException e1) {
130
				}
131
				//In MySQL you can add geometry column in CREATE TABLE statement
132
				String sqlCreate = mySql.getSqlCreateSpatialTable(lyrDef,
133
												lyrDef.getFieldsDesc(), 
134
												true);
135
				st.execute(sqlCreate);
136
				conex.commit();
137
			}//if
138
			conex.setAutoCommit(false);
139
			fieldManager = new JdbcFieldManager(conex, lyrDef.getTableName());
140

  
141
		} catch (SQLException e) {
142
			e.printStackTrace();
143
			throw new EditionException(e);
144
		}
145

  
146
	}
147

  
148
	
149
	public void preProcess() throws EditionException {
150
		numRows = 0;
151
		
152
        // ATENTION: We will transform (in PostGIS class; doubleQuote())
153
        // to UTF-8 strings. Then, we tell the PostgreSQL server
154
        // that we will use UTF-8, and it can translate
155
        // to its charset
156
        // Note: we have to translate to UTF-8 because
157
        // the server cannot manage UTF-16
158
		try {
159
			conex.setAutoCommit(false);
160
			conex.rollback();			
161
			alterTable();
162
		} catch (SQLException e) {
163
			// TODO Auto-generated catch block
164
			e.printStackTrace();
165
		}
166
	}
167

  
168
	public void process(IRowEdited row) throws EditionException {
169

  
170
		String sqlInsert;
171
		try {
172
			switch (row.getStatus()) {
173
			case IRowEdited.STATUS_ADDED:
174
				IFeature feat = (IFeature) row.getLinkedRow();
175
				sqlInsert = mySql.getSqlInsertFeature(lyrDef, feat);
176
				st.execute(sqlInsert);
177
				break;
178
				
179
			case IRowEdited.STATUS_MODIFIED:
180
				IFeature featM = (IFeature) row.getLinkedRow();
181
				if (bWriteAll) {
182
					sqlInsert = mySql.getSqlInsertFeature(lyrDef, featM);
183
					System.out.println("sql = " + sqlInsert);
184
					st.execute(sqlInsert);
185
				} else {
186
					String sqlModify = mySql.getSqlModifyFeature(lyrDef, featM);
187
					st.execute(sqlModify);
188
				}
189
				break;
190
				
191
			case IRowEdited.STATUS_ORIGINAL:
192
				IFeature featO = (IFeature) row.getLinkedRow();
193
				if (bWriteAll) {
194
					sqlInsert = mySql.getSqlInsertFeature(lyrDef, featO);
195
					st.execute(sqlInsert);
196
				}
197
				break;
198
				
199
			case IRowEdited.STATUS_DELETED:
200
				String sqlDelete = mySql.getSqlDeleteFeature(lyrDef, row);
201
				System.out.println("sql = " + sqlDelete);
202
				st.execute(sqlDelete);
203

  
204
				break;
205
			}
206

  
207
			numRows++;
208
		} catch (SQLException e) {
209
			e.printStackTrace();
210
			throw new EditionException(e);
211
		}
212

  
213
	}
214

  
215
	public void postProcess() throws EditionException {
216
		try {
217
			conex.setAutoCommit(true);
218
		} catch (SQLException e) {
219
			e.printStackTrace();
220
			throw new EditionException(e);
221
		}
222
	}
223

  
224
	public String getName() {
225
		return "MySQL Writer";
226
	}
227

  
228
	public boolean canWriteGeometry(int gvSIGgeometryType) {
229
		switch (gvSIGgeometryType) {
230
		case FShape.POINT:
231
			return true;
232
		case FShape.LINE:
233
			return true;
234
		case FShape.POLYGON:
235
			return true;
236
		case FShape.ARC:
237
			return false;
238
		case FShape.ELLIPSE:
239
			return false;
240
		case FShape.MULTIPOINT:
241
			return true;
242
		case FShape.TEXT:
243
			return false;
244
		}
245
		return false;
246
	}
247

  
248
	public boolean canWriteAttribute(int sqlType) {
249
		switch (sqlType) {
250
		case Types.DOUBLE:
251
		case Types.FLOAT:
252
		case Types.INTEGER:
253
		case Types.BIGINT:
254
			return true;
255
		case Types.DATE:
256
			return true;
257
		case Types.BIT:
258
		case Types.BOOLEAN:
259
			return true;
260
		case Types.VARCHAR:
261
		case Types.CHAR:
262
		case Types.LONGVARCHAR:
263
			return true; 
264

  
265
		}
266

  
267
		return false;
268
	}
269

  
270
	/**
271
	 * @return Returns the bCreateTable.
272
	 */
273
	public boolean isCreateTable() {
274
		return bCreateTable;
275
	}
276

  
277
	/**
278
	 * @param createTable
279
	 *            The bCreateTable to set.
280
	 */
281
	public void setCreateTable(boolean createTable) {
282
		bCreateTable = createTable;
283
	}
284

  
285
	/**
286
	 * @return Returns the bWriteAll.
287
	 */
288
	public boolean isWriteAll() {
289
		return bWriteAll;
290
	}
291

  
292
	/**
293
	 * @param writeAll
294
	 *            The bWriteAll to set.
295
	 */
296
	public void setWriteAll(boolean writeAll) {
297
		bWriteAll = writeAll;
298
	}
299

  
300

  
301
//	public void setFlatness(double flatness) {
302
//		this.flatness = flatness;
303
//	}
304

  
305
	public FieldDescription[] getOriginalFields() {
306
		return lyrDef.getFieldsDesc();
307
	}
308

  
309
	public void addField(FieldDescription fieldDesc) {
310
		fieldManager.addField(fieldDesc);
311
		
312
	}
313

  
314
	public FieldDescription removeField(String fieldName) {
315
		return fieldManager.removeField(fieldName);
316
		
317
	}
318

  
319
	public void renameField(String antName, String newName) {
320
		fieldManager.renameField(antName, newName);
321
		
322
	}
323

  
324
	public boolean alterTable() throws EditionException {
325
		return fieldManager.alterTable();
326
	}
327

  
328
	public FieldDescription[] getFields() {
329
		return fieldManager.getFields();
330
	}
331

  
332
	public boolean canAlterTable() {
333
		return true;
334
	}
335

  
336
	public boolean canSaveEdits() {
337
		// TODO: Revisar los permisos de la tabla en cuesti?n.
338
		try {
339
			return !conex.isReadOnly();
340
		} catch (SQLException e) {
341
			// TODO Auto-generated catch block
342
			e.printStackTrace();
343
			return false;
344
		}
345
	}
346

  
347
}
0 348

  
trunk/extensions/extJDBC/src/com/iver/cit/gvsig/fmap/drivers/jdbc/mysql/MySql.java
1
/*
2
 * Created on 15-ene-2007
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
/* CVS MESSAGES:
45
*
46
* $Id$
47
* $Log$
48
* Revision 1.1  2007-01-15 20:15:35  azabala
49
* *** empty log message ***
50
*
51
*
52
*/
53
package com.iver.cit.gvsig.fmap.drivers.jdbc.mysql;
54

  
55
import java.io.ByteArrayOutputStream;
56
import java.io.PrintStream;
57
import java.io.UnsupportedEncodingException;
58
import java.sql.Types;
59

  
60
import com.hardcode.gdbms.engine.values.NullValue;
61
import com.hardcode.gdbms.engine.values.Value;
62
import com.hardcode.gdbms.engine.values.ValueWriter;
63
import com.iver.cit.gvsig.fmap.core.FShape;
64
import com.iver.cit.gvsig.fmap.core.IFeature;
65
import com.iver.cit.gvsig.fmap.core.IRow;
66
import com.iver.cit.gvsig.fmap.drivers.DBLayerDefinition;
67
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
68
import com.iver.cit.gvsig.fmap.drivers.XTypes;
69
import com.vividsolutions.jts.io.WKTWriter;
70

  
71
/**
72
 * It builds sql sintax for Create, Delete, Update operations in MySQL
73
 * 
74
 * */
75
public class MySql {
76
	/**
77
	 * Converts a JTS geometry to WKT
78
	 * */
79
	private static WKTWriter geometryWriter = new WKTWriter();
80
	
81
	/**
82
	 * Mover esto a IverUtiles
83
	 * 
84
	 * @param val
85
	 * @return
86
	 */
87
	public boolean isNumeric(Value val) {
88

  
89
		switch (val.getSQLType()) {
90
		case Types.DOUBLE:
91
		case Types.FLOAT:
92
		case Types.INTEGER:
93
		case Types.SMALLINT:
94
		case Types.BIGINT:
95
		case Types.NUMERIC:
96
		case Types.REAL:
97
		case Types.TINYINT:
98
			return true;
99
		}
100

  
101
		return false;
102
	}
103

  
104
	/**
105
	 * It builds MySQL "CREATE TABLE" statement.
106
	 * 
107
	 * In PostGIS, its usual first create alphanumeric table, and 
108
	 * after that add a geometry column for geometries.
109
	 * 
110
	 * 
111
	 * @param dbLayerDef data of the new table (name, etc)
112
	 * @param fieldsDescr schema of the new table
113
	 * @param bCreateGID @DEPRECATED 
114
	 * @return SQL statement with MySQL sintax
115
	 */
116
	public String getSqlCreateSpatialTable(DBLayerDefinition dbLayerDef,
117
			FieldDescription[] fieldsDescr, boolean bCreateGID) {
118

  
119
		String result;
120
		result = "CREATE TABLE " + dbLayerDef.getTableName()
121
					+ " (gid serial PRIMARY KEY ";
122
		int j=0;
123
		for (int i = 0; i < dbLayerDef.getFieldNames().length; i++) {
124
			int fieldType = fieldsDescr[i].getFieldType();
125
			//TODO ver si XTypes me los devuelve con la sintaxis MySQL
126
			String strType = XTypes.fieldTypeToString(fieldType);
127
			
128
			//We dont allow GID field. It is a reserved field name
129
			if (fieldsDescr[i].getFieldName().equalsIgnoreCase("gid"))
130
				continue;
131
			result +=  ", " + dbLayerDef.getFieldNames()[i] + " "	+ strType;
132
			j++;
133
		}
134
		
135
		String geometryFieldName = dbLayerDef.getFieldGeometry();
136
		
137
		//TODO Ver si MySQL se traga los tipos geometricos que devuelve XTypes
138
		String geometryFieldType = "GEOMETRY";
139
		switch (dbLayerDef.getShapeType()) {
140
		case FShape.POINT:
141
			geometryFieldType = XTypes.fieldTypeToString(XTypes.POINT2D);
142
			break;
143
		case FShape.LINE:
144
			geometryFieldType = XTypes.fieldTypeToString(XTypes.LINE2D);
145
			break;
146
		case FShape.POLYGON:
147
			geometryFieldType = XTypes.fieldTypeToString(XTypes.POLYGON2D);
148
			break;
149
		case FShape.MULTI:
150
			geometryFieldType = XTypes.fieldTypeToString(XTypes.MULTI2D);
151
			break;
152
		}
153
		result += "," + geometryFieldName + " " + 
154
			geometryFieldType + " NOT NULL, SPATIAL INDEX(" + geometryFieldName + "))";
155
		return result;
156
	}
157

  
158
	protected String format(Object value) {
159
		String retString = null;
160
		if (value != null) {
161
			if (value instanceof NullValue)
162
				retString = "null";
163
			else{
164
//				retString = "'" + doubleQuote(value) + "'";
165
			    retString += ("'" + value.toString().trim() + "',");	
166
			}
167
		} else {
168
			retString = "null";
169
		}
170
		return retString;
171
	}
172
	
173
	
174
	
175
//	private String doubleQuote(Object obj) {
176
//		String aux = obj.toString().replaceAll("'", "''");
177
//		StringBuffer strBuf = new StringBuffer(aux);
178
//		ByteArrayOutputStream out = new ByteArrayOutputStream(strBuf.length());
179
//		PrintStream printStream = new PrintStream(out);
180
//		printStream.print(aux);
181
//		String aux2 = "ERROR";
182
//		try {
183
//			aux2 = out.toString(toEncode);
184
//			System.out.println(aux + " " + aux2);
185
//		} catch (UnsupportedEncodingException e) {
186
//			// TODO Auto-generated catch block
187
//			e.printStackTrace();
188
//		}
189
//
190
//		return aux2;
191
//	}
192

  
193
	
194
	
195
	/**
196
	 * Based in code from JUMP (VividSolutions) and Geotools Things to be aware:
197
	 * We always will use Spatial Tables with Unique ID. IFeature has the same
198
	 * field order than dbLayerDef.getFieldNames()
199
	 * 
200
	 * @param dbLayerDef
201
	 * @param feat
202
	 * @return
203
	 */
204
	public String getSqlInsertFeature(DBLayerDefinition dbLayerDef,
205
			IFeature feat) {
206
		StringBuffer sqlBuf = new StringBuffer("INSERT INTO "
207
				+ dbLayerDef.getTableName() + " (");
208
		String sql = null;
209
		int numAlphanumericFields = dbLayerDef.getFieldNames().length;
210

  
211
		for (int i = 0; i < numAlphanumericFields; i++) {
212
			String name = dbLayerDef.getFieldsDesc()[i].getFieldName();
213
			if (name.equals(dbLayerDef.getFieldID()))
214
				continue;
215
			sqlBuf.append(" " + name + ",");
216
		}
217
		sqlBuf.append(" " + dbLayerDef.getFieldGeometry());
218
		sqlBuf.append(" ) VALUES (");
219
		
220
		String insertQueryHead = sqlBuf.toString();
221
		sqlBuf = new StringBuffer(insertQueryHead);
222
		
223
		for (int j = 0; j < numAlphanumericFields; j++) {
224
			String name = dbLayerDef.getFieldsDesc()[j].getFieldName();
225
			if (name.equals(dbLayerDef.getFieldID()))
226
				continue;
227

  
228
			if (isNumeric(feat.getAttribute(j)))
229
				sqlBuf.append(feat.getAttribute(j) + ", ");
230
			else{
231
				sqlBuf.append(format(feat.getAttribute(j)) + ", ");
232
			}
233
		}//for	
234
		sqlBuf.append(" GeometryFromText( '"
235
				+ geometryWriter.write(feat.getGeometry().toJTSGeometry()) + "', "
236
				+ dbLayerDef.getSRID_EPSG() + ")");		   
237
		sqlBuf.append(" ) ");
238
		sql = sqlBuf.toString();
239
		return sql;
240
	}
241

  
242
	
243
	
244
//	public String getSqlCreateIndex(DBLayerDefinition lyrDef) {
245
//		String indexName = lyrDef.getTableName() + "_"
246
//				+ lyrDef.getFieldGeometry() + "_gist";
247
//		String sql = "CREATE INDEX \"" + indexName + "\" ON \""
248
//				+ lyrDef.getTableName() + "\" USING GIST (\""
249
//				+ lyrDef.getFieldGeometry() + "\" GIST_GEOMETRY_OPS)";
250
//
251
//		return sql;
252
//	}
253

  
254
	
255
	
256
	public String getSqlModifyFeature(DBLayerDefinition dbLayerDef, IFeature feat) {
257
		StringBuffer sqlBuf = new StringBuffer("UPDATE "
258
				+ dbLayerDef.getTableName() + " SET");
259
		String sql = null;
260
		int numAlphanumericFields = dbLayerDef.getFieldsDesc().length;
261
		for (int i = 0; i < numAlphanumericFields; i++) {
262
			FieldDescription fldDesc = dbLayerDef.getFieldsDesc()[i];
263
			if (fldDesc != null){
264
				String name = fldDesc.getFieldName();
265
				if (name.equalsIgnoreCase(dbLayerDef.getFieldID()))
266
					continue;
267
				Value val = feat.getAttribute(i);
268
				if (val != null)
269
				{
270
					String strAux = val.getStringValue(ValueWriter.internalValueWriter);
271
					sqlBuf.append(" " + name + " = " + strAux + " ,");
272
				}
273
			}
274
		}
275
		sqlBuf.deleteCharAt(sqlBuf.lastIndexOf(","));
276
		if (feat.getGeometry() != null){
277
			sqlBuf.append(", " + dbLayerDef.getFieldGeometry());		
278
			sqlBuf.append(" = ");
279
			sqlBuf.append(" GeometryFromText( '"
280
				+ geometryWriter.write(feat.getGeometry().toJTSGeometry()) + "', "
281
				+ dbLayerDef.getSRID_EPSG() + ")");
282
		}
283
		sqlBuf.append(" WHERE ");
284
		
285
		//TODO El feature.getID() funciona? (AZO)
286
		sqlBuf.append(dbLayerDef.getFieldID() + " = " + feat.getID());
287
		sql = sqlBuf.toString();
288
		return sql;
289

  
290
	}
291

  
292
	
293
	
294
	/**
295
	 * It builds MySQL's delete statement
296
	 * @param dbLayerDef
297
	 * @param row
298
	 * @return
299
	 */
300
	public String getSqlDeleteFeature(DBLayerDefinition dbLayerDef, IRow row) {
301
		// TODO: NECESITAMOS OTRO M?TODO PARA BORRAR CORRECTAMENTE.
302
		// Esto provocar? errores, ya que getID que viene en un row no 
303
		// nos sirve dentro de un writer para modificar y/o borrar entidades
304
		// Por ahora, cojo el ID del campo que me indica el dbLayerDev
305
		StringBuffer sqlBuf = new StringBuffer("DELETE FROM "
306
				+ dbLayerDef.getTableName() + " WHERE ");
307
		String sql = null;
308
		int indexFieldId = dbLayerDef.getIdFieldID();
309
		sqlBuf.append(dbLayerDef.getFieldID() + " = " + row.getAttribute(indexFieldId));
310
		sql = sqlBuf.toString();
311

  
312
		return sql;
313
	}
314

  
315
}
316

  
0 317

  

Also available in: Unified diff