dbis-functional-dependencies 0.0.7__py3-none-any.whl → 1.0.0__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.
@@ -0,0 +1,113 @@
1
+ """
2
+ Created on 2022-06-11
3
+ @author: wf
4
+ """
5
+ import time
6
+ from dbis_functional_dependencies.BCNF import FunctionalDependencySet
7
+ from lodstorage.sql import SQLDB
8
+
9
+
10
+ class FDCheck:
11
+ """
12
+ check functional dependencies for a tabular dataset in list of dicts form
13
+ """
14
+
15
+ def __init__(self, lod: list, debug: bool = False):
16
+ """
17
+ construct me with the given list of dicts
18
+
19
+ Args:
20
+ lod(list): the list of dicts (table) to check
21
+ debug(bool): if true switch on debugging
22
+ """
23
+ self.lod = lod
24
+ self.debug = debug
25
+ self.entityInfo = None
26
+
27
+ def createDatabase(
28
+ self,
29
+ entityName,
30
+ primaryKey=None,
31
+ executeMany=True,
32
+ fixNone=False,
33
+ fixDates=False,
34
+ debug=False,
35
+ doClose=True,
36
+ ):
37
+ """
38
+ create a database for my list of Records
39
+
40
+ Args:
41
+ entityName(string): the name of the entity type to be used as a table name
42
+ primaryKey(string): the name of the key / column to be used as a primary key
43
+ executeMany(boolean): True if executeMany mode of sqlite3 should be used
44
+ fixNone(boolean): fix dict entries that are undefined to have a "None" entry
45
+ debug(boolean): True if debug information e.g. CREATE TABLE and INSERT INTO commands should be shown
46
+ doClose(boolean): True if the connection should be closed
47
+
48
+ """
49
+ size = len(self.lod)
50
+ if self.debug:
51
+ print(
52
+ "%s size is %d fixNone is %r fixDates is: %r"
53
+ % (entityName, size, fixNone, fixDates)
54
+ )
55
+ self.sqlDB = SQLDB(debug=debug, errorDebug=True)
56
+ entityInfo = self.sqlDB.createTable(self.lod, entityName, primaryKey)
57
+ startTime = time.time()
58
+ self.sqlDB.store(self.lod, entityInfo, executeMany=executeMany, fixNone=fixNone)
59
+ elapsed = (
60
+ 0.000000000001 if time.time() - startTime == 0 else time.time() - startTime
61
+ )
62
+ if self.debug:
63
+ print(
64
+ "adding %d %s records took %5.3f s => %5.f records/s"
65
+ % (size, entityName, elapsed, size / elapsed)
66
+ )
67
+ if self.debug:
68
+ resultList = self.sqlDB.queryAll(entityInfo, fixDates=fixDates)
69
+ print(
70
+ "selecting %d %s records took %5.3f s => %5.f records/s"
71
+ % (len(resultList), entityName, elapsed, len(resultList) / elapsed)
72
+ )
73
+ if doClose:
74
+ self.sqlDB.close()
75
+ self.entityInfo = entityInfo
76
+ return entityInfo
77
+
78
+ def findFDs(self):
79
+ """
80
+ find functional dependencies
81
+
82
+ https://github.com/gustavclausen/functional-dependency-finder/blob/master/main.py
83
+ Return:
84
+ FunctionalDependencySet: the set of functional dependencies
85
+ """
86
+ if self.entityInfo is None:
87
+ raise Exception("createDataBase needed to supply entityInfo")
88
+ fields = list(self.entityInfo.typeMap.keys())
89
+ table_name = self.entityInfo.name
90
+ fds = FunctionalDependencySet()
91
+ for i, field in enumerate(fields):
92
+ attr1_var = chr(ord("A") + i)
93
+ fds.add_attribute(attr1_var, field)
94
+ for i, field in enumerate(fields):
95
+ attr1_var = chr(ord("A") + i)
96
+ for j in range(0, len(fields)):
97
+ if i == j:
98
+ continue
99
+
100
+ field_1 = fields[i]
101
+ field_2 = fields[j]
102
+ attr2_var = chr(ord("A") + j)
103
+ sql = f"SELECT {field_1}, COUNT(DISTINCT {field_2}) c FROM {table_name} GROUP BY {field_1} HAVING c > 1"
104
+ hits = self.sqlDB.query(sql)
105
+ 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
111
+ fds.add_dependency(attr1_var, attr2_var)
112
+ self.fds = fds
113
+ return fds
@@ -4,7 +4,7 @@
4
4
  # SPDX-License-Identifier: GPL-3.0-or-later
