dbis-functional-dependencies 1.0.0__py3-none-any.whl → 1.0.2__py3-none-any.whl
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.
- dbis_functional_dependencies/fdcheck.py +85 -32
- {dbis_functional_dependencies-1.0.0.dist-info → dbis_functional_dependencies-1.0.2.dist-info}/METADATA +15 -14
- dbis_functional_dependencies-1.0.2.dist-info/RECORD +10 -0
- {dbis_functional_dependencies-1.0.0.dist-info → dbis_functional_dependencies-1.0.2.dist-info}/WHEEL +1 -1
- dbis_functional_dependencies-1.0.0.dist-info/RECORD +0 -10
- {dbis_functional_dependencies-1.0.0.dist-info → dbis_functional_dependencies-1.0.2.dist-info/licenses}/LICENSE +0 -0
- {dbis_functional_dependencies-1.0.0.dist-info → dbis_functional_dependencies-1.0.2.dist-info}/top_level.txt +0 -0
@@ -4,7 +4,7 @@ Created on 2022-06-11
|
|
4
4
|
"""
|
5
5
|
import time
|
6
6
|
from dbis_functional_dependencies.BCNF import FunctionalDependencySet
|
7
|
-
|
7
|
+
import sqlite3
|
8
8
|
|
9
9
|
|
10
10
|
class FDCheck:
|
@@ -23,6 +23,7 @@ class FDCheck:
|
|
23
23
|
self.lod = lod
|
24
24
|
self.debug = debug
|
25
25
|
self.entityInfo = None
|
26
|
+
self.conn = None
|
26
27
|
|
27
28
|
def createDatabase(
|
28
29
|
self,
|
@@ -52,28 +53,74 @@ class FDCheck:
|
|
52
53
|
"%s size is %d fixNone is %r fixDates is: %r"
|
53
54
|
% (entityName, size, fixNone, fixDates)
|
54
55
|
)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
|
57
|
+
self.conn = sqlite3.connect(":memory:")
|
58
|
+
cursor = self.conn.cursor()
|
59
|
+
|
60
|
+
# Infer schema
|
61
|
+
keys = self.lod[0].keys()
|
62
|
+
columns = []
|
63
|
+
for k in keys:
|
64
|
+
value = self.lod[0][k]
|
65
|
+
sql_type = (
|
66
|
+
"INTEGER"
|
67
|
+
if isinstance(value, int)
|
68
|
+
else "REAL"
|
69
|
+
if isinstance(value, float)
|
70
|
+
else "TEXT"
|
71
|
+
)
|
72
|
+
col_def = f"{k} {sql_type}"
|
73
|
+
if k == primaryKey:
|
74
|
+
col_def += " PRIMARY KEY"
|
75
|
+
columns.append(col_def)
|
76
|
+
create_stmt = f"CREATE TABLE {entityName} ({', '.join(columns)});"
|
77
|
+
if debug:
|
78
|
+
print(create_stmt)
|
79
|
+
cursor.execute(create_stmt)
|
80
|
+
|
81
|
+
# Prepare data
|
82
|
+
col_names = list(keys)
|
83
|
+
placeholders = ", ".join(["?"] * len(col_names))
|
84
|
+
insert_stmt = (
|
85
|
+
f"INSERT INTO {entityName} ({', '.join(col_names)}) VALUES ({placeholders})"
|
61
86
|
)
|
87
|
+
|
88
|
+
values = []
|
89
|
+
for row in self.lod:
|
90
|
+
values.append(tuple(row.get(k, None) for k in col_names))
|
91
|
+
|
92
|
+
startTime = time.time()
|
93
|
+
if executeMany:
|
94
|
+
cursor.executemany(insert_stmt, values)
|
95
|
+
else:
|
96
|
+
for v in values:
|
97
|
+
cursor.execute(insert_stmt, v)
|
98
|
+
self.conn.commit()
|
99
|
+
|
100
|
+
elapsed = max(1e-12, time.time() - startTime)
|
62
101
|
if self.debug:
|
63
102
|
print(
|
64
|
-
"adding
|
65
|
-
% (size, entityName, elapsed, size / elapsed)
|
103
|
+
f"adding {size} {entityName} records took {elapsed:.3f} s => {size/elapsed:.0f} records/s"
|
66
104
|
)
|
67
|
-
|
68
|
-
|
105
|
+
|
106
|
+
cursor.execute(f"SELECT * FROM {entityName}")
|
107
|
+
resultList = cursor.fetchall()
|
69
108
|
print(
|
70
|
-
"selecting
|
71
|
-
% (len(resultList), entityName, elapsed, len(resultList) / elapsed)
|
109
|
+
f"selecting {len(resultList)} {entityName} records took {elapsed:.3f} s => {len(resultList)/elapsed:.0f} records/s"
|
72
110
|
)
|
111
|
+
|
112
|
+
self.entityInfo = {
|
113
|
+
"name": entityName,
|
114
|
+
"typeMap": {k: type(self.lod[0][k]) for k in keys},
|
115
|
+
"fields": list(keys),
|
116
|
+
}
|
117
|
+
|
73
118
|
if doClose:
|
74
|
-
|
75
|
-
|
76
|
-
|
119
|
+
cursor.close()
|
120
|
+
self.conn.close()
|
121
|
+
self.conn = None
|
122
|
+
|
123
|
+
return self.entityInfo
|
77
124
|
|
78
125
|
def findFDs(self):
|
79
126
|
"""
|
@@ -83,31 +130,37 @@ class FDCheck:
|
|
83
130
|
Return:
|
84
131
|
FunctionalDependencySet: the set of functional dependencies
|
85
132
|
"""
|
86
|
-
if self.entityInfo is None:
|
87
|
-
raise Exception("
|
88
|
-
|
89
|
-
table_name = self.entityInfo
|
133
|
+
if self.entityInfo is None or not self.conn:
|
134
|
+
raise Exception("createDatabase must be called before findFDs")
|
135
|
+
|
136
|
+
table_name = self.entityInfo["name"]
|
137
|
+
fields = self.entityInfo["fields"]
|
138
|
+
|
90
139
|
fds = FunctionalDependencySet()
|
91
140
|
for i, field in enumerate(fields):
|
92
141
|
attr1_var = chr(ord("A") + i)
|
93
142
|
fds.add_attribute(attr1_var, field)
|
94
|
-
|
143
|
+
|
144
|
+
cursor = self.conn.cursor()
|
145
|
+
for i, field_1 in enumerate(fields):
|
95
146
|
attr1_var = chr(ord("A") + i)
|
96
|
-
for j in
|
147
|
+
for j, field_2 in enumerate(fields):
|
97
148
|
if i == j:
|
98
149
|
continue
|
99
|
-
|
100
|
-
field_1 = fields[i]
|
101
|
-
field_2 = fields[j]
|
102
150
|
attr2_var = chr(ord("A") + j)
|
103
|
-
sql =
|
104
|
-
|
151
|
+
sql = (
|
152
|
+
f"SELECT {field_1}, COUNT(DISTINCT {field_2}) as c\n"
|
153
|
+
f"FROM {table_name}\n"
|
154
|
+
f"GROUP BY {field_1}\n"
|
155
|
+
f"HAVING c > 1"
|
156
|
+
)
|
157
|
+
cursor.execute(sql)
|
158
|
+
hits = cursor.fetchall()
|
105
159
|
if self.debug:
|
106
|
-
print(f"{sql}\n{hits}")
|
107
|
-
|
108
|
-
if len(hits) == 0:
|
109
|
-
# Functional dependency found: it's not the case that there's more than one value (field_2)
|
110
|
-
# associated with field_1
|
160
|
+
print(f"{sql.strip()}\n{hits}")
|
161
|
+
if not hits:
|
111
162
|
fds.add_dependency(attr1_var, attr2_var)
|
163
|
+
|
164
|
+
cursor.close()
|
112
165
|
self.fds = fds
|
113
166
|
return fds
|
@@ -1,27 +1,28 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: dbis-functional-dependencies
|
3
|
-
Version: 1.0.
|
3
|
+
Version: 1.0.2
|
4
4
|
Summary: RWTH Aachen Computer Science i5/dbis assets for Lecture Datenbanken und Informationssysteme
|
5
5
|
Author-email: DBIS i5 RWTH Aachen <dbis-vl@dbis.rwth-aachen.de>
|
6
6
|
Project-URL: Homepage, https://git.rwth-aachen.de/i5/teaching/dbis/dbis-functional-dependencies
|
7
7
|
Classifier: Programming Language :: Python :: 3.10
|
8
8
|
Classifier: Programming Language :: Python :: 3.11
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
9
10
|
Requires-Python: >=3.10
|
10
11
|
Description-Content-Type: text/markdown
|
11
12
|
License-File: LICENSE
|
12
|
-
Requires-Dist: graphviz
|
13
|
-
Requires-Dist: networkx
|
14
|
-
Requires-Dist: numpy
|
15
|
-
Requires-Dist: sphinx
|
16
|
-
Requires-Dist: sphinxcontrib-apidoc
|
17
|
-
Requires-Dist: functional-dependencies
|
18
|
-
Requires-Dist: build
|
19
|
-
Requires-Dist: pylodstorage ~=0.4.11
|
20
|
-
Provides-Extra: build
|
21
|
-
Requires-Dist: twine ==4.* ; extra == 'build'
|
22
|
-
Requires-Dist: build ==1.* ; extra == 'build'
|
13
|
+
Requires-Dist: graphviz~=0.20
|
14
|
+
Requires-Dist: networkx~=2.7
|
15
|
+
Requires-Dist: numpy~=1.26
|
16
|
+
Requires-Dist: sphinx~=7.2
|
17
|
+
Requires-Dist: sphinxcontrib-apidoc~=0.4
|
18
|
+
Requires-Dist: functional-dependencies~=1.3
|
19
|
+
Requires-Dist: build~=1.0
|
23
20
|
Provides-Extra: test
|
24
|
-
Requires-Dist: black
|
21
|
+
Requires-Dist: black==23.12.1; extra == "test"
|
22
|
+
Provides-Extra: build
|
23
|
+
Requires-Dist: twine==6.*; extra == "build"
|
24
|
+
Requires-Dist: build==1.*; extra == "build"
|
25
|
+
Dynamic: license-file
|
25
26
|
|
26
27
|
# DBIS Functional Dependencies
|
27
28
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
dbis_functional_dependencies/BCNF.py,sha256=7EosTQTPl07W_UIiTp41PoxM9OTWMIzwA5cdQxbrkyM,68688
|
2
|
+
dbis_functional_dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
dbis_functional_dependencies/fdcheck.py,sha256=q_cvs--uhl5g6IZq5ral-Y_N3kwc3royti9kYb-dNV4,5238
|
4
|
+
dbis_functional_dependencies/fds.py,sha256=CLssS0L-3NxodSCtEcOMG5lxy0elLEaWkK8cT9IUszo,24021
|
5
|
+
dbis_functional_dependencies/fdsbase.py,sha256=wgt1tjM-EyD09v8Yf57UgoZB6ptvijIuE0WfgdKj43M,5767
|
6
|
+
dbis_functional_dependencies-1.0.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
7
|
+
dbis_functional_dependencies-1.0.2.dist-info/METADATA,sha256=fxj0g0tIkM8QCHdkBpUVRxjgMrbx6grhvYFb6VPV5vM,6797
|
8
|
+
dbis_functional_dependencies-1.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
9
|
+
dbis_functional_dependencies-1.0.2.dist-info/top_level.txt,sha256=Kxq61kOpu1YSAAigxyqE3_XCyftviQ1TW55Q1oxEP-4,29
|
10
|
+
dbis_functional_dependencies-1.0.2.dist-info/RECORD,,
|
@@ -1,10 +0,0 @@
|
|
1
|
-
dbis_functional_dependencies/BCNF.py,sha256=7EosTQTPl07W_UIiTp41PoxM9OTWMIzwA5cdQxbrkyM,68688
|
2
|
-
dbis_functional_dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
-
dbis_functional_dependencies/fdcheck.py,sha256=wNFJb2WZGkvQxN8Prbcd6DhuXYnQ4Zm9HsoLxc7RU7k,4082
|
4
|
-
dbis_functional_dependencies/fds.py,sha256=CLssS0L-3NxodSCtEcOMG5lxy0elLEaWkK8cT9IUszo,24021
|
5
|
-
dbis_functional_dependencies/fdsbase.py,sha256=wgt1tjM-EyD09v8Yf57UgoZB6ptvijIuE0WfgdKj43M,5767
|
6
|
-
dbis_functional_dependencies-1.0.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
7
|
-
dbis_functional_dependencies-1.0.0.dist-info/METADATA,sha256=zvpMH7aEjXT0x4umngOYQKEqpln54NgK4YXqCOTiH9w,6774
|
8
|
-
dbis_functional_dependencies-1.0.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
9
|
-
dbis_functional_dependencies-1.0.0.dist-info/top_level.txt,sha256=Kxq61kOpu1YSAAigxyqE3_XCyftviQ1TW55Q1oxEP-4,29
|
10
|
-
dbis_functional_dependencies-1.0.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|