Skip to content

Commit 6f9d544

Browse files
troopa81nyalldawson
authored andcommittedJan 24, 2019
Update layer statistics when adding column to table in order to be displayed by QGIS
fixes #13504 (cherry picked from commit 49cb397)
1 parent b2a2251 commit 6f9d544

File tree

3 files changed

+474
-1
lines changed

3 files changed

+474
-1
lines changed
 

‎python/plugins/db_manager/db_plugins/spatialite/connector.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,8 @@ def deleteTable(self, table):
465465
self._execute(c, sql)
466466
self._commit()
467467

468+
return True
469+
468470
def emptyTable(self, table):
469471
""" delete all rows from table """
470472
if self.isRasterTable(table):
@@ -494,6 +496,7 @@ def renameTable(self, table, new_table):
494496
self._execute(c, sql)
495497

496498
self._commit()
499+
return True
497500

498501
def moveTable(self, table, new_table, new_schema=None):
499502
return self.renameTable(table, new_table)
@@ -571,7 +574,16 @@ def runVacuum(self):
571574
def addTableColumn(self, table, field_def):
572575
""" add a column to table """
573576
sql = u"ALTER TABLE %s ADD %s" % (self.quoteId(table), field_def)
574-
self._execute_and_commit(sql)
577+
self._execute(None, sql)
578+
579+
sql = u"SELECT InvalidateLayerStatistics(%s)" % (self.quoteId(table))
580+
self._execute(None, sql)
581+
582+
sql = u"SELECT UpdateLayerStatistics(%s)" % (self.quoteId(table))
583+
self._execute(None, sql)
584+
585+
self._commit()
586+
return True
575587

576588
def deleteTableColumn(self, table, column):
577589
""" delete column from a table """
@@ -583,6 +595,8 @@ def deleteTableColumn(self, table, column):
583595
sql = u"SELECT DiscardGeometryColumn(%s, %s)" % (self.quoteString(tablename), self.quoteString(column))
584596
self._execute_and_commit(sql)
585597

598+
return True
599+
586600
def updateTableColumn(self, table, column, new_name, new_data_type=None, new_not_null=None, new_default=None):
587601
return False # column editing not supported
588602

‎tests/src/python/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ ADD_PYTHON_TEST(PyQgsConsole test_console.py)
216216
ADD_PYTHON_TEST(PyQgsLayerDependencies test_layer_dependencies.py)
217217
ADD_PYTHON_TEST(PyQgsVersionCompare test_versioncompare.py)
218218
ADD_PYTHON_TEST(PyQgsDBManagerGpkg test_db_manager_gpkg.py)
219+
ADD_PYTHON_TEST(PyQgsDBManagerSpatialite test_db_manager_spatialite.py)
219220
ADD_PYTHON_TEST(PyQgsFileDownloader test_qgsfiledownloader.py)
220221
ADD_PYTHON_TEST(PyQgsSettings test_qgssettings.py)
221222
ADD_PYTHON_TEST(PyQgsZipUtils test_qgsziputils.py)
Lines changed: 458 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,458 @@
1+
# -*- coding: utf-8 -*-
2+
"""QGIS Unit tests for the DBManager SPATIALITE plugin
3+
4+
.. note:: This program is free software; you can redistribute it and/or modify
5+
it under the terms of the GNU General Public License as published by
6+
the Free Software Foundation; either version 2 of the License, or
7+
(at your option) any later version.
8+
"""
9+
__author__ = 'Even Rouault'
10+
__date__ = '2016-10-17'
11+
__copyright__ = 'Copyright 2016, Even Rouault'
12+
# This will get replaced with a git SHA1 when you do a git archive
13+
__revision__ = '$Format:%H$'
14+
15+
import qgis # NOQA
16+
17+
import os
18+
import tempfile
19+
import shutil
20+
from osgeo import gdal, ogr, osr
21+
22+
from qgis.core import QgsDataSourceUri, QgsSettings
23+
from qgis.PyQt.QtCore import QCoreApplication
24+
from qgis.testing import start_app, unittest
25+
26+
from plugins.db_manager.db_plugins import supportedDbTypes, createDbPlugin
27+
from plugins.db_manager.db_plugins.plugin import TableField
28+
29+
30+
def GDAL_COMPUTE_VERSION(maj, min, rev):
31+
return ((maj) * 1000000 + (min) * 10000 + (rev) * 100)
32+
33+
34+
class TestPyQgsDBManagerSpatialite(unittest.TestCase):
35+
36+
@classmethod
37+
def setUpClass(cls):
38+
"""Run before all tests"""
39+
40+
QCoreApplication.setOrganizationName("QGIS_Test")
41+
QCoreApplication.setOrganizationDomain("TestPyQgsDBManagerSpatialite.com")
42+
QCoreApplication.setApplicationName("TestPyQgsDBManagerSpatialite")
43+
QgsSettings().clear()
44+
start_app()
45+
46+
cls.basetestpath = tempfile.mkdtemp()
47+
48+
cls.test_spatialite = os.path.join(cls.basetestpath, 'TestPyQgsDBManagerSpatialite.spatialite')
49+
ds = ogr.GetDriverByName('SQLite').CreateDataSource(cls.test_spatialite)
50+
lyr = ds.CreateLayer('testlayer', geom_type=ogr.wkbLineString, options=['SPATIAL_INDEX=NO'])
51+
cls.supportsAlterFieldDefn = lyr.TestCapability(ogr.OLCAlterFieldDefn) == 1
52+
lyr.CreateField(ogr.FieldDefn('text_field', ogr.OFTString))
53+
f = ogr.Feature(lyr.GetLayerDefn())
54+
f['text_field'] = 'foo'
55+
f.SetGeometry(ogr.CreateGeometryFromWkt('LINESTRING(1 2,3 4)'))
56+
lyr.CreateFeature(f)
57+
f = None
58+
ds = None
59+
60+
@classmethod
61+
def tearDownClass(cls):
62+
"""Run after all tests"""
63+
64+
QgsSettings().clear()
65+
shutil.rmtree(cls.basetestpath, True)
66+
67+
def testSupportedDbTypes(self):
68+
self.assertIn('spatialite', supportedDbTypes())
69+
70+
def testCreateDbPlugin(self):
71+
plugin = createDbPlugin('spatialite')
72+
self.assertIsNotNone(plugin)
73+
74+
def testConnect(self):
75+
connection_name = 'testConnect'
76+
plugin = createDbPlugin('spatialite')
77+
78+
uri = QgsDataSourceUri()
79+
uri.setDatabase(self.test_spatialite)
80+
self.assertTrue(plugin.addConnection(connection_name, uri))
81+
82+
connections = plugin.connections()
83+
self.assertEqual(len(connections), 1)
84+
85+
connection = createDbPlugin('spatialite', connection_name + '_does_not_exist')
86+
connection_succeeded = False
87+
try:
88+
connection.connect()
89+
connection_succeeded = True
90+
except:
91+
pass
92+
self.assertFalse(connection_succeeded, 'exception should have been raised')
93+
94+
connection = connections[0]
95+
connection.connect()
96+
97+
connection.reconnect()
98+
99+
connection.remove()
100+
101+
self.assertEqual(len(plugin.connections()), 0)
102+
103+
connection = createDbPlugin('spatialite', connection_name)
104+
connection_succeeded = False
105+
try:
106+
connection.connect()
107+
connection_succeeded = True
108+
except:
109+
pass
110+
self.assertFalse(connection_succeeded, 'exception should have been raised')
111+
112+
def testListLayer(self):
113+
connection_name = 'testListLayer'
114+
plugin = createDbPlugin('spatialite')
115+
uri = QgsDataSourceUri()
116+
uri.setDatabase(self.test_spatialite)
117+
self.assertTrue(plugin.addConnection(connection_name, uri))
118+
119+
connection = createDbPlugin('spatialite', connection_name)
120+
connection.connect()
121+
122+
db = connection.database()
123+
self.assertIsNotNone(db)
124+
125+
tables = db.tables()
126+
self.assertEqual(len(tables), 1)
127+
table = tables[0]
128+
self.assertEqual(table.name, 'testlayer')
129+
130+
info = table.info()
131+
# expected_html = """<div class="section"><h2>General info</h2><div><table><tr><td>Relation type:&nbsp;</td><td>Table&nbsp;</td></tr><tr><td>Rows:&nbsp;</td><td>1&nbsp;</td></tr></table></div></div><div class="section"><h2>GeoPackage</h2><div><table><tr><td>Column:&nbsp;</td><td>geom&nbsp;</td></tr><tr><td>Geometry:&nbsp;</td><td>LINESTRING&nbsp;</td></tr><tr><td>Dimension:&nbsp;</td><td>XY&nbsp;</td></tr><tr><td>Spatial ref:&nbsp;</td><td>Undefined (-1)&nbsp;</td></tr><tr><td>Extent:&nbsp;</td><td>1.00000, 2.00000 - 3.00000, 4.00000&nbsp;</td></tr></table><p><warning> No spatial index defined (<a href="action:spatialindex/create">create it</a>)</p></div></div><div class="section"><h2>Fields</h2><div><table class="header"><tr><th>#&nbsp;</th><th>Name&nbsp;</th><th>Type&nbsp;</th><th>Null&nbsp;</th><th>Default&nbsp;</th></tr><tr><td>0&nbsp;</td><td class="underline">fid&nbsp;</td><td>INTEGER&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr><tr><td>1&nbsp;</td><td>geom&nbsp;</td><td>LINESTRING&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr><tr><td>2&nbsp;</td><td>text_field&nbsp;</td><td>TEXT&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr></table></div></div>"""
132+
133+
# # GDAL 2.2.0
134+
# expected_html_2 = """<div class="section"><h2>General info</h2><div><table><tr><td>Relation type:&nbsp;</td><td>Table&nbsp;</td></tr><tr><td>Rows:&nbsp;</td><td>1&nbsp;</td></tr></table></div></div><div class="section"><h2>GeoPackage</h2><div><table><tr><td>Column:&nbsp;</td><td>geom&nbsp;</td></tr><tr><td>Geometry:&nbsp;</td><td>LINESTRING&nbsp;</td></tr><tr><td>Dimension:&nbsp;</td><td>XY&nbsp;</td></tr><tr><td>Spatial ref:&nbsp;</td><td>Undefined (-1)&nbsp;</td></tr><tr><td>Extent:&nbsp;</td><td>1.00000, 2.00000 - 3.00000, 4.00000&nbsp;</td></tr></table><p><warning> No spatial index defined (<a href="action:spatialindex/create">create it</a>)</p></div></div><div class="section"><h2>Fields</h2><div><table class="header"><tr><th>#&nbsp;</th><th>Name&nbsp;</th><th>Type&nbsp;</th><th>Null&nbsp;</th><th>Default&nbsp;</th></tr><tr><td>0&nbsp;</td><td class="underline">fid&nbsp;</td><td>INTEGER&nbsp;</td><td>N&nbsp;</td><td>&nbsp;</td></tr><tr><td>1&nbsp;</td><td>geom&nbsp;</td><td>LINESTRING&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr><tr><td>2&nbsp;</td><td>text_field&nbsp;</td><td>TEXT&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr></table></div></div><div class="section"><h2>Triggers</h2><div><table class="header"><tr><th>Name&nbsp;</th><th>Function&nbsp;</th></tr><tr><td>trigger_insert_feature_count_testlayer (<a href="action:trigger/trigger_insert_feature_count_testlayer/delete">delete</a>)&nbsp;</td><td>CREATE TRIGGER "trigger_insert_feature_count_testlayer" AFTER INSERT ON "testlayer" BEGIN UPDATE spatialite_ogr_contents SET feature_count = feature_count + 1 WHERE table_name = 'testlayer'; END&nbsp;</td></tr><tr><td>trigger_delete_feature_count_testlayer (<a href="action:trigger/trigger_delete_feature_count_testlayer/delete">delete</a>)&nbsp;</td><td>CREATE TRIGGER "trigger_delete_feature_count_testlayer" AFTER DELETE ON "testlayer" BEGIN UPDATE spatialite_ogr_contents SET feature_count = feature_count - 1 WHERE table_name = 'testlayer'; END&nbsp;</td></tr></table></div></div>"""
135+
136+
# # GDAL 2.3.0
137+
# expected_html_3 = """<div class="section"><h2>General info</h2><div><table><tr><td>Relation type:&nbsp;</td><td>Table&nbsp;</td></tr><tr><td>Rows:&nbsp;</td><td>1&nbsp;</td></tr></table></div></div><div class="section"><h2>GeoPackage</h2><div><table><tr><td>Column:&nbsp;</td><td>geom&nbsp;</td></tr><tr><td>Geometry:&nbsp;</td><td>LINESTRING&nbsp;</td></tr><tr><td>Dimension:&nbsp;</td><td>XY&nbsp;</td></tr><tr><td>Spatial ref:&nbsp;</td><td>Undefined (-1)&nbsp;</td></tr><tr><td>Extent:&nbsp;</td><td>1.00000, 2.00000 - 3.00000, 4.00000&nbsp;</td></tr></table><p><warning> No spatial index defined (<a href="action:spatialindex/create">create it</a>)</p></div></div><div class="section"><h2>Fields</h2><div><table class="header"><tr><th>#&nbsp;</th><th>Name&nbsp;</th><th>Type&nbsp;</th><th>Null&nbsp;</th><th>Default&nbsp;</th></tr><tr><td>0&nbsp;</td><td class="underline">fid&nbsp;</td><td>INTEGER&nbsp;</td><td>N&nbsp;</td><td>&nbsp;</td></tr><tr><td>1&nbsp;</td><td>geom&nbsp;</td><td>LINESTRING&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr><tr><td>2&nbsp;</td><td>text_field&nbsp;</td><td>TEXT&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr></table></div></div><div class="section"><h2>Triggers</h2><div><table class="header"><tr><th>Name&nbsp;</th><th>Function&nbsp;</th></tr><tr><td>trigger_insert_feature_count_testlayer (<a href="action:trigger/trigger_insert_feature_count_testlayer/delete">delete</a>)&nbsp;</td><td>CREATE TRIGGER "trigger_insert_feature_count_testlayer" AFTER INSERT ON "testlayer" BEGIN UPDATE spatialite_ogr_contents SET feature_count = feature_count + 1 WHERE lower(table_name) = lower('testlayer'); END&nbsp;</td></tr><tr><td>trigger_delete_feature_count_testlayer (<a href="action:trigger/trigger_delete_feature_count_testlayer/delete">delete</a>)&nbsp;</td><td>CREATE TRIGGER "trigger_delete_feature_count_testlayer" AFTER DELETE ON "testlayer" BEGIN UPDATE spatialite_ogr_contents SET feature_count = feature_count - 1 WHERE lower(table_name) = lower('testlayer'); END&nbsp;</td></tr></table></div></div>"""
138+
139+
# GDAL 2.3.0
140+
expected_html = """<div class="section"><h2>General info</h2><div><table><tr><td>Relation type:&nbsp;</td><td>Table&nbsp;</td></tr><tr><td>Rows:&nbsp;</td><td>1&nbsp;</td></tr></table></div></div><div class="section"><h2>Fields</h2><div><table class="header"><tr><th>#&nbsp;</th><th>Name&nbsp;</th><th>Type&nbsp;</th><th>Null&nbsp;</th><th>Default&nbsp;</th></tr><tr><td>0&nbsp;</td><td class="underline">ogc_fid&nbsp;</td><td>INTEGER&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr><tr><td>1&nbsp;</td><td>GEOMETRY&nbsp;</td><td>BLOB&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr><tr><td>2&nbsp;</td><td>text_field&nbsp;</td><td>VARCHAR&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr></table></div></div>"""
141+
142+
self.assertIn(info.toHtml(), [expected_html])
143+
144+
connection.remove()
145+
146+
def testCreateRenameDeleteTable(self):
147+
connection_name = 'testCreateRenameDeleteTable'
148+
plugin = createDbPlugin('spatialite')
149+
uri = QgsDataSourceUri()
150+
151+
test_spatialite_new = os.path.join(self.basetestpath, 'testCreateRenameDeleteTable.spatialite')
152+
shutil.copy(self.test_spatialite, test_spatialite_new)
153+
154+
uri.setDatabase(test_spatialite_new)
155+
self.assertTrue(plugin.addConnection(connection_name, uri))
156+
157+
connection = createDbPlugin('spatialite', connection_name)
158+
connection.connect()
159+
160+
db = connection.database()
161+
self.assertIsNotNone(db)
162+
163+
tables = db.tables()
164+
self.assertEqual(len(tables), 1)
165+
table = tables[0]
166+
self.assertTrue(table.rename('newName'))
167+
self.assertEqual(table.name, 'newName')
168+
169+
connection.reconnect()
170+
171+
db = connection.database()
172+
tables = db.tables()
173+
self.assertEqual(len(tables), 1)
174+
table = tables[0]
175+
self.assertEqual(table.name, 'newName')
176+
177+
fields = []
178+
geom = ['geometry', 'POINT', 4326, 3]
179+
field1 = TableField(table)
180+
field1.name = 'fid'
181+
field1.dataType = 'INTEGER'
182+
field1.notNull = True
183+
field1.primaryKey = True
184+
185+
field2 = TableField(table)
186+
field2.name = 'str_field'
187+
field2.dataType = 'TEXT'
188+
field2.modifier = 20
189+
190+
fields = [field1, field2]
191+
self.assertTrue(db.createVectorTable('newName2', fields, geom))
192+
193+
tables = db.tables()
194+
self.assertEqual(len(tables), 2)
195+
new_table = tables[1]
196+
self.assertEqual(new_table.name, 'newName2')
197+
fields = new_table.fields()
198+
199+
self.assertEqual(len(fields), 2)
200+
201+
# self.assertFalse(new_table.hasSpatialIndex())
202+
203+
# self.assertTrue(new_table.createSpatialIndex())
204+
# self.assertTrue(new_table.hasSpatialIndex())
205+
206+
self.assertTrue(new_table.delete())
207+
208+
tables = db.tables()
209+
self.assertEqual(len(tables), 1)
210+
211+
connection.remove()
212+
213+
def testCreateRenameDeleteFields(self):
214+
215+
if not self.supportsAlterFieldDefn:
216+
return
217+
218+
connection_name = 'testCreateRenameDeleteFields'
219+
plugin = createDbPlugin('spatialite')
220+
uri = QgsDataSourceUri()
221+
222+
test_spatialite_new = os.path.join(self.basetestpath, 'testCreateRenameDeleteFields.spatialite')
223+
shutil.copy(self.test_spatialite, test_spatialite_new)
224+
225+
uri.setDatabase(test_spatialite_new)
226+
self.assertTrue(plugin.addConnection(connection_name, uri))
227+
228+
connection = createDbPlugin('spatialite', connection_name)
229+
connection.connect()
230+
231+
db = connection.database()
232+
self.assertIsNotNone(db)
233+
234+
tables = db.tables()
235+
self.assertEqual(len(tables), 1)
236+
table = tables[0]
237+
238+
field_before_count = len(table.fields())
239+
240+
field = TableField(table)
241+
field.name = 'real_field'
242+
field.dataType = 'DOUBLE'
243+
self.assertTrue(table.addField(field))
244+
245+
self.assertEqual(len(table.fields()), field_before_count + 1)
246+
247+
# not supported in spatialite
248+
# self.assertTrue(field.update('real_field2', new_type_str='TEXT (30)', new_not_null=True, new_default_str='foo'))
249+
250+
field = table.fields()[field_before_count]
251+
self.assertEqual(field.name, 'real_field')
252+
self.assertEqual(field.dataType, 'DOUBLE')
253+
# self.assertEqual(field.notNull, 1)
254+
# self.assertEqual(field.default, "'foo'")
255+
256+
# self.assertTrue(table.deleteField(field))
257+
258+
# self.assertEqual(len(table.fields()), field_before_count)
259+
260+
connection.remove()
261+
262+
def testTableDataModel(self):
263+
connection_name = 'testTableDataModel'
264+
plugin = createDbPlugin('spatialite')
265+
uri = QgsDataSourceUri()
266+
uri.setDatabase(self.test_spatialite)
267+
self.assertTrue(plugin.addConnection(connection_name, uri))
268+
269+
connection = createDbPlugin('spatialite', connection_name)
270+
connection.connect()
271+
272+
db = connection.database()
273+
self.assertIsNotNone(db)
274+
275+
tables = db.tables()
276+
self.assertEqual(len(tables), 1)
277+
table = tables[0]
278+
self.assertEqual(table.name, 'testlayer')
279+
model = table.tableDataModel(None)
280+
281+
self.assertEqual(model.rowCount(), 1)
282+
self.assertEqual(model.getData(0, 0), 1) # fid
283+
284+
wkb = model.getData(0, 1)
285+
geometry = ogr.CreateGeometryFromWkb(wkb)
286+
self.assertEqual(geometry.ExportToWkt(), 'LINESTRING (1 2,3 4)')
287+
288+
self.assertEqual(model.getData(0, 2), 'foo')
289+
290+
connection.remove()
291+
292+
# def testRaster(self):
293+
294+
# if int(gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 0, 2):
295+
# return
296+
297+
# connection_name = 'testRaster'
298+
# plugin = createDbPlugin('spatialite')
299+
# uri = QgsDataSourceUri()
300+
301+
# test_spatialite_new = os.path.join(self.basetestpath, 'testRaster.spatialite')
302+
# shutil.copy(self.test_spatialite, test_spatialite_new)
303+
# mem_ds = gdal.GetDriverByName('MEM').Create('', 20, 20)
304+
# mem_ds.SetGeoTransform([2, 0.01, 0, 49, 0, -0.01])
305+
# sr = osr.SpatialReference()
306+
# sr.ImportFromEPSG(4326)
307+
# mem_ds.SetProjection(sr.ExportToWkt())
308+
# mem_ds.GetRasterBand(1).Fill(255)
309+
# gdal.GetDriverByName('SQLite').CreateCopy(test_spatialite_new, mem_ds, options=['APPEND_SUBDATASET=YES', 'RASTER_TABLE=raster_table'])
310+
# mem_ds = None
311+
312+
# uri.setDatabase(test_spatialite_new)
313+
# self.assertTrue(plugin.addConnection(connection_name, uri))
314+
315+
# connection = createDbPlugin('spatialite', connection_name)
316+
# connection.connect()
317+
318+
# db = connection.database()
319+
# self.assertIsNotNone(db)
320+
321+
# tables = db.tables()
322+
# self.assertEqual(len(tables), 2)
323+
# table = None
324+
# for i in range(2):
325+
# if tables[i].name == 'raster_table':
326+
# table = tables[i]
327+
# break
328+
# self.assertIsNotNone(table)
329+
# info = table.info()
330+
# expected_html = """<div class="section"><h2>General info</h2><div><table><tr><td>Relation type:&nbsp;</td><td>Table&nbsp;</td></tr><tr><td>Rows:&nbsp;</td><td>Unknown (<a href="action:rows/count">find out</a>)&nbsp;</td></tr></table></div></div><div class="section"><h2>GeoPackage</h2><div><table><tr><td>Column:&nbsp;</td><td>&nbsp;</td></tr><tr><td>Geometry:&nbsp;</td><td>RASTER&nbsp;</td></tr><tr><td>Spatial ref:&nbsp;</td><td>WGS 84 geodetic (4326)&nbsp;</td></tr><tr><td>Extent:&nbsp;</td><td>2.00000, 48.80000 - 2.20000, 49.00000&nbsp;</td></tr></table></div></div><div class="section"><h2>Fields</h2><div><table class="header"><tr><th>#&nbsp;</th><th>Name&nbsp;</th><th>Type&nbsp;</th><th>Null&nbsp;</th><th>Default&nbsp;</th></tr><tr><td>0&nbsp;</td><td class="underline">id&nbsp;</td><td>INTEGER&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr><tr><td>1&nbsp;</td><td>zoom_level&nbsp;</td><td>INTEGER&nbsp;</td><td>N&nbsp;</td><td>&nbsp;</td></tr><tr><td>2&nbsp;</td><td>tile_column&nbsp;</td><td>INTEGER&nbsp;</td><td>N&nbsp;</td><td>&nbsp;</td></tr><tr><td>3&nbsp;</td><td>tile_row&nbsp;</td><td>INTEGER&nbsp;</td><td>N&nbsp;</td><td>&nbsp;</td></tr><tr><td>4&nbsp;</td><td>tile_data&nbsp;</td><td>BLOB&nbsp;</td><td>N&nbsp;</td><td>&nbsp;</td></tr></table></div></div><div class="section"><h2>Indexes</h2><div><table class="header"><tr><th>Name&nbsp;</th><th>Column(s)&nbsp;</th></tr><tr><td>sqlite_autoindex_raster_table_1&nbsp;</td><td>zoom_level<br>tile_column<br>tile_row&nbsp;</td></tr></table></div></div>"""
331+
332+
# self.assertEqual(info.toHtml(), expected_html)
333+
334+
# connection.remove()
335+
336+
# def testTwoRaster(self):
337+
338+
# if int(gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 0, 2):
339+
# return
340+
341+
# connection_name = 'testTwoRaster'
342+
# plugin = createDbPlugin('spatialite')
343+
# uri = QgsDataSourceUri()
344+
345+
# test_spatialite_new = os.path.join(self.basetestpath, 'testTwoRaster.spatialite')
346+
# shutil.copy(self.test_spatialite, test_spatialite_new)
347+
# mem_ds = gdal.GetDriverByName('MEM').Create('', 20, 20)
348+
# mem_ds.SetGeoTransform([2, 0.01, 0, 49, 0, -0.01])
349+
# sr = osr.SpatialReference()
350+
# sr.ImportFromEPSG(4326)
351+
# mem_ds.SetProjection(sr.ExportToWkt())
352+
# mem_ds.GetRasterBand(1).Fill(255)
353+
# for i in range(2):
354+
# gdal.GetDriverByName('SQLite').CreateCopy(test_spatialite_new, mem_ds, options=['APPEND_SUBDATASET=YES', 'RASTER_TABLE=raster_table%d' % (i + 1)])
355+
# mem_ds = None
356+
357+
# uri.setDatabase(test_spatialite_new)
358+
# self.assertTrue(plugin.addConnection(connection_name, uri))
359+
360+
# connection = createDbPlugin('spatialite', connection_name)
361+
# connection.connect()
362+
363+
# db = connection.database()
364+
# self.assertIsNotNone(db)
365+
366+
# tables = db.tables()
367+
# self.assertEqual(len(tables), 3)
368+
# table = None
369+
# for i in range(2):
370+
# if tables[i].name.startswith('raster_table'):
371+
# table = tables[i]
372+
# info = table.info()
373+
# info.toHtml()
374+
375+
# connection.remove()
376+
377+
def testNonSpatial(self):
378+
379+
connection_name = 'testnonspatial'
380+
plugin = createDbPlugin('spatialite')
381+
uri = QgsDataSourceUri()
382+
383+
test_spatialite = os.path.join(self.basetestpath, 'testnonspatial.spatialite')
384+
ds = ogr.GetDriverByName('SQLite').CreateDataSource(test_spatialite)
385+
lyr = ds.CreateLayer('testnonspatial', geom_type=ogr.wkbNone)
386+
lyr.CreateField(ogr.FieldDefn('text_field', ogr.OFTString))
387+
f = ogr.Feature(lyr.GetLayerDefn())
388+
f['text_field'] = 'foo'
389+
lyr.CreateFeature(f)
390+
f = None
391+
ds = None
392+
393+
uri.setDatabase(test_spatialite)
394+
self.assertTrue(plugin.addConnection(connection_name, uri))
395+
396+
connection = createDbPlugin('spatialite', connection_name)
397+
connection.connect()
398+
399+
db = connection.database()
400+
self.assertIsNotNone(db)
401+
402+
tables = db.tables()
403+
self.assertEqual(len(tables), 1)
404+
table = tables[0]
405+
self.assertEqual(table.name, 'testnonspatial')
406+
info = table.info()
407+
# expected_html = """<div class="section"><h2>General info</h2><div><table><tr><td>Relation type:&nbsp;</td><td>Table&nbsp;</td></tr><tr><td>Rows:&nbsp;</td><td>1&nbsp;</td></tr></table></div></div><div class="section"><h2>Fields</h2><div><table class="header"><tr><th>#&nbsp;</th><th>Name&nbsp;</th><th>Type&nbsp;</th><th>Null&nbsp;</th><th>Default&nbsp;</th></tr><tr><td>0&nbsp;</td><td class="underline">fid&nbsp;</td><td>INTEGER&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr><tr><td>1&nbsp;</td><td>text_field&nbsp;</td><td>TEXT&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr></table></div></div>"""
408+
409+
# # GDAL 2.2.0
410+
# expected_html_2 = """<div class="section"><h2>General info</h2><div><table><tr><td>Relation type:&nbsp;</td><td>Table&nbsp;</td></tr><tr><td>Rows:&nbsp;</td><td>1&nbsp;</td></tr></table></div></div><div class="section"><h2>Fields</h2><div><table class="header"><tr><th>#&nbsp;</th><th>Name&nbsp;</th><th>Type&nbsp;</th><th>Null&nbsp;</th><th>Default&nbsp;</th></tr><tr><td>0&nbsp;</td><td class="underline">fid&nbsp;</td><td>INTEGER&nbsp;</td><td>N&nbsp;</td><td>&nbsp;</td></tr><tr><td>1&nbsp;</td><td>text_field&nbsp;</td><td>TEXT&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr></table></div></div><div class="section"><h2>Triggers</h2><div><table class="header"><tr><th>Name&nbsp;</th><th>Function&nbsp;</th></tr><tr><td>trigger_insert_feature_count_testnonspatial (<a href="action:trigger/trigger_insert_feature_count_testnonspatial/delete">delete</a>)&nbsp;</td><td>CREATE TRIGGER "trigger_insert_feature_count_testnonspatial" AFTER INSERT ON "testnonspatial" BEGIN UPDATE spatialite_ogr_contents SET feature_count = feature_count + 1 WHERE table_name = 'testnonspatial'; END&nbsp;</td></tr><tr><td>trigger_delete_feature_count_testnonspatial (<a href="action:trigger/trigger_delete_feature_count_testnonspatial/delete">delete</a>)&nbsp;</td><td>CREATE TRIGGER "trigger_delete_feature_count_testnonspatial" AFTER DELETE ON "testnonspatial" BEGIN UPDATE spatialite_ogr_contents SET feature_count = feature_count - 1 WHERE table_name = 'testnonspatial'; END&nbsp;</td></tr></table></div></div>"""
411+
412+
# # GDAL 2.3.0
413+
# expected_html_3 = """<div class="section"><h2>General info</h2><div><table><tr><td>Relation type:&nbsp;</td><td>Table&nbsp;</td></tr><tr><td>Rows:&nbsp;</td><td>1&nbsp;</td></tr></table></div></div><div class="section"><h2>Fields</h2><div><table class="header"><tr><th>#&nbsp;</th><th>Name&nbsp;</th><th>Type&nbsp;</th><th>Null&nbsp;</th><th>Default&nbsp;</th></tr><tr><td>0&nbsp;</td><td class="underline">fid&nbsp;</td><td>INTEGER&nbsp;</td><td>N&nbsp;</td><td>&nbsp;</td></tr><tr><td>1&nbsp;</td><td>text_field&nbsp;</td><td>TEXT&nbsp;</td><td>Y&nbsp;</td><td>&nbsp;</td></tr></table></div></div><div class="section"><h2>Triggers</h2><div><table class="header"><tr><th>Name&nbsp;</th><th>Function&nbsp;</th></tr><tr><td>trigger_insert_feature_count_testnonspatial (<a href="action:trigger/trigger_insert_feature_count_testnonspatial/delete">delete</a>)&nbsp;</td><td>CREATE TRIGGER "trigger_insert_feature_count_testnonspatial" AFTER INSERT ON "testnonspatial" BEGIN UPDATE spatialite_ogr_contents SET feature_count = feature_count + 1 WHERE lower(table_name) = lower('testnonspatial'); END&nbsp;</td></tr><tr><td>trigger_delete_feature_count_testnonspatial (<a href="action:trigger/trigger_delete_feature_count_testnonspatial/delete">delete</a>)&nbsp;</td><td>CREATE TRIGGER "trigger_delete_feature_count_testnonspatial" AFTER DELETE ON "testnonspatial" BEGIN UPDATE spatialite_ogr_contents SET feature_count = feature_count - 1 WHERE lower(table_name) = lower('testnonspatial'); END&nbsp;</td></tr></table></div></div>"""
414+
# self.assertIn(info.toHtml(), [expected_html, expected_html_2, expected_html_3], info.toHtml())
415+
416+
connection.remove()
417+
418+
def testAllGeometryTypes(self):
419+
420+
connection_name = 'testAllGeometryTypes'
421+
plugin = createDbPlugin('spatialite')
422+
uri = QgsDataSourceUri()
423+
424+
test_spatialite = os.path.join(self.basetestpath, 'testAllGeometryTypes.spatialite')
425+
ds = ogr.GetDriverByName('SQLite').CreateDataSource(test_spatialite)
426+
ds.CreateLayer('testPoint', geom_type=ogr.wkbPoint)
427+
ds.CreateLayer('testLineString', geom_type=ogr.wkbLineString)
428+
ds.CreateLayer('testPolygon', geom_type=ogr.wkbPolygon)
429+
ds.CreateLayer('testMultiPoint', geom_type=ogr.wkbMultiPoint)
430+
ds.CreateLayer('testMultiLineString', geom_type=ogr.wkbMultiLineString)
431+
ds.CreateLayer('testMultiPolygon', geom_type=ogr.wkbMultiPolygon)
432+
ds.CreateLayer('testGeometryCollection', geom_type=ogr.wkbGeometryCollection)
433+
ds.CreateLayer('testCircularString', geom_type=ogr.wkbCircularString)
434+
ds.CreateLayer('testCompoundCurve', geom_type=ogr.wkbCompoundCurve)
435+
ds.CreateLayer('testCurvePolygon', geom_type=ogr.wkbCurvePolygon)
436+
ds.CreateLayer('testMultiCurve', geom_type=ogr.wkbMultiCurve)
437+
ds.CreateLayer('testMultiSurface', geom_type=ogr.wkbMultiSurface)
438+
ds = None
439+
440+
uri.setDatabase(test_spatialite)
441+
self.assertTrue(plugin.addConnection(connection_name, uri))
442+
443+
connection = createDbPlugin('spatialite', connection_name)
444+
connection.connect()
445+
446+
db = connection.database()
447+
self.assertIsNotNone(db)
448+
449+
# tables = db.tables()
450+
# for i in range(len(tables)):
451+
# table = tables[i]
452+
# info = table.info()
453+
454+
connection.remove()
455+
456+
457+
if __name__ == '__main__':
458+
unittest.main()

0 commit comments

Comments
 (0)
Please sign in to comment.