structured2graph 0.1.1__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.
- __init__.py +47 -0
- core/__init__.py +23 -0
- core/hygm/__init__.py +74 -0
- core/hygm/hygm.py +2351 -0
- core/hygm/models/__init__.py +82 -0
- core/hygm/models/graph_models.py +667 -0
- core/hygm/models/llm_models.py +229 -0
- core/hygm/models/operations.py +176 -0
- core/hygm/models/sources.py +68 -0
- core/hygm/models/user_operations.py +139 -0
- core/hygm/strategies/__init__.py +17 -0
- core/hygm/strategies/base.py +36 -0
- core/hygm/strategies/deterministic.py +262 -0
- core/hygm/strategies/llm.py +904 -0
- core/hygm/validation/__init__.py +38 -0
- core/hygm/validation/base.py +194 -0
- core/hygm/validation/graph_schema_validator.py +687 -0
- core/hygm/validation/memgraph_data_validator.py +991 -0
- core/migration_agent.py +1369 -0
- core/schema/spec.json +155 -0
- core/utils/meta_graph.py +108 -0
- database/__init__.py +36 -0
- database/adapters/__init__.py +11 -0
- database/adapters/memgraph.py +318 -0
- database/adapters/mysql.py +311 -0
- database/adapters/postgresql.py +335 -0
- database/analyzer.py +396 -0
- database/factory.py +219 -0
- database/models.py +209 -0
- main.py +518 -0
- query_generation/__init__.py +20 -0
- query_generation/cypher_generator.py +129 -0
- query_generation/schema_utilities.py +88 -0
- structured2graph-0.1.1.dist-info/METADATA +197 -0
- structured2graph-0.1.1.dist-info/RECORD +41 -0
- structured2graph-0.1.1.dist-info/WHEEL +4 -0
- structured2graph-0.1.1.dist-info/entry_points.txt +2 -0
- structured2graph-0.1.1.dist-info/licenses/LICENSE +21 -0
- utils/__init__.py +57 -0
- utils/config.py +235 -0
- utils/environment.py +404 -0
database/models.py
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Database data models.
|
|
3
|
+
|
|
4
|
+
This module contains all the data structures used to represent
|
|
5
|
+
database schema information in a standardized way.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from typing import Dict, List, Any, Optional
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TableType(Enum):
|
|
14
|
+
"""Enumeration of table types."""
|
|
15
|
+
|
|
16
|
+
ENTITY = "entity"
|
|
17
|
+
JOIN = "join"
|
|
18
|
+
VIEW = "view"
|
|
19
|
+
LOOKUP = "lookup"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class ColumnInfo:
|
|
24
|
+
"""Standardized column information across different database systems."""
|
|
25
|
+
|
|
26
|
+
name: str
|
|
27
|
+
data_type: str
|
|
28
|
+
is_nullable: bool
|
|
29
|
+
is_primary_key: bool
|
|
30
|
+
is_foreign_key: bool
|
|
31
|
+
default_value: Optional[Any] = None
|
|
32
|
+
auto_increment: bool = False
|
|
33
|
+
max_length: Optional[int] = None
|
|
34
|
+
precision: Optional[int] = None
|
|
35
|
+
scale: Optional[int] = None
|
|
36
|
+
|
|
37
|
+
def to_hygm_format(self) -> Dict[str, Any]:
|
|
38
|
+
"""Convert to HyGM-compatible format."""
|
|
39
|
+
# Determine key type
|
|
40
|
+
key_type = ""
|
|
41
|
+
if self.is_primary_key:
|
|
42
|
+
key_type = "PRI"
|
|
43
|
+
elif self.is_foreign_key:
|
|
44
|
+
key_type = "MUL" # MySQL convention for foreign keys
|
|
45
|
+
|
|
46
|
+
# Determine null constraint
|
|
47
|
+
null_constraint = "NO" if not self.is_nullable else "YES"
|
|
48
|
+
|
|
49
|
+
# Build type string with length/precision info
|
|
50
|
+
type_str = self.data_type
|
|
51
|
+
if self.max_length:
|
|
52
|
+
type_str += f"({self.max_length})"
|
|
53
|
+
elif self.precision and self.scale:
|
|
54
|
+
type_str += f"({self.precision},{self.scale})"
|
|
55
|
+
elif self.precision:
|
|
56
|
+
type_str += f"({self.precision})"
|
|
57
|
+
|
|
58
|
+
# Build extra field
|
|
59
|
+
extra = ""
|
|
60
|
+
if self.auto_increment:
|
|
61
|
+
extra = "auto_increment"
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
"field": self.name,
|
|
65
|
+
"type": type_str,
|
|
66
|
+
"null": null_constraint,
|
|
67
|
+
"key": key_type,
|
|
68
|
+
"default": self.default_value,
|
|
69
|
+
"extra": extra,
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@dataclass
|
|
74
|
+
class ForeignKeyInfo:
|
|
75
|
+
"""Standardized foreign key information."""
|
|
76
|
+
|
|
77
|
+
column_name: str
|
|
78
|
+
referenced_table: str
|
|
79
|
+
referenced_column: str
|
|
80
|
+
constraint_name: Optional[str] = None
|
|
81
|
+
|
|
82
|
+
def to_hygm_format(self) -> Dict[str, Any]:
|
|
83
|
+
"""Convert to HyGM-compatible format."""
|
|
84
|
+
hygm_fk = {
|
|
85
|
+
"column": self.column_name,
|
|
86
|
+
"referenced_table": self.referenced_table,
|
|
87
|
+
"referenced_column": self.referenced_column,
|
|
88
|
+
}
|
|
89
|
+
if self.constraint_name:
|
|
90
|
+
hygm_fk["constraint_name"] = self.constraint_name
|
|
91
|
+
return hygm_fk
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass
|
|
95
|
+
class TableInfo:
|
|
96
|
+
"""Standardized table information."""
|
|
97
|
+
|
|
98
|
+
name: str
|
|
99
|
+
table_type: TableType
|
|
100
|
+
columns: List[ColumnInfo]
|
|
101
|
+
foreign_keys: List[ForeignKeyInfo]
|
|
102
|
+
row_count: int
|
|
103
|
+
primary_keys: List[str]
|
|
104
|
+
indexes: List[Dict[str, Any]]
|
|
105
|
+
|
|
106
|
+
def to_hygm_format(self) -> Dict[str, Any]:
|
|
107
|
+
"""Convert to HyGM-compatible format."""
|
|
108
|
+
# Format columns for HyGM
|
|
109
|
+
schema = [col.to_hygm_format() for col in self.columns]
|
|
110
|
+
|
|
111
|
+
# Format foreign keys for HyGM
|
|
112
|
+
foreign_keys = [fk.to_hygm_format() for fk in self.foreign_keys]
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
"schema": schema,
|
|
116
|
+
"foreign_keys": foreign_keys,
|
|
117
|
+
"type": self.table_type.value,
|
|
118
|
+
"row_count": self.row_count,
|
|
119
|
+
"primary_keys": self.primary_keys,
|
|
120
|
+
"indexes": self.indexes,
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@dataclass
|
|
125
|
+
class RelationshipInfo:
|
|
126
|
+
"""Standardized relationship information."""
|
|
127
|
+
|
|
128
|
+
relationship_type: str # "one_to_many", "many_to_many", "one_to_one"
|
|
129
|
+
from_table: str
|
|
130
|
+
from_column: str
|
|
131
|
+
to_table: str
|
|
132
|
+
to_column: str
|
|
133
|
+
join_table: Optional[str] = None
|
|
134
|
+
join_from_column: Optional[str] = None
|
|
135
|
+
join_to_column: Optional[str] = None
|
|
136
|
+
additional_properties: Optional[List[str]] = None
|
|
137
|
+
|
|
138
|
+
def to_hygm_format(self) -> Dict[str, Any]:
|
|
139
|
+
"""Convert to HyGM-compatible format."""
|
|
140
|
+
hygm_rel = {
|
|
141
|
+
"type": self.relationship_type,
|
|
142
|
+
"from_table": self.from_table,
|
|
143
|
+
"from_column": self.from_column,
|
|
144
|
+
"to_table": self.to_table,
|
|
145
|
+
"to_column": self.to_column,
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
# Add many-to-many specific fields
|
|
149
|
+
if self.relationship_type == "many_to_many":
|
|
150
|
+
hygm_rel["join_table"] = self.join_table
|
|
151
|
+
hygm_rel["join_from_column"] = self.join_from_column
|
|
152
|
+
hygm_rel["join_to_column"] = self.join_to_column
|
|
153
|
+
hygm_rel["additional_properties"] = self.additional_properties or []
|
|
154
|
+
|
|
155
|
+
return hygm_rel
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
@dataclass
|
|
159
|
+
class DatabaseStructure:
|
|
160
|
+
"""Standardized database structure representation."""
|
|
161
|
+
|
|
162
|
+
tables: Dict[str, TableInfo]
|
|
163
|
+
entity_tables: Dict[str, TableInfo]
|
|
164
|
+
join_tables: Dict[str, TableInfo]
|
|
165
|
+
view_tables: Dict[str, TableInfo]
|
|
166
|
+
relationships: List[RelationshipInfo]
|
|
167
|
+
sample_data: Dict[str, List[Dict[str, Any]]]
|
|
168
|
+
table_counts: Dict[str, int]
|
|
169
|
+
database_name: str
|
|
170
|
+
database_type: str
|
|
171
|
+
|
|
172
|
+
def to_hygm_format(self) -> Dict[str, Any]:
|
|
173
|
+
"""
|
|
174
|
+
Convert to HyGM-compatible format.
|
|
175
|
+
|
|
176
|
+
This replaces the need for DatabaseDataInterface.get_hygm_data_structure()
|
|
177
|
+
"""
|
|
178
|
+
# Convert tables to HyGM format
|
|
179
|
+
hygm_tables = {}
|
|
180
|
+
hygm_entity_tables = {}
|
|
181
|
+
hygm_join_tables = {}
|
|
182
|
+
hygm_views = {}
|
|
183
|
+
|
|
184
|
+
for table_name, table_info in self.tables.items():
|
|
185
|
+
hygm_table = table_info.to_hygm_format()
|
|
186
|
+
hygm_tables[table_name] = hygm_table
|
|
187
|
+
|
|
188
|
+
# Categorize based on existing categorization
|
|
189
|
+
if table_name in self.view_tables:
|
|
190
|
+
hygm_views[table_name] = hygm_table
|
|
191
|
+
elif table_name in self.join_tables:
|
|
192
|
+
hygm_join_tables[table_name] = hygm_table
|
|
193
|
+
else:
|
|
194
|
+
hygm_entity_tables[table_name] = hygm_table
|
|
195
|
+
|
|
196
|
+
# Convert relationships to HyGM format
|
|
197
|
+
hygm_relationships = [rel.to_hygm_format() for rel in self.relationships]
|
|
198
|
+
|
|
199
|
+
return {
|
|
200
|
+
"tables": hygm_tables,
|
|
201
|
+
"entity_tables": hygm_entity_tables,
|
|
202
|
+
"join_tables": hygm_join_tables,
|
|
203
|
+
"views": hygm_views,
|
|
204
|
+
"relationships": hygm_relationships,
|
|
205
|
+
"sample_data": self.sample_data,
|
|
206
|
+
"table_counts": self.table_counts,
|
|
207
|
+
"database_type": self.database_type,
|
|
208
|
+
"database_name": self.database_name,
|
|
209
|
+
}
|