5
5
  # SPDX-FileCopyrightText: 2000-2022 Jens Lechtenbörger
6
6
 
7
- u"""Functional dependencies (FDs) are a major tool for database design.
7
+ """Functional dependencies (FDs) are a major tool for database design.
8
8
 
9
9
  Introduction
10
10
  ============
@@ -416,8 +416,9 @@ class FD(object):
416
416
  singleton.add(attr)
417
417
  if attr in self.lhs:
418
418
  # FDs of the form XA->A are trivial.
419
- logging.debug("rminimize: omitted trivial FD %s",
420
- FD(self.lhs, singleton))
419
+ logging.debug(
420
+ "rminimize: omitted trivial FD %s", FD(self.lhs, singleton)
421
+ )
421
422
  continue
422
423
  result.add(FD(self.lhs.copy(), singleton))
423
424
  return result
@@ -490,7 +491,10 @@ class FDSet(set):
490
491
  else:
491
492
  logging.debug(
492
493
  "lminimize: removed %s for rhs %s: new lhs: %s",
493
- attr, _set2string(rhs), _set2string(cand))
494
+ attr,
495
+ _set2string(rhs),
496
+ _set2string(cand),
497
+ )
494
498
  return cand
495
499
 
496
500
  def key(self, attributes=None):
@@ -527,8 +531,8 @@ class FDSet(set):
527
531
  if lhs != fdep.lhs:
528
532
  result.remove(fdep)
529
533
  logging.debug(
530
- "basis: replaced lhs in %s with %s",
531
- fdep, _set2string(lhs))
534
+ "basis: replaced lhs in %s with %s", fdep, _set2string(lhs)
535
+ )
532
536
  result.add(FD(lhs, fdep.rhs))
533
537
 
534
538
  # Third, remove redundant FDs. (An FD is redundant if it is implied
@@ -559,8 +563,7 @@ class RelSchema(object):
559
563
 
560
564
  def __str__(self):
561
565
  """Return relation schema in usual pair representation."""
562
- return "({}, {})".format(_set2string(self.attributes),
563
- _set2string(self.fds))
566
+ return "({}, {})".format(_set2string(self.attributes), _set2string(self.fds))
564
567
 
565
568
  def key(self):
566
569
  """Return a key."""
@@ -631,6 +634,7 @@ def extract_by_lhs(basis, fdep):
631
634
 
632
635
 
633
636
  # Run doctests by default.
634
- if __name__ == '__main__':
637
+ if __name__ == "__main__":
635
638
  import doctest
