sql: add geolocation to views (#14784)

This commit is contained in:
Frédéric Péters 2017-01-31 14:50:01 +01:00
parent 83826dd478
commit e385356263
2 changed files with 67 additions and 2 deletions

View File

@ -191,6 +191,10 @@ def test_sql_geoloc():
data_class = test_formdef.data_class(mode='sql')
formdata = data_class()
formdata.data = {}
formdata.store() # NULL geolocation
formdata2 = data_class.get(formdata.id)
assert not formdata2.geolocations
formdata.geolocations = {'base': {'lat': 12, 'lon': 21}}
formdata.store()
@ -1186,6 +1190,49 @@ def test_select_any_formdata():
objects2 = sql.AnyFormData.select(order_by='receipt_time', limit=10, offset=20)
assert [(x.formdef_id, x.id) for x in objects2] == [(x.formdef_id, x.id) for x in objects][20:30]
@postgresql
def test_geoloc_in_global_view():
drop_formdef_tables()
conn, cur = sql.get_connection_and_cursor()
now = datetime.datetime.now()
formdef = FormDef()
formdef.name = 'test no geoloc'
formdef.fields = []
formdef.store()
formdef2 = FormDef()
formdef2.name = 'test with geoloc'
formdef2.fields = []
formdef2.geolocations = {'base': 'Plop'}
formdef2.store()
data_class = formdef.data_class(mode='sql')
formdata = data_class()
formdata.just_created()
formdata.store()
data_class = formdef2.data_class(mode='sql')
formdata = data_class()
formdata.just_created()
formdata.geolocations = {'base': {'lat': 12, 'lon': 21}}
formdata.store()
# test generic select
objects = sql.AnyFormData.select()
assert len(objects) == 2
# test clauses
objects2 = sql.AnyFormData.select([st.Null('geoloc_base_x')])
assert len(objects2) == 1
assert not objects2[0].geolocations
objects2 = sql.AnyFormData.select([st.NotNull('geoloc_base_x')])
assert len(objects2) == 1
assert int(objects2[0].geolocations['base']['lat']) == formdata.geolocations['base']['lat']
assert int(objects2[0].geolocations['base']['lon']) == formdata.geolocations['base']['lon']
@postgresql
def test_actions_roles():
drop_formdef_tables()

View File

@ -669,6 +669,16 @@ def do_views(formdef, conn, cur, rebuild_global_views=True):
view_fields.append(('actions_roles_array', 'actions_roles_array'))
view_fields.append(('fts', 'fts'))
if formdef.geolocations and 'base' in formdef.geolocations:
# default geolocation is in the 'base' key; we have to unstructure the
# field is the POINT type of postgresql cannot be used directly as it
# doesn't have an equality operator.
view_fields.append(('geoloc_base[0]', 'geoloc_base_x'))
view_fields.append(('geoloc_base[1]', 'geoloc_base_y'))
else:
view_fields.append(('NULL::real', 'geoloc_base_x'))
view_fields.append(('NULL::real', 'geoloc_base_y'))
fields_list = ', '.join(['%s AS %s' % x for x in view_fields])
cur.execute('''CREATE VIEW %s AS SELECT %s FROM %s''' % (
@ -727,6 +737,8 @@ def do_global_views(conn, cur):
common_fields.append(('formdef_name', 'formdef_name'))
common_fields.append(('user_name', 'user_name'))
common_fields.append(('criticality_level', 'criticality_level'))
common_fields.append(('geoloc_base_x', 'geoloc_base_x'))
common_fields.append(('geoloc_base_y', 'geoloc_base_y'))
union = ' UNION '.join(['''SELECT %s FROM %s''' % (
', '.join([y[1] for y in common_fields]), x) for x in view_names])
@ -1680,6 +1692,8 @@ class AnyFormData(SqlMixin):
common_fields = get_view_fields(fake_formdef)
cls.__table_static_fields = [(x[1], x[0]) for x in common_fields]
cls.__table_static_fields.append(('criticality_level', 'criticality_level'))
cls.__table_static_fields.append(('geoloc_base_x', 'geoloc_base_x'))
cls.__table_static_fields.append(('geoloc_base_y', 'geoloc_base_y'))
return cls.__table_static_fields
@classmethod
@ -1704,6 +1718,9 @@ class AnyFormData(SqlMixin):
# range (see [CRITICALITY_1])
levels = len(formdef.workflow.criticality_levels or [0])
o.criticality_level = levels + o.criticality_level
# convert back unstructured geolocation to the 'native' formdata format.
if o.geoloc_base_x is not None:
o.geolocations = {'base': {'lon': o.geoloc_base_x, 'lat': o.geoloc_base_y}}
return o
@ -1834,7 +1851,7 @@ def get_yearly_totals(period_start=None, period_end=None, criterias=None):
return result
SQL_LEVEL = 18
SQL_LEVEL = 19
def migrate_global_views(conn, cur):
cur.execute('''SELECT COUNT(*) FROM information_schema.tables
@ -1868,7 +1885,7 @@ def migrate():
raise RuntimeError()
if sql_level < 1: # 1: introduction of tracking_code table
do_tracking_code_table()
if sql_level < 17:
if sql_level < 19:
# 2: introduction of formdef_id in views
# 5: add concerned_roles_array, is_at_endpoint and fts to views
# 7: add backoffice_submission to tables
@ -1879,6 +1896,7 @@ def migrate():
# 13: add backoffice_submission to views
# 14: add criticality_level to tables & views
# 15: add geolocation to formdata
# 19: add geolocation to views
migrate_views(conn, cur)
if sql_level < 16:
# 3: introduction of _structured for user fields