Skip to content

Commit b7d75af

Browse files
authored
Use GET & POST appropriately according to InfluxDB documentation (influxdata#608)
* Use GET & POST appropriately according to InfluxDB documentation From 'https://docs.influxdata.com/influxdb/v1.5/tools/api/#verb-usage', certain queries should be POST (where previously they have been GET) * Appease flake8
1 parent a47c801 commit b7d75af

File tree

5 files changed

+84
-32
lines changed

5 files changed

+84
-32
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99
- Finally add a CHANGELOG.md to communicate breaking changes (#598)
1010
- Test multiple versions of InfluxDB in travis
1111
### Changed
12+
- Update POST/GET requests to follow verb guidelines from InfluxDB documentation
1213
- Update test suite to support InfluxDB v1.3.9, v1.4.2, and v1.5.4
1314
- Fix performance degradation when removing NaN values via line protocol (#592)
1415
### Removed

examples/tutorial_sine_wave.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def main(host='localhost', port=8086):
4343
time.sleep(3)
4444

4545
query = 'SELECT * FROM foobar'
46-
print("Queying data: " + query)
46+
print("Querying data: " + query)
4747
result = client.query(query, database=DBNAME)
4848
print("Result: {0}".format(result))
4949

influxdb/client.py

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,8 @@ def query(self,
350350
database=None,
351351
raise_errors=True,
352352
chunked=False,
353-
chunk_size=0):
353+
chunk_size=0,
354+
method="GET"):
354355
"""Send a query to InfluxDB.
355356
356357
:param query: the actual query string
@@ -384,6 +385,9 @@ def query(self,
384385
:param chunk_size: Size of each chunk to tell InfluxDB to use.
385386
:type chunk_size: int
386387
388+
:param method: the HTTP method for the request, defaults to GET
389+
:type method: str
390+
387391
:returns: the queried data
388392
:rtype: :class:`~.ResultSet`
389393
"""
@@ -401,9 +405,12 @@ def query(self,
401405
if chunk_size > 0:
402406
params['chunk_size'] = chunk_size
403407

408+
if query.lower().startswith("select ") and " into " in query.lower():
409+
method = "POST"
410+
404411
response = self.request(
405412
url="query",
406-
method='GET',
413+
method=method,
407414
params=params,
408415
data=None,
409416
expected_response_code=expected_response_code
@@ -568,15 +575,17 @@ def create_database(self, dbname):
568575
:param dbname: the name of the database to create
569576
:type dbname: str
570577
"""
571-
self.query("CREATE DATABASE {0}".format(quote_ident(dbname)))
578+
self.query("CREATE DATABASE {0}".format(quote_ident(dbname)),
579+
method="POST")
572580

573581
def drop_database(self, dbname):
574582
"""Drop a database from InfluxDB.
575583
576584
:param dbname: the name of the database to drop
577585
:type dbname: str
578586
"""
579-
self.query("DROP DATABASE {0}".format(quote_ident(dbname)))
587+
self.query("DROP DATABASE {0}".format(quote_ident(dbname)),
588+
method="POST")
580589

581590
def get_list_measurements(self):
582591
"""Get the list of measurements in InfluxDB.
@@ -602,7 +611,8 @@ def drop_measurement(self, measurement):
602611
:param measurement: the name of the measurement to drop
603612
:type measurement: str
604613
"""
605-
self.query("DROP MEASUREMENT {0}".format(quote_ident(measurement)))
614+
self.query("DROP MEASUREMENT {0}".format(quote_ident(measurement)),
615+
method="POST")
606616

607617
def create_retention_policy(self, name, duration, replication,
608618
database=None, default=False):
@@ -634,11 +644,11 @@ def create_retention_policy(self, name, duration, replication,
634644
if default is True:
635645
query_string += " DEFAULT"
636646

637-
self.query(query_string)
647+
self.query(query_string, method="POST")
638648

639649
def alter_retention_policy(self, name, database=None,
640650
duration=None, replication=None, default=None):
641-
"""Mofidy an existing retention policy for a database.
651+
"""Modify an existing retention policy for a database.
642652
643653
:param name: the name of the retention policy to modify
644654
:type name: str
@@ -671,7 +681,7 @@ def alter_retention_policy(self, name, database=None,
671681
if default is True:
672682
query_string += " DEFAULT"
673683

674-
self.query(query_string)
684+
self.query(query_string, method="POST")
675685

676686
def drop_retention_policy(self, name, database=None):
677687
"""Drop an existing retention policy for a database.
@@ -685,7 +695,7 @@ def drop_retention_policy(self, name, database=None):
685695
query_string = (
686696
"DROP RETENTION POLICY {0} ON {1}"
687697
).format(quote_ident(name), quote_ident(database or self._database))
688-
self.query(query_string)
698+
self.query(query_string, method="POST")
689699

690700
def get_list_retention_policies(self, database=None):
691701
"""Get the list of retention policies for a database.
@@ -751,16 +761,16 @@ def create_user(self, username, password, admin=False):
751761
quote_ident(username), quote_literal(password))
752762
if admin:
753763
text += ' WITH ALL PRIVILEGES'
754-
self.query(text)
764+
self.query(text, method="POST")
755765

756766
def drop_user(self, username):
757767
"""Drop a user from InfluxDB.
758768
759769
:param username: the username to drop
760770
:type username: str
761771
"""
762-
text = "DROP USER {0}".format(quote_ident(username))
763-
self.query(text)
772+
text = "DROP USER {0}".format(quote_ident(username), method="POST")
773+
self.query(text, method="POST")
764774

765775
def set_user_password(self, username, password):
766776
"""Change the password of an existing user.
@@ -796,7 +806,7 @@ def delete_series(self, database=None, measurement=None, tags=None):
796806
tag_eq_list = ["{0}={1}".format(quote_ident(k), quote_literal(v))
797807
for k, v in tags.items()]
798808
query_str += ' WHERE ' + ' AND '.join(tag_eq_list)
799-
self.query(query_str, database=database)
809+
self.query(query_str, database=database, method="POST")
800810

801811
def grant_admin_privileges(self, username):
802812
"""Grant cluster administration privileges to a user.
@@ -808,7 +818,7 @@ def grant_admin_privileges(self, username):
808818
and manage users.
809819
"""
810820
text = "GRANT ALL PRIVILEGES TO {0}".format(quote_ident(username))
811-
self.query(text)
821+
self.query(text, method="POST")
812822

813823
def revoke_admin_privileges(self, username):
814824
"""Revoke cluster administration privileges from a user.
@@ -820,7 +830,7 @@ def revoke_admin_privileges(self, username):
820830
and manage users.
821831
"""
822832
text = "REVOKE ALL PRIVILEGES FROM {0}".format(quote_ident(username))
823-
self.query(text)
833+
self.query(text, method="POST")
824834

825835
def grant_privilege(self, privilege, database, username):
826836
"""Grant a privilege on a database to a user.
@@ -836,7 +846,7 @@ def grant_privilege(self, privilege, database, username):
836846
text = "GRANT {0} ON {1} TO {2}".format(privilege,
837847
quote_ident(database),
838848
quote_ident(username))
839-
self.query(text)
849+
self.query(text, method="POST")
840850

841851
def revoke_privilege(self, privilege, database, username):
842852
"""Revoke a privilege on a database from a user.
@@ -852,7 +862,7 @@ def revoke_privilege(self, privilege, database, username):
852862
text = "REVOKE {0} ON {1} FROM {2}".format(privilege,
853863
quote_ident(database),
854864
quote_ident(username))
855-
self.query(text)
865+
self.query(text, method="POST")
856866

857867
def get_list_privileges(self, username):
858868
"""Get the list of all privileges granted to given user.

influxdb/tests/client_test.py

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,29 @@ def test_query(self):
439439
[{'value': 0.64, 'time': '2009-11-10T23:00:00Z'}]
440440
)
441441

442+
def test_select_into_post(self):
443+
"""Test SELECT.*INTO is POSTed."""
444+
example_response = (
445+
'{"results": [{"series": [{"measurement": "sdfsdfsdf", '
446+
'"columns": ["time", "value"], "values": '
447+
'[["2009-11-10T23:00:00Z", 0.64]]}]}, {"series": '
448+
'[{"measurement": "cpu_load_short", "columns": ["time", "value"], '
449+
'"values": [["2009-11-10T23:00:00Z", 0.64]]}]}]}'
450+
)
451+
452+
with requests_mock.Mocker() as m:
453+
m.register_uri(
454+
requests_mock.POST,
455+
"http://localhost:8086/query",
456+
text=example_response
457+
)
458+
rs = self.cli.query('select * INTO newmeas from foo')
459+
460+
self.assertListEqual(
461+
list(rs[0].get_points()),
462+
[{'value': 0.64, 'time': '2009-11-10T23:00:00Z'}]
463+
)
464+
442465
@unittest.skip('Not implemented for 0.9')
443466
def test_query_chunked(self):
444467
"""Test chunked query for TestInfluxDBClient object."""
@@ -495,7 +518,7 @@ def test_create_database(self):
495518
"""Test create database for TestInfluxDBClient object."""
496519
with requests_mock.Mocker() as m:
497520
m.register_uri(
498-
requests_mock.GET,
521+
requests_mock.POST,
499522
"http://localhost:8086/query",
500523
text='{"results":[{}]}'
501524
)
@@ -509,7 +532,7 @@ def test_create_numeric_named_database(self):
509532
"""Test create db w/numeric name for TestInfluxDBClient object."""
510533
with requests_mock.Mocker() as m:
511534
m.register_uri(
512-
requests_mock.GET,
535+
requests_mock.POST,
513536
"http://localhost:8086/query",
514537
text='{"results":[{}]}'
515538
)
@@ -529,7 +552,7 @@ def test_drop_database(self):
529552
"""Test drop database for TestInfluxDBClient object."""
530553
with requests_mock.Mocker() as m:
531554
m.register_uri(
532-
requests_mock.GET,
555+
requests_mock.POST,
533556
"http://localhost:8086/query",
534557
text='{"results":[{}]}'
535558
)
@@ -543,7 +566,7 @@ def test_drop_measurement(self):
543566
"""Test drop measurement for TestInfluxDBClient object."""
544567
with requests_mock.Mocker() as m:
545568
m.register_uri(
546-
requests_mock.GET,
569+
requests_mock.POST,
547570
"http://localhost:8086/query",
548571
text='{"results":[{}]}'
549572
)
@@ -557,7 +580,7 @@ def test_drop_numeric_named_database(self):
557580
"""Test drop numeric db for TestInfluxDBClient object."""
558581
with requests_mock.Mocker() as m:
559582
m.register_uri(
560-
requests_mock.GET,
583+
requests_mock.POST,
561584
"http://localhost:8086/query",
562585
text='{"results":[{}]}'
563586
)
@@ -615,7 +638,7 @@ def test_create_retention_policy_default(self):
615638

616639
with requests_mock.Mocker() as m:
617640
m.register_uri(
618-
requests_mock.GET,
641+
requests_mock.POST,
619642
"http://localhost:8086/query",
620643
text=example_response
621644
)
@@ -635,7 +658,7 @@ def test_create_retention_policy(self):
635658

636659
with requests_mock.Mocker() as m:
637660
m.register_uri(
638-
requests_mock.GET,
661+
requests_mock.POST,
639662
"http://localhost:8086/query",
640663
text=example_response
641664
)
@@ -655,7 +678,7 @@ def test_alter_retention_policy(self):
655678

656679
with requests_mock.Mocker() as m:
657680
m.register_uri(
658-
requests_mock.GET,
681+
requests_mock.POST,
659682
"http://localhost:8086/query",
660683
text=example_response
661684
)
@@ -695,7 +718,7 @@ def test_drop_retention_policy(self):
695718

696719
with requests_mock.Mocker() as m:
697720
m.register_uri(
698-
requests_mock.GET,
721+
requests_mock.POST,
699722
"http://localhost:8086/query",
700723
text=example_response
701724
)
@@ -879,7 +902,7 @@ def test_grant_admin_privileges(self):
879902

880903
with requests_mock.Mocker() as m:
881904
m.register_uri(
882-
requests_mock.GET,
905+
requests_mock.POST,
883906
"http://localhost:8086/query",
884907
text=example_response
885908
)
@@ -903,7 +926,7 @@ def test_revoke_admin_privileges(self):
903926

904927
with requests_mock.Mocker() as m:
905928
m.register_uri(
906-
requests_mock.GET,
929+
requests_mock.POST,
907930
"http://localhost:8086/query",
908931
text=example_response
909932
)
@@ -927,7 +950,7 @@ def test_grant_privilege(self):
927950

928951
with requests_mock.Mocker() as m:
929952
m.register_uri(
930-
requests_mock.GET,
953+
requests_mock.POST,
931954
"http://localhost:8086/query",
932955
text=example_response
933956
)
@@ -951,7 +974,7 @@ def test_revoke_privilege(self):
951974

952975
with requests_mock.Mocker() as m:
953976
m.register_uri(
954-
requests_mock.GET,
977+
requests_mock.POST,
955978
"http://localhost:8086/query",
956979
text=example_response
957980
)

influxdb/tests/server_tests/client_test_with_server.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ def test_drop_user(self):
211211
self.assertEqual(users, [])
212212

213213
def test_drop_user_nonexisting(self):
214-
"""Test dropping a nonexistant user."""
214+
"""Test dropping a nonexistent user."""
215215
with self.assertRaises(InfluxDBClientError) as ctx:
216216
self.cli.drop_user('test')
217217
self.assertIn('user not found',
@@ -383,6 +383,24 @@ def test_write_multiple_points_different_series(self):
383383
]]
384384
)
385385

386+
def test_select_into_as_post(self):
387+
"""Test SELECT INTO is POSTed."""
388+
self.assertIs(True, self.cli.write_points(dummy_points))
389+
time.sleep(1)
390+
rsp = self.cli.query('SELECT * INTO "newmeas" FROM "memory"')
391+
rsp = self.cli.query('SELECT * FROM "newmeas"')
392+
lrsp = list(rsp)
393+
394+
self.assertEqual(
395+
lrsp,
396+
[[
397+
{'value': 33,
398+
'time': '2009-11-10T23:01:35Z',
399+
"host": "server01",
400+
"region": "us-west"}
401+
]]
402+
)
403+
386404
@unittest.skip("Broken as of 0.9.0")
387405
def test_write_multiple_points_different_series_DF(self):
388406
"""Test write multiple points using dataframe to different series."""

0 commit comments

Comments
 (0)