Ejemplo n.º 1
0
    def update_timestamp(self, attrs):
        self.ts = attrs.get("timestamp",
                            time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()))
        self.version = attrs.get("version", None)
        self.analyser_version = attrs.get("analyser_version", None)

        if not self._tstamp_updated:
            try:
                execute_sql(
                    self._dbcurs,
                    "INSERT INTO dynpoi_update (source, timestamp, remote_url, remote_ip, version, analyser_version) VALUES(%s, %s, %s, %s, %s, %s);",
                    (self._source_id, utils.pg_escape(
                        self.ts), utils.pg_escape(self._source_url),
                     utils.pg_escape(
                         self._remote_ip), utils.pg_escape(self.version),
                     utils.pg_escape(self.analyser_version)))
            except psycopg2.IntegrityError:
                self._dbconn.rollback()
                execute_sql(
                    self._dbcurs,
                    "SELECT count(*) FROM dynpoi_update WHERE source = %s AND \"timestamp\" = %s",
                    (self._source_id, utils.pg_escape(self.ts)))
                r = self._dbcurs.fetchone()
                if r["count"] == 1:
                    raise OsmoseUpdateAlreadyDone(
                        "source=%s and timestamp=%s are already present" %
                        (self._source_id, utils.pg_escape(self.ts)))
                else:
                    raise

            execute_sql(
                self._dbcurs,
                "UPDATE dynpoi_update_last SET timestamp=%s, version=%s, analyser_version=%s, remote_ip=%s WHERE source=%s;",
                (utils.pg_escape(self.ts), utils.pg_escape(
                    self.version), utils.pg_escape(self.analyser_version),
                 utils.pg_escape(self._remote_ip), self._source_id))
            if self._dbcurs.rowcount == 0:
                execute_sql(
                    self._dbcurs,
                    "INSERT INTO dynpoi_update_last(source, timestamp, version, analyser_version, remote_ip) VALUES(%s, %s, %s, %s, %s);",
                    (self._source_id, utils.pg_escape(
                        self.ts), utils.pg_escape(self.version),
                     utils.pg_escape(self.analyser_version),
                     utils.pg_escape(self._remote_ip)))

            self._tstamp_updated = True
Ejemplo n.º 2
0
    def endElement(self, name):
        self.element_stack.pop()

        if name == u"analyser":
            for class_id, uuid in self.all_uuid.items():
                execute_sql(
                    self._dbcurs,
                    "DELETE FROM marker WHERE source = %s AND class = %s AND uuid != ALL (%s::uuid[])",
                    (self._source_id, class_id, uuid))

        elif name == u"error":
            ## add data at all location
            if len(self._error_locations) == 0:
                print("No location on error found on line %d" %
                      self.locator.getLineNumber())
                return

            elems = list(
                filter(
                    lambda e: e,
                    map(
                        lambda elem: dict(
                            filter(
                                lambda k_v: k_v[1], {
                                    'type': elem['type'][0].upper(),
                                    'id': int(elem['id']),
                                    'tags': elem['tag'],
                                    'username': elem['user'],
                                }.items())) if elem['type'] in
                        ('node', 'way', 'relation') else dict(
                            filter(lambda k_v: k_v[1], {
                                'tags': elem['tag'],
                                'username': elem['user'],
                            }.items())) if elem['type'] in ('infos') else None,
                        self._error_elements)))

            fixes = list(
                map(
                    lambda fix: list(
                        map(
                            lambda elem: dict(
                                filter(
                                    lambda k_v: k_v[1], {
                                        'type': elem['type'][0].upper(),
                                        'id': int(elem['id']),
                                        'create': elem['create'],
                                        'modify': elem['modify'],
                                        'delete': elem['delete'],
                                    }.items())),
                            filter(
                                lambda elem: elem['type'] in
                                ('node', 'way', 'relation'), fix))),
                    self._fixes))

            sql_uuid = u"SELECT ('{' || encode(substring(digest(%(source)s || '/' || %(class)s || '/' || %(subclass)s || '/' || %(elems_sig)s, 'sha256') from 1 for 16), 'hex') || '}')::uuid AS uuid"

            ## sql template
            sql_marker = u"INSERT INTO marker (uuid, source, class, item, lat, lon, elems, fixes, subtitle) "
            sql_marker += u"VALUES (('{' || encode(substring(digest(%(source)s || '/' || %(class)s || '/' || %(subclass)s || '/' || %(elems_sig)s, 'sha256') from 1 for 16), 'hex') || '}')::uuid, "
            sql_marker += u"%(source)s, %(class)s, %(item)s, %(lat)s, %(lon)s, %(elems)s::jsonb[], %(fixes)s::jsonb[], %(subtitle)s) "
            sql_marker += u"ON CONFLICT (uuid) DO "
            sql_marker += u"UPDATE SET item = %(item)s, lat = %(lat)s, lon = %(lon)s, elems = %(elems)s::jsonb[], fixes = %(fixes)s::jsonb[], subtitle = %(subtitle)s "
            sql_marker += u"WHERE marker.uuid = ('{' || encode(substring(digest(%(source)s || '/' || %(class)s || '/' || %(subclass)s || '/' || %(elems_sig)s, 'sha256') from 1 for 16), 'hex') || '}')::uuid AND "
            sql_marker += u"      marker.source = %(source)s AND marker.class = %(class)s AND "
            sql_marker += u"      (marker.item IS DISTINCT FROM %(item)s OR marker.lat IS DISTINCT FROM %(lat)s OR marker.lon IS DISTINCT FROM %(lon)s OR marker.elems IS DISTINCT FROM %(elems)s::jsonb[] OR marker.fixes IS DISTINCT FROM %(fixes)s::jsonb[] OR marker.subtitle IS DISTINCT FROM %(subtitle)s) "
            sql_marker += u"RETURNING uuid"

            for location in self._error_locations:
                lat = float(location["lat"])
                lon = float(location["lon"])

                params = {
                    "source":
                    self._source_id,
                    "class":
                    self._class_id,
                    "subclass":
                    self._class_sub,
                    "item":
                    self._class_item[self._class_id],
                    "lat":
                    lat,
                    "lon":
                    lon,
                    "elems_sig":
                    '_'.join(
                        map(lambda elem: elem['type'] + str(elem['id']),
                            self._error_elements)),
                    "elems":
                    list(map(lambda elem: json.dumps(elem), elems))
                    if elems else None,
                    "fixes":
                    list(map(lambda fix: json.dumps(fix), fixes))
                    if fixes else None,
                    "subtitle":
                    self._error_texts,
                }

                execute_sql(self._dbcurs, sql_uuid, params)
                r = self._dbcurs.fetchone()
                if r and r[0]:
                    self.all_uuid[self._class_id].append(r[0])

                execute_sql(self._dbcurs, sql_marker, params)
                self._dbcurs.fetchone()

        elif name in [u"node", u"way", u"relation", u"infos"]:
            if self.elem_mode == "info":
                self._elem[u"tag"] = self._elem_tags
                self._error_elements.append(self._elem)
            else:
                self._elem[u"create"] = self._fix_create
                self._elem[u"modify"] = self._fix_modify
                self._elem[u"delete"] = self._fix_delete
                self._fix.append(self._elem)

        elif name == u"class":
            self.all_uuid[self._class_id] = []

            # Commit class update on its own transaction. Avoid lock the class table and block other updates.
            dbconn = utils.get_dbconn()
            dbcurs = dbconn.cursor()
            sql = u"INSERT INTO class (class, item, title, level, tags, detail, fix, trap, example, source, resource, timestamp) "
            sql += u"VALUES (%(class)s, %(item)s, %(title)s, %(level)s, %(tags)s, %(detail)s, %(fix)s, %(trap)s, %(example)s, %(source)s, %(resource)s, %(timestamp)s) "
            sql += u"ON CONFLICT (item, class) DO "
            sql += u"UPDATE SET title = %(title)s, level = %(level)s, tags = %(tags)s, detail = %(detail)s, fix = %(fix)s, trap = %(trap)s, example = %(example)s, source = %(source)s, resource = %(resource)s, timestamp = %(timestamp)s "
            sql += u"WHERE class.class = %(class)s AND class.item = %(item)s AND class.timestamp < %(timestamp)s AND "
            sql += u"      (class.title IS DISTINCT FROM %(title)s OR class.level IS DISTINCT FROM %(level)s OR class.tags IS DISTINCT FROM %(tags)s::varchar[] OR class.detail IS DISTINCT FROM %(detail)s OR class.fix IS DISTINCT FROM %(fix)s OR class.trap IS DISTINCT FROM %(trap)s OR class.example IS DISTINCT FROM %(example)s OR class.source IS DISTINCT FROM %(source)s OR class.resource IS DISTINCT FROM %(resource)s)"
            execute_sql(
                dbcurs, sql, {
                    'class': self._class_id,
                    'item': self._class_item[self._class_id],
                    'title': self._class_title,
                    'level': self._class_level,
                    'tags': self._class_tags,
                    'detail': self._class_detail or None,
                    'fix': self._class_fix or None,
                    'trap': self._class_trap or None,
                    'example': self._class_example or None,
                    'source': self._class_source or None,
                    'resource': self._class_resource or None,
                    'timestamp': utils.pg_escape(self.ts),
                })
            dbconn.commit()
            dbconn.close()

            sql = u"INSERT INTO dynpoi_class (source, class, item, timestamp) "
            sql += u"VALUES (%(source)s, %(class)s, %(item)s, %(timestamp)s)"
            sql += u"ON CONFLICT (source, class) DO "
            sql += u"UPDATE SET item = %(item)s, timestamp = %(timestamp)s "
            sql += u"WHERE dynpoi_class.source = %(source)s AND dynpoi_class.class = %(class)s"
            execute_sql(
                self._dbcurs, sql, {
                    'source': self._source_id,
                    'class': self._class_id,
                    'item': self._class_item[self._class_id],
                    'timestamp': utils.pg_escape(self.ts),
                })

        elif name == u"fixes":
            self.elem_mode = "info"
        elif name == u"fix" and self.element_stack[-1] == u"fixes":
            self._fixes.append(self._fix)