Skip to content

Commit afcfd25

Browse files
clslgrncxginn8
authored andcommitted
Parameter binding for client's query() method (influxdata#678)
* add bind_params to query * tutorial for bind_params
1 parent 02865ae commit afcfd25

File tree

6 files changed

+46
-5
lines changed

6 files changed

+46
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
77
## [Unreleased]
88

99
### Added
10+
- query() now accepts a bind_params argument for parameter binding (#678 thx @clslgrnc)
1011

1112
### Changed
1213
- Update test suite to add support for Python 3.7 and InfluxDB v1.6.4 and 1.7.4 (#692 thx @clslgrnc)

examples/tutorial.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ def main(host='localhost', port=8086):
1313
dbname = 'example'
1414
dbuser = 'smly'
1515
dbuser_password = 'my_secret_password'
16-
query = 'select value from cpu_load_short;'
16+
query = 'select Float_value from cpu_load_short;'
17+
query_where = 'select Int_value from cpu_load_short where host=$host;'
18+
bind_params = {'host': 'server01'}
1719
json_body = [
1820
{
1921
"measurement": "cpu_load_short",
@@ -50,6 +52,11 @@ def main(host='localhost', port=8086):
5052

5153
print("Result: {0}".format(result))
5254

55+
print("Querying data: " + query_where)
56+
result = client.query(query_where, bind_params=bind_params)
57+
58+
print("Result: {0}".format(result))
59+
5360
print("Switch user: " + user)
5461
client.switch_user(user, password)
5562

influxdb/_dataframe_client.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ def write_points(self,
142142
def query(self,
143143
query,
144144
params=None,
145+
bind_params=None,
145146
epoch=None,
146147
expected_response_code=200,
147148
database=None,
@@ -153,8 +154,18 @@ def query(self,
153154
"""
154155
Query data into a DataFrame.
155156
157+
.. danger::
158+
In order to avoid injection vulnerabilities (similar to `SQL
159+
injection <https://www.owasp.org/index.php/SQL_Injection>`_
160+
vulnerabilities), do not directly include untrusted data into the
161+
``query`` parameter, use ``bind_params`` instead.
162+
156163
:param query: the actual query string
157164
:param params: additional parameters for the request, defaults to {}
165+
:param bind_params: bind parameters for the query:
166+
any variable in the query written as ``'$var_name'`` will be
167+
replaced with ``bind_params['var_name']``. Only works in the
168+
``WHERE`` clause and takes precedence over ``params['params']``
158169
:param epoch: response timestamps to be in epoch format either 'h',
159170
'm', 's', 'ms', 'u', or 'ns',defaults to `None` which is
160171
RFC3339 UTC format with nanosecond precision
@@ -172,6 +183,7 @@ def query(self,
172183
:rtype: :class:`~.ResultSet`
173184
"""
174185
query_args = dict(params=params,
186+
bind_params=bind_params,
175187
epoch=epoch,
176188
expected_response_code=expected_response_code,
177189
raise_errors=raise_errors,

influxdb/client.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ def _read_chunked_response(response, raise_errors=True):
345345
def query(self,
346346
query,
347347
params=None,
348+
bind_params=None,
348349
epoch=None,
349350
expected_response_code=200,
350351
database=None,
@@ -354,13 +355,25 @@ def query(self,
354355
method="GET"):
355356
"""Send a query to InfluxDB.
356357
358+
.. danger::
359+
In order to avoid injection vulnerabilities (similar to `SQL
360+
injection <https://www.owasp.org/index.php/SQL_Injection>`_
361+
vulnerabilities), do not directly include untrusted data into the
362+
``query`` parameter, use ``bind_params`` instead.
363+
357364
:param query: the actual query string
358365
:type query: str
359366
360367
:param params: additional parameters for the request,
361368
defaults to {}
362369
:type params: dict
363370
371+
:param bind_params: bind parameters for the query:
372+
any variable in the query written as ``'$var_name'`` will be
373+
replaced with ``bind_params['var_name']``. Only works in the
374+
``WHERE`` clause and takes precedence over ``params['params']``
375+
:type bind_params: dict
376+
364377
:param epoch: response timestamps to be in epoch format either 'h',
365378
'm', 's', 'ms', 'u', or 'ns',defaults to `None` which is
366379
RFC3339 UTC format with nanosecond precision
@@ -394,6 +407,11 @@ def query(self,
394407
if params is None:
395408
params = {}
396409

410+
if bind_params is not None:
411+
params_dict = json.loads(params.get('params', '{}'))
412+
params_dict.update(bind_params)
413+
params['params'] = json.dumps(params_dict)
414+
397415
params['q'] = query
398416
params['db'] = database or self._database
399417

influxdb/tests/dataframe_client_test.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -894,10 +894,11 @@ def test_multiquery_into_dataframe(self):
894894
expected = [{'cpu_load_short': pd1}, {'cpu_load_short': pd2}]
895895

896896
cli = DataFrameClient('host', 8086, 'username', 'password', 'db')
897-
iql = "SELECT value FROM cpu_load_short WHERE region='us-west';"\
898-
"SELECT count(value) FROM cpu_load_short WHERE region='us-west'"
897+
iql = "SELECT value FROM cpu_load_short WHERE region=$region;"\
898+
"SELECT count(value) FROM cpu_load_short WHERE region=$region"
899+
bind_params = {'region': 'us-west'}
899900
with _mocked_session(cli, 'GET', 200, data):
900-
result = cli.query(iql)
901+
result = cli.query(iql, bind_params=bind_params)
901902
for r, e in zip(result, expected):
902903
for k in e:
903904
assert_frame_equal(e[k], r[k])

influxdb/tests/server_tests/client_test_with_server.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,9 @@ def test_write_points_batch(self):
440440
batch_size=2)
441441
time.sleep(5)
442442
net_in = self.cli.query("SELECT value FROM network "
443-
"WHERE direction='in'").raw
443+
"WHERE direction=$dir",
444+
bind_params={'dir': 'in'}
445+
).raw
444446
net_out = self.cli.query("SELECT value FROM network "
445447
"WHERE direction='out'").raw
446448
cpu = self.cli.query("SELECT value FROM cpu_usage").raw

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy