String für SQL Abfrage aufbereiten

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
osmi
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 08:43

Hallo,

ich arbeite gerade an einem kleinem Dialogfenster, das je nach Eingabeparameter eine SQL Abfrage aus vorgefertigten Teilen generiert. In einem der Eingabefelder sollen die Spalten angegeben werden, welche in die Abfrage übernommen werden. Die Eingabe muss durch Beistriche getrennt werden und könnte etwa wie nachfolgend aussehen:

Code: Alles auswählen

spalte-1, Spalte2, nocheinespalte
Ich möchte nun alle Spalten unter einfache Hochkomma setzen und vor der ersten Spalte einen Beistrich hinzufügen, falls dieser in der Eingabe fehlt:

Code: Alles auswählen

, 'spalte-1', 'Spalte2', 'nocheinespalte'
Außerdem soll ein möglicher Beistrich am Ende der Eingabe entfernt werden.

Was ist denn für mein Anliegen das Mittel der Wahl? Ein regulärer Ausdruck? Wie könnte dieser aussehen?

Vielen Dank!
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@osmi: es sieht so aus, als wolltest Du in irgendeiner Form Programmcode generieren wollen. Beistriche und Anführungszeichen formatiert man normalerweise nicht in Eingaben. Die natürliche Vorgehensweise wäre, die Eingabe der Spalten in eine Liste zu überführen und mit dieser weiter zu arbeiten. Was hast Du denn genau vor, zu tun? Beschreibe Dein eigentliches Problem und nicht ein Problem, das bei der Umsetzung Deiner Lösung auftritt.
BlackJack

Benutzereingaben von Spaltennamen zum Zusammenbauen einer SQL-Anfrage als Zeichenkette? Sieht noch jemand die SQL-Injection kommen. :-)

@osmi: Gar keine gute Idee! Warum muss der Benutzer Spaltennamen eingeben können? Warum werden ihm nicht einfach die vorhandenen Spaltennamen zur Auswahl angeboten, damit er keine bösen Sachen anstellen kann? Selbst wenn man dem Benutzer nichts böses unterstellt, ist das wesentlich weniger fehleranfällig.
osmi
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 08:43

Hallo Sirius und BlackJack, hier ein bisschen etwas zu den Hintergründen:

In der freien GIS Software QGIS gibt es seit einiger Zeit sogenannte virtuelle Layer. Dieser basieren auf SpatiaLite/SQLite und erlauben es, Abfragen bzw. geographische Analysen dynamisch zu erstellen. Mit nachfolgendem SQL Statement wir etwa für jedes Polygon des Layers "gebaeude" ein Punkt generiert. Werden Gebäude entfernt, ergänzt oder editiert, ändern sich auch die Punkte.

Code: Alles auswählen

SELECT 
	rowid AS 'gid' /*:int*/,
	ST_PointOnSurface(geometry) AS geom /*:point:31256:*/
FROM 'gebaeude';
Bild

Viele GIS Anwender (v.a. Anfänger) wollen aber oft nur einfache Analysen erstellen und sind mit SQL überfordert. Um diesen Nutzern QGIS näher zu bringen, möchte ich mithilfe der 'Processing Toolbox' Skripte erstellen, welche virtuelle Layer über eine graphische Oberfläche erzeugen. Mein erstes Testskript (ST_PointOnSurface) ist praktisch fertigt, lediglich fehlt die Möglichkeit Attribute aus dem Eingabelayer (z.B. "gebaeude") in die Ausgabepunkte zu übernehmen (siehe "Attributes to keep").

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# ----- define interface -----
##Virtual Layers (QGIS 2.x)=group
##Point on surface (ST_PointOnSurface)=name
##Input_layer=vector
##Output_layer=string vl_
##Unique_identifier_column=string gid
##Geometry_column=string geom
##Coordinate_reference_system=crs
##Attributes_to_keep_(comma_separated_list)=string

from qgis.core import QgsVectorLayer, QgsMapLayerRegistry

inptlyr = processing.getObject(Input_layer)
otptlyr = Output_layer
uic = Unique_identifier_column
gmc = Geometry_column
crs = Coordinate_reference_system
crs = crs[5:]
att = Attributes_to_keep_(comma_separated_list)

query = """SELECT
	rowid AS '""" + uic + """' /*:int*/,
	ST_PointOnSurface(geometry) AS '""" + gmc + """' /*:point:""" + crs + """*/
FROM '""" + inptlyr.name() + """';
"""

vlayer = QgsVectorLayer( "?query={}".format(query), otptlyr, "virtual" )
QgsMapLayerRegistry.instance().addMapLayer(vlayer)
Bild

SQL-Injection sind in diesem Fall kein Thema. Es steht ja jedem Anwender frei die SQL Eingabe ('Create a virtual layer') zu öffnen und darin herumzufuhrwerken.

Hier noch ein Link zu Python Skripten in der "Processing Toolbox":

http://docs.qgis.org/2.14/de/docs/user_ ... ripts.html
Zuletzt geändert von Anonymous am Samstag 18. Februar 2017, 13:40, insgesamt 1-mal geändert.
Grund: Quelltext in Codebox-Tags gesetzt.
osmi
User
Beiträge: 5
Registriert: Samstag 18. Februar 2017, 08:43

Die Idee, die benötigten Attribute als String zu übernehmen stammt aus dem "PostGIS Geoprocessing Tools" Plugin:

Bild

Die Attribute des Eingabelayers zur Auswahl anzubieten ist wohl - im Rahmen der "Processing Toolbox" - nicht ganz trivial. Mit

Code: Alles auswählen

##Attributes_to_keep = field Input_layer
könnte man mittels Drop-Down-Liste auf ein einzelnes Attribut des Eingabelayers zugreifen. Die Auswahl mehrerer Layer über Checkboxen ist aber m.W. nicht möglich.
Antworten