sql-testing-tools 0.2.4a0__tar.gz → 0.2.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sql_testing_tools-0.2.6/PKG-INFO +178 -0
- sql_testing_tools-0.2.6/README.md +168 -0
- sql_testing_tools-0.2.6/setup.py +17 -0
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools/BaseAccess.py +54 -37
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools/Helper.py +6 -95
- sql_testing_tools-0.2.6/sql_testing_tools.egg-info/PKG-INFO +178 -0
- sql_testing_tools-0.2.4a0/PKG-INFO +0 -127
- sql_testing_tools-0.2.4a0/README.md +0 -117
- sql_testing_tools-0.2.4a0/setup.py +0 -27
- sql_testing_tools-0.2.4a0/sql_testing_tools.egg-info/PKG-INFO +0 -127
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/setup.cfg +0 -0
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools/TokenProcessing.py +0 -0
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools/__init__.py +0 -0
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools.egg-info/SOURCES.txt +0 -0
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools.egg-info/dependency_links.txt +0 -0
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools.egg-info/requires.txt +0 -0
- {sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: sql_testing_tools
|
|
3
|
+
Version: 0.2.6
|
|
4
|
+
Description-Content-Type: text/markdown
|
|
5
|
+
Requires-Dist: sqlparse>=0.5.1
|
|
6
|
+
Requires-Dist: requests>=2.32.3
|
|
7
|
+
Dynamic: description
|
|
8
|
+
Dynamic: description-content-type
|
|
9
|
+
Dynamic: requires-dist
|
|
10
|
+
|
|
11
|
+
A library that normalizes simple SQL queries and compares them first by equality of the normalized string and then using the cosette API.
|
|
12
|
+
|
|
13
|
+
#### [Beta in Development!]
|
|
14
|
+
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-build.yml)
|
|
15
|
+
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-unittests.yml)
|
|
16
|
+
|
|
17
|
+
- Submit bug reports and features requests at: https://github.com/ValentinHerrmann/sql_testing_tools
|
|
18
|
+
- PyPi-Package available at: https://pypi.org/project/sql-testing-tools/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## Getting started
|
|
22
|
+
|
|
23
|
+
### Imports
|
|
24
|
+
``` python
|
|
25
|
+
# ensure to always use the latest version of sql_testing_tools
|
|
26
|
+
import os
|
|
27
|
+
os.system('pip install -U sql_testing_tools')
|
|
28
|
+
|
|
29
|
+
# import sql_testing_tools
|
|
30
|
+
import sql_testing_tools.BaseAccess as Ba
|
|
31
|
+
import sql_testing_tools.Helper as He
|
|
32
|
+
|
|
33
|
+
# import unittest and create TestClass
|
|
34
|
+
import unittest
|
|
35
|
+
class TestClass(unittest.TestCase):
|
|
36
|
+
# Ba.setDBName(...)
|
|
37
|
+
# ...
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Choosing a database
|
|
41
|
+
|
|
42
|
+
On top level of your test class, set the SQLite database you want to use.
|
|
43
|
+
|
|
44
|
+
**Option 1:** Use the predefined ones from [dbiu_databases](https://github.com/ValentinHerrmann/dbiu_databases) which are based on [datenbanken-im-unterricht.de](https://www.datenbanken-im-unterricht.de/catalog.php)
|
|
45
|
+
|
|
46
|
+
``` python
|
|
47
|
+
# with DB name (preferred)
|
|
48
|
+
# --> only available if current dbiu_databases version has been imported to sql_testing_tools
|
|
49
|
+
Ba.setDBName("dbiu.bayern")
|
|
50
|
+
|
|
51
|
+
# or with dbiu_databases version number
|
|
52
|
+
# --> available as soon as a dbiu_databases version has been published on PyPi
|
|
53
|
+
Ba.setDBName(2)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Currently supported to use with DB name are:
|
|
57
|
+
1. `dbiu.bahn`: https://www.dbiu.de/bahn
|
|
58
|
+
2. `dbiu.bayern`: https://www.dbiu.de/bayern
|
|
59
|
+
3. `dbiu.bundestag`: https://www.datenbanken-im-unterricht.de/downloads/bundestag.zip
|
|
60
|
+
4. `dbiu.bundestag_einfach`: https://www.dbiu.de/bundestagsmitglieder
|
|
61
|
+
5. `dbiu.film_fernsehen`: https://www.dbiu.de/filmundfernsehen
|
|
62
|
+
6. `dbiu.haushaltsausstattung`: https://www.dbiu.de/haushaltsausstattung
|
|
63
|
+
7. `dbiu.straftaten`: https://www.datenbanken-im-unterricht.de/downloads/kriminalstatistik-erweitert.zip
|
|
64
|
+
8. `dbiu.straftaten_einfach`: https://www.dbiu.de/kriminalstatistik
|
|
65
|
+
9. `dbiu.kunstsammlung`: https://www.dbiu.de/kunstsammlung
|
|
66
|
+
10. `dbiu.ladepunkte`: https://www.dbiu.de/ladepunkte
|
|
67
|
+
11. `dbiu.laenderspiele`: https://www.dbiu.de/laenderspiele
|
|
68
|
+
12. `dbiu.lebensmittel`: https://www.dbiu.de/lebensmittel
|
|
69
|
+
13. `dbiu.schulstatistik`: https://www.dbiu.de/schulstatistik
|
|
70
|
+
14. `dbiu.studierende`: https://www.dbiu.de/studierende
|
|
71
|
+
15. `dbiu.unfallstatistik`: https://www.dbiu.de/unfallstatistik
|
|
72
|
+
16. `dbiu.videospiele_einfach`: https://www.dbiu.de/videospiele
|
|
73
|
+
17. `dbiu.videospiele`: https://www.dbiu.de/videospiele2
|
|
74
|
+
18. `dbiu.wetterdaten`: https://www.dbiu.de/wetterdaten
|
|
75
|
+
|
|
76
|
+
**Option 2:** Use your own SQLite database with relative path starting at the working dir of your test repository.
|
|
77
|
+
``` python
|
|
78
|
+
Ba.setDBName("databases/bayern.db")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Available testing features
|
|
82
|
+
|
|
83
|
+
The following methods are available for use in test methods:
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
**Run the query to find out if syntax/database errors occur.**
|
|
87
|
+
``` python
|
|
88
|
+
try:
|
|
89
|
+
Ba.runAndGetStringTable_fromFile("sqlfile.sql")
|
|
90
|
+
except Exception as e:
|
|
91
|
+
# the execution failed (usually due to syntax or database errors)
|
|
92
|
+
self.fail(e)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
**Set sql files to be compared (optional).**
|
|
98
|
+
The sql strings will be normalized and used or all following methods (to improve performance) until new files are specified. All check...() functions call setup(...) as first step. If one argument is `""` or `None` the corresponding file is not changed. Therefore calling the check...() functions without arguments does not change the sql files that are compared.
|
|
99
|
+
``` python
|
|
100
|
+
# Raises an Exception if one of the files is empty.
|
|
101
|
+
setup("sqlfile.sql","solution.sql")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Compared single parts of a sql query**
|
|
105
|
+
Call without arguments to keep the last normalized sql strings (and improve performance) and with one or two sql file paths to load and normalize new queries.
|
|
106
|
+
Each check was successfull if `""` is returned. Returns a German error message if not.
|
|
107
|
+
Each method compares the normalized string between the start keyword and the next keyword or ;
|
|
108
|
+
``` python
|
|
109
|
+
|
|
110
|
+
res = He.checkColumns() # starts at "SELECT"
|
|
111
|
+
res = He.checkTables() # starts at "FROM"
|
|
112
|
+
res = He.checkCondition() # starts at "WHERE"
|
|
113
|
+
res = He.checkOrder() # starts at "ORDER BY"
|
|
114
|
+
res = He.checkGroup() # starts at "GROUP BY"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
In special cases where you'd like to start and stop at individual keywords for comparison use this directly:
|
|
118
|
+
``` python
|
|
119
|
+
# Can not be called with new sql files. If needed call setup(...) before.
|
|
120
|
+
res = checkKeywords("startKeyword",["end","keywords"])
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Compares equality of the full normalized sql strings and if not equal uses the Cosette API (cosette.cs.washington.edu) for comparison. A file `cosette_apikey.txt` with only the apikey in it on root level of the test repository is required to use this feature. If not existant, only the string comparison is performed. *Warning: Cosette is currently not maintained!*
|
|
124
|
+
|
|
125
|
+
``` python
|
|
126
|
+
res = checkEquality()
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
### Changelog
|
|
138
|
+
|
|
139
|
+
##### V 0.2.6
|
|
140
|
+
- Fixed bug in checkKeywords: if keyword was present in one query and not in the other, the comparison was not performed correctly.
|
|
141
|
+
|
|
142
|
+
##### V 0.2.5
|
|
143
|
+
- Added support for [dbiu.de](https://www.datenbanken-im-unterricht.de/catalog.php) databases 1-18 (loaded via [dbiu_databases](https://github.com/ValentinHerrmann/dbiu_databases)) with option to still load DBs from local repo.
|
|
144
|
+
- Improved docs
|
|
145
|
+
|
|
146
|
+
##### V 0.2.4
|
|
147
|
+
- Added more check methods for single parts of queries: checkColumns, checkTables, checkCondition, checkOrder, checkGroup, checkKeywords
|
|
148
|
+
|
|
149
|
+
##### V 0.2.3
|
|
150
|
+
- fix: ASC/DESC in ORDER BY (also with multiple columns and order directions), no direction treated as ASC
|
|
151
|
+
- Verified that ; and whitespaces, linebreaks at end of query are ignored
|
|
152
|
+
|
|
153
|
+
##### V 0.2.2
|
|
154
|
+
- Support LIKE
|
|
155
|
+
- Support '<=' and '>=' (geq and leq)
|
|
156
|
+
|
|
157
|
+
##### V 0.2.1
|
|
158
|
+
- Support LIMIT
|
|
159
|
+
|
|
160
|
+
##### V 0.1.9 + 0.2.0
|
|
161
|
+
- Support ORDER BY
|
|
162
|
+
|
|
163
|
+
##### V 0.1.8
|
|
164
|
+
- Fixed linebreak problems: Linebreaks are now converted into whitespaces before parsing where tokens
|
|
165
|
+
|
|
166
|
+
##### V 0.1.6 + V 0.1.7
|
|
167
|
+
- Fixed import error to ensure imports working in different environments
|
|
168
|
+
|
|
169
|
+
##### V 0.1.4 + V 0.1.5
|
|
170
|
+
- Chained conditions (with AND,OR and Paranthesises) in WHERE statement
|
|
171
|
+
- Aggregate Functions
|
|
172
|
+
|
|
173
|
+
##### V 0.1.3
|
|
174
|
+
- SELECT: columns with our without table prefix
|
|
175
|
+
- FROM: one or more table from DB; no queries as tables!
|
|
176
|
+
- WHERE: single conditions; no Paranthesises!
|
|
177
|
+
- GROUP BY one or more columns
|
|
178
|
+
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
A library that normalizes simple SQL queries and compares them first by equality of the normalized string and then using the cosette API.
|
|
2
|
+
|
|
3
|
+
#### [Beta in Development!]
|
|
4
|
+
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-build.yml)
|
|
5
|
+
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-unittests.yml)
|
|
6
|
+
|
|
7
|
+
- Submit bug reports and features requests at: https://github.com/ValentinHerrmann/sql_testing_tools
|
|
8
|
+
- PyPi-Package available at: https://pypi.org/project/sql-testing-tools/
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
## Getting started
|
|
12
|
+
|
|
13
|
+
### Imports
|
|
14
|
+
``` python
|
|
15
|
+
# ensure to always use the latest version of sql_testing_tools
|
|
16
|
+
import os
|
|
17
|
+
os.system('pip install -U sql_testing_tools')
|
|
18
|
+
|
|
19
|
+
# import sql_testing_tools
|
|
20
|
+
import sql_testing_tools.BaseAccess as Ba
|
|
21
|
+
import sql_testing_tools.Helper as He
|
|
22
|
+
|
|
23
|
+
# import unittest and create TestClass
|
|
24
|
+
import unittest
|
|
25
|
+
class TestClass(unittest.TestCase):
|
|
26
|
+
# Ba.setDBName(...)
|
|
27
|
+
# ...
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Choosing a database
|
|
31
|
+
|
|
32
|
+
On top level of your test class, set the SQLite database you want to use.
|
|
33
|
+
|
|
34
|
+
**Option 1:** Use the predefined ones from [dbiu_databases](https://github.com/ValentinHerrmann/dbiu_databases) which are based on [datenbanken-im-unterricht.de](https://www.datenbanken-im-unterricht.de/catalog.php)
|
|
35
|
+
|
|
36
|
+
``` python
|
|
37
|
+
# with DB name (preferred)
|
|
38
|
+
# --> only available if current dbiu_databases version has been imported to sql_testing_tools
|
|
39
|
+
Ba.setDBName("dbiu.bayern")
|
|
40
|
+
|
|
41
|
+
# or with dbiu_databases version number
|
|
42
|
+
# --> available as soon as a dbiu_databases version has been published on PyPi
|
|
43
|
+
Ba.setDBName(2)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Currently supported to use with DB name are:
|
|
47
|
+
1. `dbiu.bahn`: https://www.dbiu.de/bahn
|
|
48
|
+
2. `dbiu.bayern`: https://www.dbiu.de/bayern
|
|
49
|
+
3. `dbiu.bundestag`: https://www.datenbanken-im-unterricht.de/downloads/bundestag.zip
|
|
50
|
+
4. `dbiu.bundestag_einfach`: https://www.dbiu.de/bundestagsmitglieder
|
|
51
|
+
5. `dbiu.film_fernsehen`: https://www.dbiu.de/filmundfernsehen
|
|
52
|
+
6. `dbiu.haushaltsausstattung`: https://www.dbiu.de/haushaltsausstattung
|
|
53
|
+
7. `dbiu.straftaten`: https://www.datenbanken-im-unterricht.de/downloads/kriminalstatistik-erweitert.zip
|
|
54
|
+
8. `dbiu.straftaten_einfach`: https://www.dbiu.de/kriminalstatistik
|
|
55
|
+
9. `dbiu.kunstsammlung`: https://www.dbiu.de/kunstsammlung
|
|
56
|
+
10. `dbiu.ladepunkte`: https://www.dbiu.de/ladepunkte
|
|
57
|
+
11. `dbiu.laenderspiele`: https://www.dbiu.de/laenderspiele
|
|
58
|
+
12. `dbiu.lebensmittel`: https://www.dbiu.de/lebensmittel
|
|
59
|
+
13. `dbiu.schulstatistik`: https://www.dbiu.de/schulstatistik
|
|
60
|
+
14. `dbiu.studierende`: https://www.dbiu.de/studierende
|
|
61
|
+
15. `dbiu.unfallstatistik`: https://www.dbiu.de/unfallstatistik
|
|
62
|
+
16. `dbiu.videospiele_einfach`: https://www.dbiu.de/videospiele
|
|
63
|
+
17. `dbiu.videospiele`: https://www.dbiu.de/videospiele2
|
|
64
|
+
18. `dbiu.wetterdaten`: https://www.dbiu.de/wetterdaten
|
|
65
|
+
|
|
66
|
+
**Option 2:** Use your own SQLite database with relative path starting at the working dir of your test repository.
|
|
67
|
+
``` python
|
|
68
|
+
Ba.setDBName("databases/bayern.db")
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Available testing features
|
|
72
|
+
|
|
73
|
+
The following methods are available for use in test methods:
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
**Run the query to find out if syntax/database errors occur.**
|
|
77
|
+
``` python
|
|
78
|
+
try:
|
|
79
|
+
Ba.runAndGetStringTable_fromFile("sqlfile.sql")
|
|
80
|
+
except Exception as e:
|
|
81
|
+
# the execution failed (usually due to syntax or database errors)
|
|
82
|
+
self.fail(e)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
**Set sql files to be compared (optional).**
|
|
88
|
+
The sql strings will be normalized and used or all following methods (to improve performance) until new files are specified. All check...() functions call setup(...) as first step. If one argument is `""` or `None` the corresponding file is not changed. Therefore calling the check...() functions without arguments does not change the sql files that are compared.
|
|
89
|
+
``` python
|
|
90
|
+
# Raises an Exception if one of the files is empty.
|
|
91
|
+
setup("sqlfile.sql","solution.sql")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Compared single parts of a sql query**
|
|
95
|
+
Call without arguments to keep the last normalized sql strings (and improve performance) and with one or two sql file paths to load and normalize new queries.
|
|
96
|
+
Each check was successfull if `""` is returned. Returns a German error message if not.
|
|
97
|
+
Each method compares the normalized string between the start keyword and the next keyword or ;
|
|
98
|
+
``` python
|
|
99
|
+
|
|
100
|
+
res = He.checkColumns() # starts at "SELECT"
|
|
101
|
+
res = He.checkTables() # starts at "FROM"
|
|
102
|
+
res = He.checkCondition() # starts at "WHERE"
|
|
103
|
+
res = He.checkOrder() # starts at "ORDER BY"
|
|
104
|
+
res = He.checkGroup() # starts at "GROUP BY"
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
In special cases where you'd like to start and stop at individual keywords for comparison use this directly:
|
|
108
|
+
``` python
|
|
109
|
+
# Can not be called with new sql files. If needed call setup(...) before.
|
|
110
|
+
res = checkKeywords("startKeyword",["end","keywords"])
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Compares equality of the full normalized sql strings and if not equal uses the Cosette API (cosette.cs.washington.edu) for comparison. A file `cosette_apikey.txt` with only the apikey in it on root level of the test repository is required to use this feature. If not existant, only the string comparison is performed. *Warning: Cosette is currently not maintained!*
|
|
114
|
+
|
|
115
|
+
``` python
|
|
116
|
+
res = checkEquality()
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
### Changelog
|
|
128
|
+
|
|
129
|
+
##### V 0.2.6
|
|
130
|
+
- Fixed bug in checkKeywords: if keyword was present in one query and not in the other, the comparison was not performed correctly.
|
|
131
|
+
|
|
132
|
+
##### V 0.2.5
|
|
133
|
+
- Added support for [dbiu.de](https://www.datenbanken-im-unterricht.de/catalog.php) databases 1-18 (loaded via [dbiu_databases](https://github.com/ValentinHerrmann/dbiu_databases)) with option to still load DBs from local repo.
|
|
134
|
+
- Improved docs
|
|
135
|
+
|
|
136
|
+
##### V 0.2.4
|
|
137
|
+
- Added more check methods for single parts of queries: checkColumns, checkTables, checkCondition, checkOrder, checkGroup, checkKeywords
|
|
138
|
+
|
|
139
|
+
##### V 0.2.3
|
|
140
|
+
- fix: ASC/DESC in ORDER BY (also with multiple columns and order directions), no direction treated as ASC
|
|
141
|
+
- Verified that ; and whitespaces, linebreaks at end of query are ignored
|
|
142
|
+
|
|
143
|
+
##### V 0.2.2
|
|
144
|
+
- Support LIKE
|
|
145
|
+
- Support '<=' and '>=' (geq and leq)
|
|
146
|
+
|
|
147
|
+
##### V 0.2.1
|
|
148
|
+
- Support LIMIT
|
|
149
|
+
|
|
150
|
+
##### V 0.1.9 + 0.2.0
|
|
151
|
+
- Support ORDER BY
|
|
152
|
+
|
|
153
|
+
##### V 0.1.8
|
|
154
|
+
- Fixed linebreak problems: Linebreaks are now converted into whitespaces before parsing where tokens
|
|
155
|
+
|
|
156
|
+
##### V 0.1.6 + V 0.1.7
|
|
157
|
+
- Fixed import error to ensure imports working in different environments
|
|
158
|
+
|
|
159
|
+
##### V 0.1.4 + V 0.1.5
|
|
160
|
+
- Chained conditions (with AND,OR and Paranthesises) in WHERE statement
|
|
161
|
+
- Aggregate Functions
|
|
162
|
+
|
|
163
|
+
##### V 0.1.3
|
|
164
|
+
- SELECT: columns with our without table prefix
|
|
165
|
+
- FROM: one or more table from DB; no queries as tables!
|
|
166
|
+
- WHERE: single conditions; no Paranthesises!
|
|
167
|
+
- GROUP BY one or more columns
|
|
168
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
with open("README.md", "r") as fh:
|
|
4
|
+
description = fh.read()
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
setup(
|
|
8
|
+
name='sql_testing_tools',
|
|
9
|
+
version='0.2.6',
|
|
10
|
+
packages=find_packages(),
|
|
11
|
+
install_requires=[
|
|
12
|
+
'sqlparse>=0.5.1',
|
|
13
|
+
'requests>=2.32.3'
|
|
14
|
+
],
|
|
15
|
+
long_description=description,
|
|
16
|
+
long_description_content_type="text/markdown"
|
|
17
|
+
)
|
|
@@ -3,51 +3,68 @@ import os
|
|
|
3
3
|
import importlib
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
__db=""
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
dbMap = {
|
|
8
|
+
"dbiu.bahn":1,
|
|
9
|
+
"dbiu.bayern":2,
|
|
10
|
+
"dbiu.bundestag": 3,
|
|
11
|
+
"dbiu.bundestag_einfach": 4,
|
|
12
|
+
"dbiu.film_fernsehen": 5,
|
|
13
|
+
"dbiu.haushaltsausstattung": 6,
|
|
14
|
+
"dbiu.straftaten": 7,
|
|
15
|
+
"dbiu.straftaten_einfach": 8,
|
|
16
|
+
"dbiu.kunstsammlung": 9,
|
|
17
|
+
"dbiu.ladepunkte": 10,
|
|
18
|
+
"dbiu.laenderspiele": 11,
|
|
19
|
+
"dbiu.lebensmittel": 12,
|
|
20
|
+
"dbiu.schulstatistik": 13,
|
|
21
|
+
"dbiu.studierende": 14,
|
|
22
|
+
"dbiu.unfallstatistik": 15,
|
|
23
|
+
"dbiu.videospiele_einfach": 16,
|
|
24
|
+
"dbiu.videospiele": 17,
|
|
25
|
+
"dbiu.wetterdaten": 18
|
|
26
|
+
}
|
|
12
27
|
|
|
13
|
-
|
|
14
|
-
global __db
|
|
15
|
-
|
|
16
|
-
resources = list(importlib.resources.contents('sql_testing_tools.databases'))
|
|
17
|
-
print("Available resources: " + str(resources))
|
|
28
|
+
__db=""
|
|
18
29
|
|
|
19
|
-
|
|
30
|
+
def setDBName(database):
|
|
31
|
+
global __db
|
|
20
32
|
|
|
21
|
-
if(
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
print("Database found in current directory.")
|
|
29
|
-
return False
|
|
33
|
+
if isinstance(database, str) and database.startswith("dbiu."):
|
|
34
|
+
dbVersion = dbMap.get(database)
|
|
35
|
+
elif isinstance(database, int):
|
|
36
|
+
dbVersion = database
|
|
37
|
+
database = "dbiu."+str(database)
|
|
38
|
+
elif isinstance(database, str):
|
|
39
|
+
dbVersion = None
|
|
30
40
|
else:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
41
|
+
raise Exception("Invalid database selected")
|
|
42
|
+
|
|
43
|
+
if(dbVersion is not None):
|
|
44
|
+
os.system('pip install dbiu_databases=='+str(dbVersion))
|
|
45
|
+
try:
|
|
46
|
+
import dbiu_databases
|
|
47
|
+
except ImportError:
|
|
48
|
+
raise Exception("Invalid database selected")
|
|
49
|
+
print("Setting DB to: " + database)
|
|
50
|
+
__db = database
|
|
51
|
+
|
|
52
|
+
|
|
36
53
|
def run(sql: str):
|
|
37
54
|
global __db
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
cur.execute(sql)
|
|
43
|
-
con.commit()
|
|
44
|
-
return cur
|
|
55
|
+
|
|
56
|
+
if __db.startswith("dbiu.") and not __db.endswith(".db"):
|
|
57
|
+
with importlib.resources.path('dbiu_databases', "base.db") as db_path:
|
|
58
|
+
return __run(sql, db_path)
|
|
45
59
|
else:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
60
|
+
return __run(sql, __db)
|
|
61
|
+
|
|
62
|
+
def __run(sql: str, db: str):
|
|
63
|
+
with sqlite3.connect(db) as con:
|
|
64
|
+
cur = con.cursor()
|
|
65
|
+
cur.execute(sql)
|
|
66
|
+
con.commit()
|
|
67
|
+
return cur
|
|
51
68
|
|
|
52
69
|
def runFromFile(path: str):
|
|
53
70
|
sql = getSQLFromFile(path)
|
|
@@ -152,7 +152,7 @@ def buildAndSendCosetteRequest(baseDict, sql, sol):
|
|
|
152
152
|
def checkKeywords(startWord:str, endWords:list):
|
|
153
153
|
global sql,sol
|
|
154
154
|
|
|
155
|
-
if(startWord not in sol
|
|
155
|
+
if(startWord not in sol and startWord not in sql):
|
|
156
156
|
return ""
|
|
157
157
|
|
|
158
158
|
if(startWord in sql):
|
|
@@ -186,119 +186,30 @@ def checkKeywords(startWord:str, endWords:list):
|
|
|
186
186
|
return "Der '"+startWord+"' Teil der SQL-Abfrage ist nicht korrekt (oder nicht automatisch überprüfbar)."
|
|
187
187
|
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
|
|
191
189
|
def checkColumns(sqlPath="", solPath=""):
|
|
192
190
|
global sql,sol
|
|
193
191
|
setup(sqlPath, solPath)
|
|
194
192
|
return checkKeywords("SELECT", ["FROM", "WHERE", "GROUP BY", "ORDER BY", "LIMIT", ";", "HAVING"])
|
|
195
193
|
|
|
196
194
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if("SELECT" in sql and "FROM" in sql):
|
|
200
|
-
start = str.find(sql, "SELECT")
|
|
201
|
-
end = str.find(sql, "FROM")
|
|
202
|
-
submission = str.strip(sql[start:end])
|
|
203
|
-
print("'"+submission+"'")
|
|
204
|
-
|
|
205
|
-
start = str.find(sol, "SELECT")
|
|
206
|
-
end = str.find(sol, "FROM")
|
|
207
|
-
solution = str.strip(sol[start:end])
|
|
208
|
-
print("'"+solution+"'")
|
|
209
|
-
|
|
210
|
-
if submission == solution:
|
|
211
|
-
return ""
|
|
212
|
-
return "Ausgegebene Spalten sind nicht korrekt (oder nicht automatisch überprüfbar)."
|
|
213
|
-
|
|
214
195
|
def checkTables(sqlPath="", solPath=""):
|
|
215
196
|
global sql,sol
|
|
216
197
|
setup(sqlPath, solPath)
|
|
217
198
|
return checkKeywords("FROM", ["FROM", "WHERE", "GROUP BY", "ORDER BY", "LIMIT", ";", "HAVING"])
|
|
218
199
|
|
|
219
200
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
if("SELECT" in sql and "FROM" in sql):
|
|
223
|
-
endFromKeywords = ["WHERE", "GROUP", "ORDER", "LIMIT", ";"]
|
|
224
|
-
|
|
225
|
-
start = str.find(sql, "FROM")
|
|
226
|
-
end = -1
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
for keyword in endFromKeywords:
|
|
230
|
-
if(str.find(sql, keyword) != -1):
|
|
231
|
-
end = str.find(sql, keyword)
|
|
232
|
-
break
|
|
233
|
-
if(end == -1):
|
|
234
|
-
end = len(sql)
|
|
235
|
-
|
|
236
|
-
submission = str.strip(sql[start:end])
|
|
237
|
-
print("'"+submission+"'")
|
|
238
|
-
|
|
239
|
-
start = str.find(sol, "FROM")
|
|
240
|
-
end = -1
|
|
241
|
-
|
|
242
|
-
for keyword in endFromKeywords:
|
|
243
|
-
if(str.find(sol, keyword) != -1):
|
|
244
|
-
end = str.find(sol, keyword)
|
|
245
|
-
break
|
|
246
|
-
if(end == -1):
|
|
247
|
-
end = len(sol)
|
|
248
|
-
|
|
249
|
-
solution = str.strip(sol[start:end])
|
|
250
|
-
print("'"+solution+"'")
|
|
251
|
-
|
|
252
|
-
if submission == solution:
|
|
253
|
-
return ""
|
|
254
|
-
return "Verwendete Tabellen sind nicht korrekt (oder nicht automatisch überprüfbar)."
|
|
255
|
-
|
|
256
201
|
def checkCondition(sqlPath="", solPath=""):
|
|
257
202
|
global sql,sol
|
|
258
203
|
setup(sqlPath, solPath)
|
|
259
204
|
return checkKeywords("WHERE", ["GROUP BY", "ORDER BY", "LIMIT", ";", "HAVING"])
|
|
260
205
|
|
|
206
|
+
|
|
261
207
|
def checkOrder(sqlPath="", solPath=""):
|
|
262
208
|
global sql,sol
|
|
263
209
|
setup(sqlPath, solPath)
|
|
264
210
|
return checkKeywords("ORDER BY", ["WHERE", "GROUP BY", "ORDER BY", "LIMIT", ";", "HAVING"])
|
|
265
211
|
|
|
266
212
|
|
|
267
|
-
|
|
268
|
-
if("ORDER BY" in sql):
|
|
269
|
-
endFromKeywords = ["WHERE", "GROUP", "LIMIT", ";"]
|
|
270
|
-
|
|
271
|
-
start = str.find(sql, "ORDER BY")
|
|
272
|
-
end = -1
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
for keyword in endFromKeywords:
|
|
276
|
-
if(str.find(sql, keyword) != -1):
|
|
277
|
-
end = str.find(sql, keyword)
|
|
278
|
-
break
|
|
279
|
-
if(end == -1):
|
|
280
|
-
end = len(sql)
|
|
281
|
-
|
|
282
|
-
submission = str.strip(sql[start:end])
|
|
283
|
-
print("'"+submission+"'")
|
|
284
|
-
|
|
285
|
-
start = str.find(sol, "ORDER BY")
|
|
286
|
-
end = -1
|
|
287
|
-
|
|
288
|
-
for keyword in endFromKeywords:
|
|
289
|
-
if(str.find(sol, keyword) != -1):
|
|
290
|
-
end = str.find(sol, keyword)
|
|
291
|
-
break
|
|
292
|
-
if(end == -1):
|
|
293
|
-
end = len(sol)
|
|
294
|
-
|
|
295
|
-
solution = str.strip(sol[start:end])
|
|
296
|
-
print("'"+solution+"'")
|
|
297
|
-
|
|
298
|
-
if submission == solution:
|
|
299
|
-
return ""
|
|
300
|
-
return "Die Sortierung ist nicht korrekt (oder nicht automatisch überprüfbar)."
|
|
301
|
-
|
|
302
213
|
def checkGroup(sqlPath="", solPath=""):
|
|
303
214
|
global sql,sol
|
|
304
215
|
setup(sqlPath, solPath)
|
|
@@ -306,17 +217,17 @@ def checkGroup(sqlPath="", solPath=""):
|
|
|
306
217
|
|
|
307
218
|
|
|
308
219
|
def checkEquality(sqlPath="", solPath=""):
|
|
309
|
-
global sql,sol
|
|
220
|
+
global sql, sol
|
|
310
221
|
setup(sqlPath, solPath)
|
|
311
222
|
|
|
312
|
-
if
|
|
223
|
+
if sql == sol:
|
|
313
224
|
return ""
|
|
314
225
|
|
|
315
226
|
result = buildAndSendCosetteRequest(bd, sql, sol)
|
|
316
227
|
|
|
317
|
-
if
|
|
228
|
+
if result[0] == "ERR":
|
|
318
229
|
return "\n\nFehler bei der automatischen Überprüfung der Abgabe. Es kann keine Aussage über die Korrektheit der Abgabe getroffen werden."
|
|
319
|
-
elif
|
|
230
|
+
elif result[0] != "EQ":
|
|
320
231
|
return "\n\nDie Abgabe stimmt nicht mit der Musterlösung überein."
|
|
321
232
|
return ""
|
|
322
233
|
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: sql_testing_tools
|
|
3
|
+
Version: 0.2.6
|
|
4
|
+
Description-Content-Type: text/markdown
|
|
5
|
+
Requires-Dist: sqlparse>=0.5.1
|
|
6
|
+
Requires-Dist: requests>=2.32.3
|
|
7
|
+
Dynamic: description
|
|
8
|
+
Dynamic: description-content-type
|
|
9
|
+
Dynamic: requires-dist
|
|
10
|
+
|
|
11
|
+
A library that normalizes simple SQL queries and compares them first by equality of the normalized string and then using the cosette API.
|
|
12
|
+
|
|
13
|
+
#### [Beta in Development!]
|
|
14
|
+
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-build.yml)
|
|
15
|
+
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-unittests.yml)
|
|
16
|
+
|
|
17
|
+
- Submit bug reports and features requests at: https://github.com/ValentinHerrmann/sql_testing_tools
|
|
18
|
+
- PyPi-Package available at: https://pypi.org/project/sql-testing-tools/
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## Getting started
|
|
22
|
+
|
|
23
|
+
### Imports
|
|
24
|
+
``` python
|
|
25
|
+
# ensure to always use the latest version of sql_testing_tools
|
|
26
|
+
import os
|
|
27
|
+
os.system('pip install -U sql_testing_tools')
|
|
28
|
+
|
|
29
|
+
# import sql_testing_tools
|
|
30
|
+
import sql_testing_tools.BaseAccess as Ba
|
|
31
|
+
import sql_testing_tools.Helper as He
|
|
32
|
+
|
|
33
|
+
# import unittest and create TestClass
|
|
34
|
+
import unittest
|
|
35
|
+
class TestClass(unittest.TestCase):
|
|
36
|
+
# Ba.setDBName(...)
|
|
37
|
+
# ...
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Choosing a database
|
|
41
|
+
|
|
42
|
+
On top level of your test class, set the SQLite database you want to use.
|
|
43
|
+
|
|
44
|
+
**Option 1:** Use the predefined ones from [dbiu_databases](https://github.com/ValentinHerrmann/dbiu_databases) which are based on [datenbanken-im-unterricht.de](https://www.datenbanken-im-unterricht.de/catalog.php)
|
|
45
|
+
|
|
46
|
+
``` python
|
|
47
|
+
# with DB name (preferred)
|
|
48
|
+
# --> only available if current dbiu_databases version has been imported to sql_testing_tools
|
|
49
|
+
Ba.setDBName("dbiu.bayern")
|
|
50
|
+
|
|
51
|
+
# or with dbiu_databases version number
|
|
52
|
+
# --> available as soon as a dbiu_databases version has been published on PyPi
|
|
53
|
+
Ba.setDBName(2)
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Currently supported to use with DB name are:
|
|
57
|
+
1. `dbiu.bahn`: https://www.dbiu.de/bahn
|
|
58
|
+
2. `dbiu.bayern`: https://www.dbiu.de/bayern
|
|
59
|
+
3. `dbiu.bundestag`: https://www.datenbanken-im-unterricht.de/downloads/bundestag.zip
|
|
60
|
+
4. `dbiu.bundestag_einfach`: https://www.dbiu.de/bundestagsmitglieder
|
|
61
|
+
5. `dbiu.film_fernsehen`: https://www.dbiu.de/filmundfernsehen
|
|
62
|
+
6. `dbiu.haushaltsausstattung`: https://www.dbiu.de/haushaltsausstattung
|
|
63
|
+
7. `dbiu.straftaten`: https://www.datenbanken-im-unterricht.de/downloads/kriminalstatistik-erweitert.zip
|
|
64
|
+
8. `dbiu.straftaten_einfach`: https://www.dbiu.de/kriminalstatistik
|
|
65
|
+
9. `dbiu.kunstsammlung`: https://www.dbiu.de/kunstsammlung
|
|
66
|
+
10. `dbiu.ladepunkte`: https://www.dbiu.de/ladepunkte
|
|
67
|
+
11. `dbiu.laenderspiele`: https://www.dbiu.de/laenderspiele
|
|
68
|
+
12. `dbiu.lebensmittel`: https://www.dbiu.de/lebensmittel
|
|
69
|
+
13. `dbiu.schulstatistik`: https://www.dbiu.de/schulstatistik
|
|
70
|
+
14. `dbiu.studierende`: https://www.dbiu.de/studierende
|
|
71
|
+
15. `dbiu.unfallstatistik`: https://www.dbiu.de/unfallstatistik
|
|
72
|
+
16. `dbiu.videospiele_einfach`: https://www.dbiu.de/videospiele
|
|
73
|
+
17. `dbiu.videospiele`: https://www.dbiu.de/videospiele2
|
|
74
|
+
18. `dbiu.wetterdaten`: https://www.dbiu.de/wetterdaten
|
|
75
|
+
|
|
76
|
+
**Option 2:** Use your own SQLite database with relative path starting at the working dir of your test repository.
|
|
77
|
+
``` python
|
|
78
|
+
Ba.setDBName("databases/bayern.db")
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Available testing features
|
|
82
|
+
|
|
83
|
+
The following methods are available for use in test methods:
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
**Run the query to find out if syntax/database errors occur.**
|
|
87
|
+
``` python
|
|
88
|
+
try:
|
|
89
|
+
Ba.runAndGetStringTable_fromFile("sqlfile.sql")
|
|
90
|
+
except Exception as e:
|
|
91
|
+
# the execution failed (usually due to syntax or database errors)
|
|
92
|
+
self.fail(e)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
**Set sql files to be compared (optional).**
|
|
98
|
+
The sql strings will be normalized and used or all following methods (to improve performance) until new files are specified. All check...() functions call setup(...) as first step. If one argument is `""` or `None` the corresponding file is not changed. Therefore calling the check...() functions without arguments does not change the sql files that are compared.
|
|
99
|
+
``` python
|
|
100
|
+
# Raises an Exception if one of the files is empty.
|
|
101
|
+
setup("sqlfile.sql","solution.sql")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**Compared single parts of a sql query**
|
|
105
|
+
Call without arguments to keep the last normalized sql strings (and improve performance) and with one or two sql file paths to load and normalize new queries.
|
|
106
|
+
Each check was successfull if `""` is returned. Returns a German error message if not.
|
|
107
|
+
Each method compares the normalized string between the start keyword and the next keyword or ;
|
|
108
|
+
``` python
|
|
109
|
+
|
|
110
|
+
res = He.checkColumns() # starts at "SELECT"
|
|
111
|
+
res = He.checkTables() # starts at "FROM"
|
|
112
|
+
res = He.checkCondition() # starts at "WHERE"
|
|
113
|
+
res = He.checkOrder() # starts at "ORDER BY"
|
|
114
|
+
res = He.checkGroup() # starts at "GROUP BY"
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
In special cases where you'd like to start and stop at individual keywords for comparison use this directly:
|
|
118
|
+
``` python
|
|
119
|
+
# Can not be called with new sql files. If needed call setup(...) before.
|
|
120
|
+
res = checkKeywords("startKeyword",["end","keywords"])
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Compares equality of the full normalized sql strings and if not equal uses the Cosette API (cosette.cs.washington.edu) for comparison. A file `cosette_apikey.txt` with only the apikey in it on root level of the test repository is required to use this feature. If not existant, only the string comparison is performed. *Warning: Cosette is currently not maintained!*
|
|
124
|
+
|
|
125
|
+
``` python
|
|
126
|
+
res = checkEquality()
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
### Changelog
|
|
138
|
+
|
|
139
|
+
##### V 0.2.6
|
|
140
|
+
- Fixed bug in checkKeywords: if keyword was present in one query and not in the other, the comparison was not performed correctly.
|
|
141
|
+
|
|
142
|
+
##### V 0.2.5
|
|
143
|
+
- Added support for [dbiu.de](https://www.datenbanken-im-unterricht.de/catalog.php) databases 1-18 (loaded via [dbiu_databases](https://github.com/ValentinHerrmann/dbiu_databases)) with option to still load DBs from local repo.
|
|
144
|
+
- Improved docs
|
|
145
|
+
|
|
146
|
+
##### V 0.2.4
|
|
147
|
+
- Added more check methods for single parts of queries: checkColumns, checkTables, checkCondition, checkOrder, checkGroup, checkKeywords
|
|
148
|
+
|
|
149
|
+
##### V 0.2.3
|
|
150
|
+
- fix: ASC/DESC in ORDER BY (also with multiple columns and order directions), no direction treated as ASC
|
|
151
|
+
- Verified that ; and whitespaces, linebreaks at end of query are ignored
|
|
152
|
+
|
|
153
|
+
##### V 0.2.2
|
|
154
|
+
- Support LIKE
|
|
155
|
+
- Support '<=' and '>=' (geq and leq)
|
|
156
|
+
|
|
157
|
+
##### V 0.2.1
|
|
158
|
+
- Support LIMIT
|
|
159
|
+
|
|
160
|
+
##### V 0.1.9 + 0.2.0
|
|
161
|
+
- Support ORDER BY
|
|
162
|
+
|
|
163
|
+
##### V 0.1.8
|
|
164
|
+
- Fixed linebreak problems: Linebreaks are now converted into whitespaces before parsing where tokens
|
|
165
|
+
|
|
166
|
+
##### V 0.1.6 + V 0.1.7
|
|
167
|
+
- Fixed import error to ensure imports working in different environments
|
|
168
|
+
|
|
169
|
+
##### V 0.1.4 + V 0.1.5
|
|
170
|
+
- Chained conditions (with AND,OR and Paranthesises) in WHERE statement
|
|
171
|
+
- Aggregate Functions
|
|
172
|
+
|
|
173
|
+
##### V 0.1.3
|
|
174
|
+
- SELECT: columns with our without table prefix
|
|
175
|
+
- FROM: one or more table from DB; no queries as tables!
|
|
176
|
+
- WHERE: single conditions; no Paranthesises!
|
|
177
|
+
- GROUP BY one or more columns
|
|
178
|
+
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: sql_testing_tools
|
|
3
|
-
Version: 0.2.4a0
|
|
4
|
-
Description-Content-Type: text/markdown
|
|
5
|
-
Requires-Dist: sqlparse>=0.5.1
|
|
6
|
-
Requires-Dist: requests>=2.32.3
|
|
7
|
-
Dynamic: description
|
|
8
|
-
Dynamic: description-content-type
|
|
9
|
-
Dynamic: requires-dist
|
|
10
|
-
|
|
11
|
-
A library that normalizes simple SQL queries and compares them first by equality of the normalized string and then using the cosette API.
|
|
12
|
-
|
|
13
|
-
### [Beta in Development!]
|
|
14
|
-
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-build.yml)
|
|
15
|
-
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-unittests.yml)
|
|
16
|
-
|
|
17
|
-
- Submit bug reports and features requests at: https://github.com/ValentinHerrmann/sql_testing_tools
|
|
18
|
-
- PyPi-Package available at: https://pypi.org/project/sql-testing-tools/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
### Getting started
|
|
23
|
-
|
|
24
|
-
Use the following code to import the SQL Testing Tools to your project:
|
|
25
|
-
``` python
|
|
26
|
-
# ensure to always use the latest version of sql_testing_tools
|
|
27
|
-
import os
|
|
28
|
-
os.system('pip install -U sql_testing_tools')
|
|
29
|
-
|
|
30
|
-
# import sql_testing_tools
|
|
31
|
-
import sql_testing_tools.BaseAccess as Ba
|
|
32
|
-
import sql_testing_tools.Helper as He
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
On global level of your test class, set the SQLite database you want to use (bases must be located in the repository of the test class, no DBs contained in sql_testing_tools).
|
|
36
|
-
``` python
|
|
37
|
-
import unittest
|
|
38
|
-
class TestClass(unittest.TestCase):
|
|
39
|
-
Ba.setDBName("databases/ladepunkte.db")
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
The following methods are available for use in test methods:
|
|
43
|
-
``` python
|
|
44
|
-
try:
|
|
45
|
-
Ba.runAndGetStringTable_fromFile("sqlfile.sql")
|
|
46
|
-
except Exception as e:
|
|
47
|
-
# the execution failed
|
|
48
|
-
# (usually due to syntax or database errors)
|
|
49
|
-
self.fail(e)
|
|
50
|
-
|
|
51
|
-
# (optional) set the files to be compared. The sql strings will
|
|
52
|
-
# be normalized and used for all following methods (to improve
|
|
53
|
-
# performance), until new files are set. Arguments that are
|
|
54
|
-
# None or "" are ignored and the sql string remains the same.
|
|
55
|
-
# Raises an Exception if one of the files is empty.
|
|
56
|
-
setup("sqlfile.sql","solution.sql")
|
|
57
|
-
|
|
58
|
-
# All following methods call setup(sql,sol) before executing
|
|
59
|
-
# anything else. Call without arguments to keep the last
|
|
60
|
-
# normalized sql strings (and improve performance).
|
|
61
|
-
# Each check was successfull if "" is returned. Returns a
|
|
62
|
-
# German error message if not.
|
|
63
|
-
# Each method compares the normalized string between the start
|
|
64
|
-
# keyword and the next keyword or ;
|
|
65
|
-
|
|
66
|
-
res = He.checkColumns() # starts to search at keyword "SELECT"
|
|
67
|
-
res = He.checkTables() # starts to search at keyword "FROM"
|
|
68
|
-
res = He.checkCondition() # starts to search at keyword "WHERE"
|
|
69
|
-
res = He.checkOrder() # starts to search at keyword "ORDER BY"
|
|
70
|
-
res = He.checkGroup() # starts to search at keyword "GROUP BY"
|
|
71
|
-
|
|
72
|
-
# can not be called with new sql files
|
|
73
|
-
res = checkKeywords("startKeyword",["end","keywords"])
|
|
74
|
-
|
|
75
|
-
# compares equality of the full normalized sql strings and if
|
|
76
|
-
# not equal uses the Cosette API (cosette.cs.washington.edu)
|
|
77
|
-
# for comparison. A file 'cosette_apikey.txt' with only the
|
|
78
|
-
# apikey in it on root level of the test repository is required
|
|
79
|
-
# to use this feature. If not existant, only the string comparison
|
|
80
|
-
# is performed.
|
|
81
|
-
# Warning: Cosette is not maintained!
|
|
82
|
-
res = checkEquality()
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
### Changelog
|
|
94
|
-
|
|
95
|
-
##### V0.2.4
|
|
96
|
-
- Added more check methods for single parts of queries: checkColumns, checkTables, checkCondition, checkOrder, checkGroup, checkKeywords
|
|
97
|
-
|
|
98
|
-
##### V 0.2.3
|
|
99
|
-
- fix: ASC/DESC in ORDER BY (also with multiple columns and order directions), no direction treated as ASC
|
|
100
|
-
- Verified that ; and whitespaces, linebreaks at end of query are ignored
|
|
101
|
-
|
|
102
|
-
##### V 0.2.2
|
|
103
|
-
- Support LIKE
|
|
104
|
-
- Support '<=' and '>=' (geq and leq)
|
|
105
|
-
|
|
106
|
-
##### V 0.2.1
|
|
107
|
-
- Support LIMIT
|
|
108
|
-
|
|
109
|
-
##### V 0.1.9 + 0.2.0
|
|
110
|
-
- Support ORDER BY
|
|
111
|
-
|
|
112
|
-
##### V 0.1.8
|
|
113
|
-
- Fixed linebreak problems: Linebreaks are now converted into whitespaces before parsing where tokens
|
|
114
|
-
|
|
115
|
-
##### V 0.1.6 + V 0.1.7
|
|
116
|
-
- Fixed import error to ensure imports working in different environments
|
|
117
|
-
|
|
118
|
-
##### V 0.1.4 + V 0.1.5
|
|
119
|
-
- Chained conditions (with AND,OR and Paranthesises) in WHERE statement
|
|
120
|
-
- Aggregate Functions
|
|
121
|
-
|
|
122
|
-
##### V 0.1.3
|
|
123
|
-
- SELECT: columns with our without table prefix
|
|
124
|
-
- FROM: one or more table from DB; no queries as tables!
|
|
125
|
-
- WHERE: single conditions; no Paranthesises!
|
|
126
|
-
- GROUP BY one or more columns
|
|
127
|
-
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
A library that normalizes simple SQL queries and compares them first by equality of the normalized string and then using the cosette API.
|
|
2
|
-
|
|
3
|
-
### [Beta in Development!]
|
|
4
|
-
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-build.yml)
|
|
5
|
-
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-unittests.yml)
|
|
6
|
-
|
|
7
|
-
- Submit bug reports and features requests at: https://github.com/ValentinHerrmann/sql_testing_tools
|
|
8
|
-
- PyPi-Package available at: https://pypi.org/project/sql-testing-tools/
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
### Getting started
|
|
13
|
-
|
|
14
|
-
Use the following code to import the SQL Testing Tools to your project:
|
|
15
|
-
``` python
|
|
16
|
-
# ensure to always use the latest version of sql_testing_tools
|
|
17
|
-
import os
|
|
18
|
-
os.system('pip install -U sql_testing_tools')
|
|
19
|
-
|
|
20
|
-
# import sql_testing_tools
|
|
21
|
-
import sql_testing_tools.BaseAccess as Ba
|
|
22
|
-
import sql_testing_tools.Helper as He
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
On global level of your test class, set the SQLite database you want to use (bases must be located in the repository of the test class, no DBs contained in sql_testing_tools).
|
|
26
|
-
``` python
|
|
27
|
-
import unittest
|
|
28
|
-
class TestClass(unittest.TestCase):
|
|
29
|
-
Ba.setDBName("databases/ladepunkte.db")
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
The following methods are available for use in test methods:
|
|
33
|
-
``` python
|
|
34
|
-
try:
|
|
35
|
-
Ba.runAndGetStringTable_fromFile("sqlfile.sql")
|
|
36
|
-
except Exception as e:
|
|
37
|
-
# the execution failed
|
|
38
|
-
# (usually due to syntax or database errors)
|
|
39
|
-
self.fail(e)
|
|
40
|
-
|
|
41
|
-
# (optional) set the files to be compared. The sql strings will
|
|
42
|
-
# be normalized and used for all following methods (to improve
|
|
43
|
-
# performance), until new files are set. Arguments that are
|
|
44
|
-
# None or "" are ignored and the sql string remains the same.
|
|
45
|
-
# Raises an Exception if one of the files is empty.
|
|
46
|
-
setup("sqlfile.sql","solution.sql")
|
|
47
|
-
|
|
48
|
-
# All following methods call setup(sql,sol) before executing
|
|
49
|
-
# anything else. Call without arguments to keep the last
|
|
50
|
-
# normalized sql strings (and improve performance).
|
|
51
|
-
# Each check was successfull if "" is returned. Returns a
|
|
52
|
-
# German error message if not.
|
|
53
|
-
# Each method compares the normalized string between the start
|
|
54
|
-
# keyword and the next keyword or ;
|
|
55
|
-
|
|
56
|
-
res = He.checkColumns() # starts to search at keyword "SELECT"
|
|
57
|
-
res = He.checkTables() # starts to search at keyword "FROM"
|
|
58
|
-
res = He.checkCondition() # starts to search at keyword "WHERE"
|
|
59
|
-
res = He.checkOrder() # starts to search at keyword "ORDER BY"
|
|
60
|
-
res = He.checkGroup() # starts to search at keyword "GROUP BY"
|
|
61
|
-
|
|
62
|
-
# can not be called with new sql files
|
|
63
|
-
res = checkKeywords("startKeyword",["end","keywords"])
|
|
64
|
-
|
|
65
|
-
# compares equality of the full normalized sql strings and if
|
|
66
|
-
# not equal uses the Cosette API (cosette.cs.washington.edu)
|
|
67
|
-
# for comparison. A file 'cosette_apikey.txt' with only the
|
|
68
|
-
# apikey in it on root level of the test repository is required
|
|
69
|
-
# to use this feature. If not existant, only the string comparison
|
|
70
|
-
# is performed.
|
|
71
|
-
# Warning: Cosette is not maintained!
|
|
72
|
-
res = checkEquality()
|
|
73
|
-
```
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
### Changelog
|
|
84
|
-
|
|
85
|
-
##### V0.2.4
|
|
86
|
-
- Added more check methods for single parts of queries: checkColumns, checkTables, checkCondition, checkOrder, checkGroup, checkKeywords
|
|
87
|
-
|
|
88
|
-
##### V 0.2.3
|
|
89
|
-
- fix: ASC/DESC in ORDER BY (also with multiple columns and order directions), no direction treated as ASC
|
|
90
|
-
- Verified that ; and whitespaces, linebreaks at end of query are ignored
|
|
91
|
-
|
|
92
|
-
##### V 0.2.2
|
|
93
|
-
- Support LIKE
|
|
94
|
-
- Support '<=' and '>=' (geq and leq)
|
|
95
|
-
|
|
96
|
-
##### V 0.2.1
|
|
97
|
-
- Support LIMIT
|
|
98
|
-
|
|
99
|
-
##### V 0.1.9 + 0.2.0
|
|
100
|
-
- Support ORDER BY
|
|
101
|
-
|
|
102
|
-
##### V 0.1.8
|
|
103
|
-
- Fixed linebreak problems: Linebreaks are now converted into whitespaces before parsing where tokens
|
|
104
|
-
|
|
105
|
-
##### V 0.1.6 + V 0.1.7
|
|
106
|
-
- Fixed import error to ensure imports working in different environments
|
|
107
|
-
|
|
108
|
-
##### V 0.1.4 + V 0.1.5
|
|
109
|
-
- Chained conditions (with AND,OR and Paranthesises) in WHERE statement
|
|
110
|
-
- Aggregate Functions
|
|
111
|
-
|
|
112
|
-
##### V 0.1.3
|
|
113
|
-
- SELECT: columns with our without table prefix
|
|
114
|
-
- FROM: one or more table from DB; no queries as tables!
|
|
115
|
-
- WHERE: single conditions; no Paranthesises!
|
|
116
|
-
- GROUP BY one or more columns
|
|
117
|
-
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
from setuptools import setup, find_packages
|
|
2
|
-
|
|
3
|
-
with open("README.md", "r") as fh:
|
|
4
|
-
description = fh.read()
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
setup(
|
|
8
|
-
name='sql_testing_tools',
|
|
9
|
-
version='0.2.4.a',
|
|
10
|
-
packages=find_packages(),
|
|
11
|
-
install_requires=[
|
|
12
|
-
'sqlparse>=0.5.1',
|
|
13
|
-
'requests>=2.32.3'
|
|
14
|
-
],
|
|
15
|
-
long_description=description,
|
|
16
|
-
long_description_content_type="text/markdown",
|
|
17
|
-
package_data={
|
|
18
|
-
'sql_testing_tools.databases': [
|
|
19
|
-
'databases/*.db'#,
|
|
20
|
-
#'./databases/bayern.db',
|
|
21
|
-
#'./databases/film_fernsehen.db',
|
|
22
|
-
#'./databases/ladepunkte.db',
|
|
23
|
-
#'./databases/straftaten.db',
|
|
24
|
-
]
|
|
25
|
-
},
|
|
26
|
-
include_package_data=True
|
|
27
|
-
)
|
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.2
|
|
2
|
-
Name: sql_testing_tools
|
|
3
|
-
Version: 0.2.4a0
|
|
4
|
-
Description-Content-Type: text/markdown
|
|
5
|
-
Requires-Dist: sqlparse>=0.5.1
|
|
6
|
-
Requires-Dist: requests>=2.32.3
|
|
7
|
-
Dynamic: description
|
|
8
|
-
Dynamic: description-content-type
|
|
9
|
-
Dynamic: requires-dist
|
|
10
|
-
|
|
11
|
-
A library that normalizes simple SQL queries and compares them first by equality of the normalized string and then using the cosette API.
|
|
12
|
-
|
|
13
|
-
### [Beta in Development!]
|
|
14
|
-
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-build.yml)
|
|
15
|
-
[](https://github.com/ValentinHerrmann/sql_testing_tools/actions/workflows/python-unittests.yml)
|
|
16
|
-
|
|
17
|
-
- Submit bug reports and features requests at: https://github.com/ValentinHerrmann/sql_testing_tools
|
|
18
|
-
- PyPi-Package available at: https://pypi.org/project/sql-testing-tools/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
### Getting started
|
|
23
|
-
|
|
24
|
-
Use the following code to import the SQL Testing Tools to your project:
|
|
25
|
-
``` python
|
|
26
|
-
# ensure to always use the latest version of sql_testing_tools
|
|
27
|
-
import os
|
|
28
|
-
os.system('pip install -U sql_testing_tools')
|
|
29
|
-
|
|
30
|
-
# import sql_testing_tools
|
|
31
|
-
import sql_testing_tools.BaseAccess as Ba
|
|
32
|
-
import sql_testing_tools.Helper as He
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
On global level of your test class, set the SQLite database you want to use (bases must be located in the repository of the test class, no DBs contained in sql_testing_tools).
|
|
36
|
-
``` python
|
|
37
|
-
import unittest
|
|
38
|
-
class TestClass(unittest.TestCase):
|
|
39
|
-
Ba.setDBName("databases/ladepunkte.db")
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
The following methods are available for use in test methods:
|
|
43
|
-
``` python
|
|
44
|
-
try:
|
|
45
|
-
Ba.runAndGetStringTable_fromFile("sqlfile.sql")
|
|
46
|
-
except Exception as e:
|
|
47
|
-
# the execution failed
|
|
48
|
-
# (usually due to syntax or database errors)
|
|
49
|
-
self.fail(e)
|
|
50
|
-
|
|
51
|
-
# (optional) set the files to be compared. The sql strings will
|
|
52
|
-
# be normalized and used for all following methods (to improve
|
|
53
|
-
# performance), until new files are set. Arguments that are
|
|
54
|
-
# None or "" are ignored and the sql string remains the same.
|
|
55
|
-
# Raises an Exception if one of the files is empty.
|
|
56
|
-
setup("sqlfile.sql","solution.sql")
|
|
57
|
-
|
|
58
|
-
# All following methods call setup(sql,sol) before executing
|
|
59
|
-
# anything else. Call without arguments to keep the last
|
|
60
|
-
# normalized sql strings (and improve performance).
|
|
61
|
-
# Each check was successfull if "" is returned. Returns a
|
|
62
|
-
# German error message if not.
|
|
63
|
-
# Each method compares the normalized string between the start
|
|
64
|
-
# keyword and the next keyword or ;
|
|
65
|
-
|
|
66
|
-
res = He.checkColumns() # starts to search at keyword "SELECT"
|
|
67
|
-
res = He.checkTables() # starts to search at keyword "FROM"
|
|
68
|
-
res = He.checkCondition() # starts to search at keyword "WHERE"
|
|
69
|
-
res = He.checkOrder() # starts to search at keyword "ORDER BY"
|
|
70
|
-
res = He.checkGroup() # starts to search at keyword "GROUP BY"
|
|
71
|
-
|
|
72
|
-
# can not be called with new sql files
|
|
73
|
-
res = checkKeywords("startKeyword",["end","keywords"])
|
|
74
|
-
|
|
75
|
-
# compares equality of the full normalized sql strings and if
|
|
76
|
-
# not equal uses the Cosette API (cosette.cs.washington.edu)
|
|
77
|
-
# for comparison. A file 'cosette_apikey.txt' with only the
|
|
78
|
-
# apikey in it on root level of the test repository is required
|
|
79
|
-
# to use this feature. If not existant, only the string comparison
|
|
80
|
-
# is performed.
|
|
81
|
-
# Warning: Cosette is not maintained!
|
|
82
|
-
res = checkEquality()
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
### Changelog
|
|
94
|
-
|
|
95
|
-
##### V0.2.4
|
|
96
|
-
- Added more check methods for single parts of queries: checkColumns, checkTables, checkCondition, checkOrder, checkGroup, checkKeywords
|
|
97
|
-
|
|
98
|
-
##### V 0.2.3
|
|
99
|
-
- fix: ASC/DESC in ORDER BY (also with multiple columns and order directions), no direction treated as ASC
|
|
100
|
-
- Verified that ; and whitespaces, linebreaks at end of query are ignored
|
|
101
|
-
|
|
102
|
-
##### V 0.2.2
|
|
103
|
-
- Support LIKE
|
|
104
|
-
- Support '<=' and '>=' (geq and leq)
|
|
105
|
-
|
|
106
|
-
##### V 0.2.1
|
|
107
|
-
- Support LIMIT
|
|
108
|
-
|
|
109
|
-
##### V 0.1.9 + 0.2.0
|
|
110
|
-
- Support ORDER BY
|
|
111
|
-
|
|
112
|
-
##### V 0.1.8
|
|
113
|
-
- Fixed linebreak problems: Linebreaks are now converted into whitespaces before parsing where tokens
|
|
114
|
-
|
|
115
|
-
##### V 0.1.6 + V 0.1.7
|
|
116
|
-
- Fixed import error to ensure imports working in different environments
|
|
117
|
-
|
|
118
|
-
##### V 0.1.4 + V 0.1.5
|
|
119
|
-
- Chained conditions (with AND,OR and Paranthesises) in WHERE statement
|
|
120
|
-
- Aggregate Functions
|
|
121
|
-
|
|
122
|
-
##### V 0.1.3
|
|
123
|
-
- SELECT: columns with our without table prefix
|
|
124
|
-
- FROM: one or more table from DB; no queries as tables!
|
|
125
|
-
- WHERE: single conditions; no Paranthesises!
|
|
126
|
-
- GROUP BY one or more columns
|
|
127
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools.egg-info/requires.txt
RENAMED
|
File without changes
|
{sql_testing_tools-0.2.4a0 → sql_testing_tools-0.2.6}/sql_testing_tools.egg-info/top_level.txt
RENAMED
|
File without changes
|