636
- print(doctest.testmod())
639
+
640
+ print(doctest.testmod())
@@ -0,0 +1,207 @@
1
+ """
2
+ Created on 2022-06-08
3
+
4
+ @author: wf
5
+ """
6
+ from enum import Enum
7
+ import copy
8
+
9
+
10
+ class Notation(str, Enum):
11
+ """
12
+ a notation to be used for stringifcation
13
+ """
14
+
15
+ math = "LaTex math symbols"
16
+ utf8 = "UTF-8 Symbols"
17
+ plain = "plaintext ASCII"
18
+ short = "short notation without delimiters using juxtapositions"
19
+
20
+
21
+ class Set(set):
22
+ """
23
+ https://docs.python.org/3/tutorial/datastructures.html#sets
24
+ """
25
+
26
+ notation = Notation.plain
27
+
28
+ def __init__(self, *args, **kwargs):
29
+ """
30
+ constructor
31
+ """
32
+ super().__init__(*args, **kwargs)
33
+
34
+ def __str__(self):
35
+ text = Set.stringify_set(self, notation=Set.notation)
36
+ return text
37
+
38
+ @classmethod
39
+ def stringify_set(cls, pSet, notation: Notation):
40
+ """
41
+ return a string representation of the given set using the given delimiter
42
+
43
+ Args:
44
+ pSet(set): the set to stringify
45
+ delim(str): the delimiter to use
46
+ """
47
+ elementTexts = []
48
+ for elem in pSet:
49
+ elementTexts.append(str(elem))
50
+ sortedElements = sorted(elementTexts)
51
+ if len(sortedElements) == 0:
52
+ # empty set
53
+ if notation == Notation.math:
54
+ text = "\emptyset"
55
+ else:
56
+ text = "∅"
57
+ else:
58
+ elementDelim = ","
59
+ if notation == Notation.short:
60
+ elementDelim = "" # Thin space would be better
61
+ if notation == Notation.short:
62
+ text = ""
63
+ elif notation == Notation.math:
64
+ text = "\{"
65
+ else:
66
+ text = "{"
67
+
68
+ delim = ""
69
+ for element in sortedElements:
70
+ text += f"{delim}{element}"
71
+ delim = elementDelim
72
+ if notation == Notation.short:
73
+ pass
74
+ elif notation == Notation.math:
75
+ text += "\}"
76
+ else:
77
+ text += "}"
78
+ return text
79
+
80
+
81
+ class FD(object):
82
+ """A functional dependency with left- and right-hand side."""
83
+
84
+ notation = Notation.plain
85
+
86
+ def __init__(self, left, right):
87
+ """Create FD with left hand side and right hand side
88
+
89
+ Args:
90
+ left(object): set of attributes for the left hand side
91
+ right(object): set of attributes for the right hand side
92
+
93
+ """
94
+ self.left = Set(left)
95
+ self.right = Set(right)
96
+
97
+ def __str__(self):
98
+ """
99
+ convert me to a string
100
+
101
+ Return:
102
+ str: a string representation of myself
103
+ """
104
+ text = FD.stringify_FD(self, FD.notation)
105
+ return text
106
+
107
+ @classmethod
108
+ def stringify_FD(cls, fd, notation: Notation):
109
+ """
110
+ Return:
111
+ a string representation of the given Functional Dependency
112
+ """
113
+ setNotation = Notation.short
114
+ leftText = Set.stringify_set(fd.left, notation=setNotation)
115
+ rightText = Set.stringify_set(fd.right, notation=setNotation)
116
+ if notation == Notation.utf8:
117
+ to = "→"
118
+ elif notation == Notation.math:
119
+ to = " \to "
120
+ else:
121
+ to = "->"
122
+ text = f"{leftText}{to}{rightText}"
123
+ return text
124
+
125
+
126
+ class Attribute:
127
+ """
128
+ an Attribute e.g.
129
+ Example: Attribute('A', 'Wikidata identifier', 'Wikidata-Schlüssel')
130
+ """
131
+
132
+ def __init__(self, var_name: str, english_name: str, german_name: str):
133
+ """
134
+ constructor
135
+
136
+ Args:
137
+ var_name(str): the Variable name
138
+ english_name(str): the english name
139
+ german_name(str): the german name
140
+
141
+ """
142
+ self.var_name = var_name
143
+ self.german_name = german_name
144
+ self.english_name = english_name
145
+
146
+ def __str__(self):
147
+ text = f"{self.var_name}≡{self.english_name}≡{self.german_name}"
148
+ return text
149
+
150
+
151
+ class RelSchema(object):
152
+ """A relation schema consists of a set of attributes and a set of FDs.
153
+
154
+ Various normal forms exist to describe "good" schemata. Normalization
155
+ is the process of creating schemata that satisfy certain normal forms.
156
+ The class of synthesis algorithms targets 3NF.
157
+ """
158
+
159
+ def __init__(
160
+ self, attributes: Set, fds, name: str = "R", notation: Notation = None
161
+ ):
162
+ """
163
+ Construct relation schema with attributes and FDs.
164
+
165
+ Args:
166
+ attributes(list): a list of Attributes
167
+ fds(FunctionalDependencySet): a set of FDs
168
+ name(string): the name of the RelatonSchema
169
+ notation(Notation): the notation to use
170
+ """
171
+ if notation is None:
172
+ notation = Notation.utf8
173
+ self.notation = notation
174
+ self.attributes = attributes
175
+ self.fds = fds
176
+ self.name = name
177
+
178
+ def __str__(self):
179
+ text = RelSchema.stringify(self, self.notation)
180
+ return text
181
+
182
+ @classmethod
183
+ def stringify(cls, rs, notation):
184
+ """
185
+ return a textual representation of the given relational schema in the given notation
186
+ """
187
+ attrText = Set.stringify_set(rs.attributes, notation)
188
+ fds = copy.deepcopy(rs.fds)
189
+ fds.notation = notation
190
+ fdsText = str(fds)
191
+ rsSet = Set([attrText, fdsText])
192
+ rsSetText = Set.stringify_set(rsSet, notation=notation)
193
+ rsText = f"{rs.name}={rsSetText}"
194
+ return rsText
195
+
196
+ def findCandidateKeys(self):
197
+ """
198
+ find candidate keys
199
+ """
200
+ cklist = []
201
+ for foundKeySet in self.fds.find_candidate_keys():
202
+ keySet = Set()
203
+ for foundKey in foundKeySet:
204
+ attr = self.fds.attribute_map[foundKey]
205
+ keySet.update([attr])
206
+ cklist.append(keySet)
207
+ return cklist
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.1
2
+ Name: dbis-functional-dependencies
3
+ Version: 1.0.0
4
+ Summary: RWTH Aachen Computer Science i5/dbis assets for Lecture Datenbanken und Informationssysteme
5
+ Author-email: DBIS i5 RWTH Aachen <dbis-vl@dbis.rwth-aachen.de>
6
+ Project-URL: Homepage, https://git.rwth-aachen.de/i5/teaching/dbis/dbis-functional-dependencies
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Requires-Python: >=3.10
10
+ Description-Content-Type: text/markdown
11
+ License-File: LICENSE
12
+ Requires-Dist: graphviz ~=0.20
13
+ Requires-Dist: networkx ~=2.7
14
+ Requires-Dist: numpy ~=1.26
15
+ Requires-Dist: sphinx ~=7.2
16
+ Requires-Dist: sphinxcontrib-apidoc ~=0.4
17
+ Requires-Dist: functional-dependencies ~=1.3
18
+ Requires-Dist: build ~=1.0
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'
23
+ Provides-Extra: test
24
+ Requires-Dist: black ==23.12.1 ; extra == 'test'
25
+
26
+ # DBIS Functional Dependencies
27
+
28
+ Functional Dependencies and Normal Forms for Relational Databases
29
+
30
+ [![PyPI Status](https://img.shields.io/pypi/v/dbis-functional-dependencies.svg)](https://pypi.python.org/pypi/dbis-functional-dependencies/)
31
+ [![pypi](https://img.shields.io/pypi/pyversions/dbis-functional-dependencies)](https://pypi.org/project/dbis-functional-dependencies/)
32
+ [![License](https://img.shields.io/pypi/l/dbis-functional-dependencies)](https://www.apache.org/licenses/LICENSE-2.0)
33
+ [![Pipeline Status](https://git.rwth-aachen.de/i5/teaching/dbis/dbis-functional-dependencies/badges/main/pipeline.svg)](https://git.rwth-aachen.de/i5/teaching/dbis/dbis-functional-dependencies/-/packages)
34
+
35
+ This library provides a Python implementation of the [synthesis algorithm](https://de.wikipedia.org/wiki/Synthesealgorithmus) and decomposition algorithm according to the DBIS lecture. For more background and application of functional dependencies and the algorithms, see [Doku-FunctionalDependencies](https://git.rwth-aachen.de/i5/teaching/dbis-jupyter/dbis-ss-2023-test/-/blob/main/doku/Doku-FunctionalDependencies.ipynb).
36
+
37
+ # Features
38
+ - Create sets of Functional dependencies (FDSets).
39
+ - Calculate candidate keys of an FDSet.
40
+ - Calculate attribute closure of an attribute or set of attributes.
41
+ - Test whether an FDSet is in 2NF, 3NF or BCNF.
42
+ - Execute the synthesis algorithm to transform the FDSet into 3NF.
43
+ - Execute the decomposition algorithm to transform the FDSet into BCNF.
44
+ - Generate the closure $F^+$ of an FDSet $F$.
45
+ - Generate true/false questions w.r.t. synthesis and decomposition algorithm.
46
+
47
+ # Installation
48
+ Install via pip:
49
+ ```bash
50
+ pip install dbis-functional-dependencies
51
+ ```
52
+
53
+ # Usage
54
+ ### Creating an FDSet
55
+ Create a new instance of `FunctionalDependencySet`. The set of attributes is passed as parameter.
56
+ ```python
57
+ fdset = FunctionalDependencySet('ABCDE')
58
+ ```
59
+ You can add more attributes later by using the `add_attribute` function.
60
+ ```python
61
+ fdset.add_attribute('F')
62
+ ```
63
+ Add dependencies with the `add_dependency` function ...
64
+ ```python
65
+ fdset.add_dependency("AC", "DE")
66
+ fdset.add_dependency("DEF", "B")
67
+ fdset.add_dependency("B", "D")
68
+ ```
69
+ ... or remove them with the `remove_dependency` function.
70
+ ```python
71
+ fdset.remove_dependency("B", "D")
72
+ ```
73
+
74
+ Printing an FDSet shows the dependencies in a more readable form.
75
+ ```python
76
+ print(f"{fdset}")
77
+ ```
78
+
79
+ ### Attribute closure and candidate keys
80
+ Calculate the attribute closure of one or multiple attributes.
81
+ ```python
82
+ closureA = fdset.get_attr_closure('A')
83
+ closureAC = fdset.get_attr_closure('AC')
84
+ ```
85
+
86
+ Calculate all candidate keys.
87
+ ```python
88
+ ckeys = fdset.find_candidate_keys()
89
+ ```
90
+
91
+ ### Check for normal forms
92
+ Since we only work with schemas (no actual values for the attributes), we assume that a corresponding database is in 1NF.
93
+
94
+ Check whether the FDSet is in 2NF, 3NF or BCNF.
95
+ ```python
96
+ is2NF = fdset.is2NF()
97
+ is3NF = fdset.is3NF()
98
+ isBCNF = fdset.isBCNF()
99
+ ```
100
+
101
+ ### Execute the synthesis algorithm
102
+ Execute the synthesis algorithm on an FDSet to generate a corresponding list of FDSets in 3NF.
103
+ ```python
104
+ fdslist = fdset.synthesize()
105
+ ```
106
+ The algorithm performs the following steps:
107
+
108
+ 0. Find the candidate keys.
109
+ 1. Calculate the canonical cover.
110
+ - left reduction
111
+ - right reduction
112
+ - remove dependencies with empty rhs
113
+ - combine dependencies with same lhs
114
+ 2. Create a new relation for every dependency in the canonical cover.
115
+ 3. Create the optional key scheme if no candidate key is included in the attribute set of one of the relations of step 2.
116
+ 4. Remove subset relations.
117
+
118
+ You receive additional information on the steps of the algorithm by toggling the parameter `verbose`.
119
+ ```python
120
+ fdslist = fdset.synthesize(vebose=True)
121
+ ```
122
+ Alternatively, you can also execute the single steps with the following functions:
123
+ ```python
124
+ fdset_step.canonical_cover()
125
+ fdslist_step = fdset_step.create_new_fdsets()
126
+ fdslist_step_with_key = FunctionalDependencySet.create_optional_key_scheme(self, ckeys, fdslist_step)
127
+ reduced_fdslist_step = FunctionalDependencySet.remove_subset_relations(self, fdslist_step_with_key)
128
+ ```
129
+ The verbose option exists for all steps.
130
+
131
+ ### Execute the decomposition algorithm
132
+ Execute the decomposition algorithm on an FDSet to generate a corresponding decomposition of FDSets in BCNF.
133
+ ```python
134
+ fdslist = fdset.decompose2()
135
+ ```
136
+ Before performing the actual algorithm, the the closure of the FDSet is calculated.
137
+
138
+ ### Closure of an FDSet
139
+ Calculate the closure $F^+$ of an FDSet $F$.
140
+ ```python
141
+ fdset.completeFDsetToClosure()
142
+ ```
143
+ This function just adds dependencies with all subset combinations of the attribute set with their corresponding closures on the rhs of the dependency, so that no implicit dependency is missed by the decomposition algorithm.
144
+
145
+ ### Exercise generator
146
+ Generate true/false statements based on the different steps of the algorithms.
147
+ ```python
148
+ fdslist = fdset.synthesize(genEx=True)
149
+ ```
150
+ The `genEx` option is available for the following functions:
151
+ * `find_candidate_keys`
152
+ * `synthesize`
153
+ * `canonical_cover`
154
+ * `left_reduction`
155
+ * `right_reduction`
156
+ * `remove_empty_fds`
157
+ * `combine_fds`
158
+ * `create_new_fdsets`
159
+ * `create_optional_key_scheme`
160
+ * `remove_subset_relations`
161
+ * `decompose2`
162
+
163
+ ### Checking results against expected
164
+ Checks a given calculated step of an FDSet during the synthesis algorithm (according to the DBIS lecture) for correctness.
165
+ ```python
166
+ original = fdset.copy()
167
+ fdset.left_reduction()
168
+ original.isCorrectLeftReduction(fdset)
169
+ ```
170
+ For this purpose, the following functions exist:
171
+ * `isCorrectLeftReduction`
172
+ * `isCorrectRightReduction`
173
+ * `isCorrectRemovingEmptyFDs`
174
+ * `isCorrectCombinationOfDependencies`
175
+ * `isCorrectCanonicalCover`
176
+ * `isCorrectCreationOfNewFDS`
177
+
178
+ These functions are called on the FDSet with all steps before already calculated on it.
@@ -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=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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.36.2)
2
+ Generator: bdist_wheel (0.43.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -0,0 +1 @@
1
+ dbis_functional_dependencies
@@ -1,23 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: dbis-functional-dependencies
3
- Version: 0.0.7
4
- Summary: RWTH Aachen Computer Science i5/dbis assets for Lecture Datenbanken und Informationssysteme
5
- Home-page: https://git.rwth-aachen.de/i5/teaching/dbis-functional-dependencies
6
- Author: Wolfgang Fahl
7
- Author-email: fahl@dbis.rwth-aachen.de
8
- License: Apache
9
- Classifier: Programming Language :: Python
10
- Classifier: Programming Language :: Python :: 3.7
11
- Classifier: Programming Language :: Python :: 3.8
12
- Classifier: Programming Language :: Python :: 3.9
13
- Classifier: Programming Language :: Python :: 3.10
14
- Description-Content-Type: text/markdown
15
- License-File: LICENSE
16
-
17
- # dbis-functional-dependencies
18
-
19
- Functional Dependencies and Normal Forms for Relational Databases
20
-
21
- [![PyPI Status](https://img.shields.io/pypi/v/dbis-functional-dependencies.svg)](https://pypi.python.org/pypi/dbis-functional-dependencies/)
22
- [![pypi](https://img.shields.io/pypi/pyversions/dbis-functional-dependencies)](https://pypi.org/project/dbis-functional-dependencies/)
23
- [![License](https://img.shields.io/pypi/l/dbis-functional-dependencies)](https://www.apache.org/licenses/LICENSE-2.0)
@@ -1,10 +0,0 @@
1
- functional_dependencies/BCNF.py,sha256=O9mzLeUfOOD9891-DOl7soJmzEGpPEmyXRuJnfOLDhE,22485
2
- functional_dependencies/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- functional_dependencies/fdcheck.py,sha256=z1gk1DY0O6bATFCD0mQsrVRJ9FmcusQ0TmIPu97JMUk,3854
4
- functional_dependencies/fds.py,sha256=jYVc4Dlo8wZutIq7CUo5znIYoDuooCxu3U6qhVWRGhc,23990
5
- functional_dependencies/fdsbase.py,sha256=Lx2KO2W9LngGHJHK6bhapWJr7P72xaJ_SUDVyyrCaz8,5683
6
- dbis_functional_dependencies-0.0.7.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
7
- dbis_functional_dependencies-0.0.7.dist-info/METADATA,sha256=2U_HSE5_NVYgWAYbdgilZerfVil8tu6JG45BgvudbwE,1129
8
- dbis_functional_dependencies-0.0.7.dist-info/WHEEL,sha256=OqRkF0eY5GHssMorFjlbTIq072vpHpF60fIQA6lS9xA,92
9
- dbis_functional_dependencies-0.0.7.dist-info/top_level.txt,sha256=gdKnqm_LuTOPR2jukC8CfBSBQTbgvYbKJOSjJtM1woo,24
10
- dbis_functional_dependencies-0.0.7.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- functional_dependencies