py-auto-migrate 0.3.5__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.
- py_auto_migrate/__init__.py +3 -0
- py_auto_migrate/base_models/__init__.py +0 -0
- py_auto_migrate/base_models/base.py +18 -0
- py_auto_migrate/base_models/base_clickhouse.py +88 -0
- py_auto_migrate/base_models/base_dynamodb.py +67 -0
- py_auto_migrate/base_models/base_elasticsearch.py +52 -0
- py_auto_migrate/base_models/base_mariadb.py +40 -0
- py_auto_migrate/base_models/base_mongodb.py +70 -0
- py_auto_migrate/base_models/base_mssql.py +61 -0
- py_auto_migrate/base_models/base_mysql.py +51 -0
- py_auto_migrate/base_models/base_oracle.py +36 -0
- py_auto_migrate/base_models/base_postgressql.py +43 -0
- py_auto_migrate/base_models/base_redis.py +55 -0
- py_auto_migrate/base_models/base_sqlite.py +26 -0
- py_auto_migrate/cli.py +154 -0
- py_auto_migrate/insert_models/__init__.py +0 -0
- py_auto_migrate/insert_models/base.py +9 -0
- py_auto_migrate/insert_models/insert_clickhouse.py +95 -0
- py_auto_migrate/insert_models/insert_dynamodb.py +38 -0
- py_auto_migrate/insert_models/insert_elasticsearch.py +32 -0
- py_auto_migrate/insert_models/insert_mariadb.py +27 -0
- py_auto_migrate/insert_models/insert_mongodb.py +17 -0
- py_auto_migrate/insert_models/insert_mssql.py +41 -0
- py_auto_migrate/insert_models/insert_mysql.py +39 -0
- py_auto_migrate/insert_models/insert_oracle.py +38 -0
- py_auto_migrate/insert_models/insert_postgressql.py +30 -0
- py_auto_migrate/insert_models/insert_redis.py +23 -0
- py_auto_migrate/insert_models/insert_sqlite.py +19 -0
- py_auto_migrate/mapping.py +164 -0
- py_auto_migrate/migrate_models/__init__.py +0 -0
- py_auto_migrate/migrate_models/base.py +45 -0
- py_auto_migrate/migrate_models/migrate_clickhouse.py +83 -0
- py_auto_migrate/migrate_models/migrate_dynamodb.py +82 -0
- py_auto_migrate/migrate_models/migrate_elastic.py +83 -0
- py_auto_migrate/migrate_models/migrate_mariadb.py +82 -0
- py_auto_migrate/migrate_models/migrate_mongodb.py +85 -0
- py_auto_migrate/migrate_models/migrate_mssql.py +82 -0
- py_auto_migrate/migrate_models/migrate_mysql.py +83 -0
- py_auto_migrate/migrate_models/migrate_oracle.py +82 -0
- py_auto_migrate/migrate_models/migrate_postgresql.py +86 -0
- py_auto_migrate/migrate_models/migrate_redis.py +81 -0
- py_auto_migrate/migrate_models/migrate_sqlite.py +81 -0
- py_auto_migrate/shell.py +154 -0
- py_auto_migrate/utils/__init__.py +0 -0
- py_auto_migrate/utils/helpers.py +14 -0
- py_auto_migrate-0.3.5.dist-info/METADATA +146 -0
- py_auto_migrate-0.3.5.dist-info/RECORD +50 -0
- py_auto_migrate-0.3.5.dist-info/WHEEL +5 -0
- py_auto_migrate-0.3.5.dist-info/entry_points.txt +2 -0
- py_auto_migrate-0.3.5.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
class BaseModel(ABC):
|
|
4
|
+
|
|
5
|
+
def __init__(self, uri):
|
|
6
|
+
self.uri = uri
|
|
7
|
+
|
|
8
|
+
@abstractmethod
|
|
9
|
+
def _connect(self):
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
@abstractmethod
|
|
13
|
+
def get_tables(self):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
@abstractmethod
|
|
17
|
+
def read_table(self, table_name):
|
|
18
|
+
pass
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from clickhouse_driver import Client
|
|
3
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseClickHouse(BaseModel):
|
|
7
|
+
def __init__(self, clickhouse_uri):
|
|
8
|
+
super().__init__(clickhouse_uri)
|
|
9
|
+
self.user, self.password, self.host, self.port, self.db_name = self._parse_clickhouse_uri()
|
|
10
|
+
|
|
11
|
+
def _parse_clickhouse_uri(self):
|
|
12
|
+
if self.uri.startswith("clickhouse://"):
|
|
13
|
+
uri = self.uri.replace("clickhouse://", "")
|
|
14
|
+
else:
|
|
15
|
+
uri = self.uri
|
|
16
|
+
|
|
17
|
+
if "@" in uri:
|
|
18
|
+
auth_part, host_db_part = uri.split("@")
|
|
19
|
+
if ":" in auth_part:
|
|
20
|
+
user, password = auth_part.split(":")
|
|
21
|
+
else:
|
|
22
|
+
user, password = auth_part, ""
|
|
23
|
+
else:
|
|
24
|
+
user, password = "default", ""
|
|
25
|
+
host_db_part = uri
|
|
26
|
+
|
|
27
|
+
if "/" in host_db_part:
|
|
28
|
+
host_port, db_name = host_db_part.split("/", 1)
|
|
29
|
+
else:
|
|
30
|
+
host_port, db_name = host_db_part, ""
|
|
31
|
+
|
|
32
|
+
if ":" in host_port:
|
|
33
|
+
host, port = host_port.split(":")
|
|
34
|
+
port = int(port)
|
|
35
|
+
else:
|
|
36
|
+
host, port = host_port, 9000
|
|
37
|
+
|
|
38
|
+
return user, password, host, port, db_name
|
|
39
|
+
|
|
40
|
+
def _connect(self):
|
|
41
|
+
try:
|
|
42
|
+
client = Client(
|
|
43
|
+
host=self.host,
|
|
44
|
+
port=self.port,
|
|
45
|
+
user=self.user,
|
|
46
|
+
password=self.password,
|
|
47
|
+
database=self.db_name
|
|
48
|
+
)
|
|
49
|
+
client.execute('SELECT 1')
|
|
50
|
+
return client
|
|
51
|
+
except Exception as e:
|
|
52
|
+
print(f"❌ Error connecting to ClickHouse: {e}")
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
def get_tables(self):
|
|
56
|
+
client = self._connect()
|
|
57
|
+
if client is None:
|
|
58
|
+
return []
|
|
59
|
+
|
|
60
|
+
query = "SELECT name FROM system.tables WHERE database = %s"
|
|
61
|
+
try:
|
|
62
|
+
tables_result = client.execute(query, [self.db_name])
|
|
63
|
+
tables = [r[0] for r in tables_result]
|
|
64
|
+
client.disconnect()
|
|
65
|
+
return tables
|
|
66
|
+
except Exception as e:
|
|
67
|
+
print(f"❌ Error fetching tables: {e}")
|
|
68
|
+
return []
|
|
69
|
+
|
|
70
|
+
def read_table(self, table_name):
|
|
71
|
+
client = self._connect()
|
|
72
|
+
if client is None:
|
|
73
|
+
return pd.DataFrame()
|
|
74
|
+
|
|
75
|
+
query = f'SELECT * FROM "{table_name}"'
|
|
76
|
+
try:
|
|
77
|
+
data = client.execute(query)
|
|
78
|
+
columns = [desc[0] for desc in client.description_of_result_set]
|
|
79
|
+
|
|
80
|
+
client.disconnect()
|
|
81
|
+
|
|
82
|
+
df = pd.DataFrame(data, columns=columns)
|
|
83
|
+
if df.empty:
|
|
84
|
+
print(f"❌ Table '{table_name}' is empty.")
|
|
85
|
+
return df.fillna(0)
|
|
86
|
+
except Exception as e:
|
|
87
|
+
print(f"❌ Error reading table {table_name}: {e}")
|
|
88
|
+
return pd.DataFrame()
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import boto3
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from botocore.exceptions import ClientError
|
|
4
|
+
from urllib.parse import urlparse, parse_qs
|
|
5
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BaseDynamoDB(BaseModel):
|
|
9
|
+
def __init__(self, dynamo_uri):
|
|
10
|
+
super().__init__(dynamo_uri)
|
|
11
|
+
self._parse_uri()
|
|
12
|
+
|
|
13
|
+
def _parse_uri(self):
|
|
14
|
+
try:
|
|
15
|
+
parsed = urlparse(self.uri)
|
|
16
|
+
self.host = parsed.hostname
|
|
17
|
+
self.port = parsed.port
|
|
18
|
+
self.aws_access_key = parsed.username or None
|
|
19
|
+
self.aws_secret_key = parsed.password or None
|
|
20
|
+
self.table_prefix = parsed.path.lstrip('/') or 'default'
|
|
21
|
+
|
|
22
|
+
qs = parse_qs(parsed.query)
|
|
23
|
+
self.region_name = qs.get('region', [ 'us-west-2' ])[0]
|
|
24
|
+
|
|
25
|
+
except Exception as e:
|
|
26
|
+
self.aws_access_key = None
|
|
27
|
+
self.aws_secret_key = None
|
|
28
|
+
self.host = 'localhost'
|
|
29
|
+
self.port = 9000
|
|
30
|
+
self.table_prefix = 'default'
|
|
31
|
+
self.region_name = 'us-west-2'
|
|
32
|
+
|
|
33
|
+
def _connect(self):
|
|
34
|
+
try:
|
|
35
|
+
endpoint = f"http://{self.host}:{self.port}" if self.host and self.port else None
|
|
36
|
+
client = boto3.resource(
|
|
37
|
+
'dynamodb',
|
|
38
|
+
region_name=self.region_name,
|
|
39
|
+
aws_access_key_id=self.aws_access_key,
|
|
40
|
+
aws_secret_access_key=self.aws_secret_key,
|
|
41
|
+
endpoint_url=endpoint
|
|
42
|
+
)
|
|
43
|
+
return client
|
|
44
|
+
except Exception as e:
|
|
45
|
+
return None
|
|
46
|
+
|
|
47
|
+
def get_tables(self):
|
|
48
|
+
conn = self._connect()
|
|
49
|
+
if not conn:
|
|
50
|
+
return []
|
|
51
|
+
try:
|
|
52
|
+
tables = [t.name for t in conn.tables.all() if t.name.startswith(self.table_prefix)]
|
|
53
|
+
return tables
|
|
54
|
+
except ClientError as e:
|
|
55
|
+
return []
|
|
56
|
+
|
|
57
|
+
def read_table(self, table_name):
|
|
58
|
+
conn = self._connect()
|
|
59
|
+
if not conn:
|
|
60
|
+
return pd.DataFrame()
|
|
61
|
+
try:
|
|
62
|
+
table = conn.Table(table_name)
|
|
63
|
+
response = table.scan()
|
|
64
|
+
data = response.get("Items", [])
|
|
65
|
+
return pd.DataFrame(data)
|
|
66
|
+
except ClientError as e:
|
|
67
|
+
return pd.DataFrame()
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from elasticsearch import Elasticsearch
|
|
3
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseElasticsearch(BaseModel):
|
|
7
|
+
def __init__(self, es_uri):
|
|
8
|
+
super().__init__(es_uri)
|
|
9
|
+
|
|
10
|
+
def _connect(self):
|
|
11
|
+
try:
|
|
12
|
+
es = Elasticsearch(self.uri)
|
|
13
|
+
if not es.ping():
|
|
14
|
+
return None
|
|
15
|
+
return es
|
|
16
|
+
except Exception as e:
|
|
17
|
+
return None
|
|
18
|
+
|
|
19
|
+
def get_tables(self):
|
|
20
|
+
es = self._connect()
|
|
21
|
+
if es is None:
|
|
22
|
+
return []
|
|
23
|
+
try:
|
|
24
|
+
indices = es.indices.get_alias("*").keys()
|
|
25
|
+
return list(indices)
|
|
26
|
+
except Exception as e:
|
|
27
|
+
return []
|
|
28
|
+
|
|
29
|
+
def read_table(self, index_name):
|
|
30
|
+
es = self._connect()
|
|
31
|
+
if es is None:
|
|
32
|
+
return pd.DataFrame()
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
query = {
|
|
36
|
+
"query": {"match_all": {}},
|
|
37
|
+
"size": 10000
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
result = es.search(index=index_name, body=query)
|
|
41
|
+
|
|
42
|
+
hits = result.get("hits", {}).get("hits", [])
|
|
43
|
+
if not hits:
|
|
44
|
+
return pd.DataFrame()
|
|
45
|
+
|
|
46
|
+
records = [hit["_source"] | {"_id": hit["_id"]} for hit in hits]
|
|
47
|
+
|
|
48
|
+
df = pd.DataFrame(records)
|
|
49
|
+
return df
|
|
50
|
+
|
|
51
|
+
except Exception as e:
|
|
52
|
+
return pd.DataFrame()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import pymysql
|
|
3
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseMariaDB(BaseModel):
|
|
7
|
+
def __init__(self, maria_uri):
|
|
8
|
+
super().__init__(maria_uri)
|
|
9
|
+
|
|
10
|
+
def _parse_maria_uri(self, maria_uri=None):
|
|
11
|
+
if maria_uri is None:
|
|
12
|
+
maria_uri = self.uri
|
|
13
|
+
maria_uri = maria_uri.replace("mariadb://", "").replace("mysql://", "")
|
|
14
|
+
user_pass, host_db = maria_uri.split("@")
|
|
15
|
+
user, password = user_pass.split(":")
|
|
16
|
+
host_port, db_name = host_db.split("/")
|
|
17
|
+
if ":" in host_port:
|
|
18
|
+
host, port = host_port.split(":")
|
|
19
|
+
port = int(port)
|
|
20
|
+
else:
|
|
21
|
+
host, port = host_port, 3306
|
|
22
|
+
return host, port, user, password, db_name
|
|
23
|
+
|
|
24
|
+
def _connect(self):
|
|
25
|
+
host, port, user, password, db_name = self._parse_maria_uri()
|
|
26
|
+
return pymysql.connect(host=host, port=port, user=user, password=password, database=db_name)
|
|
27
|
+
|
|
28
|
+
def get_tables(self):
|
|
29
|
+
conn = self._connect()
|
|
30
|
+
cur = conn.cursor()
|
|
31
|
+
cur.execute("SHOW TABLES")
|
|
32
|
+
tables = [r[0] for r in cur.fetchall()]
|
|
33
|
+
conn.close()
|
|
34
|
+
return tables
|
|
35
|
+
|
|
36
|
+
def read_table(self, table_name):
|
|
37
|
+
conn = self._connect()
|
|
38
|
+
df = pd.read_sql(f"SELECT * FROM `{table_name}`", conn)
|
|
39
|
+
conn.close()
|
|
40
|
+
return df.fillna(0)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from pymongo import MongoClient
|
|
3
|
+
from urllib.parse import urlparse
|
|
4
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BaseMongoDB(BaseModel):
|
|
8
|
+
def __init__(self, mongo_uri):
|
|
9
|
+
super().__init__(mongo_uri)
|
|
10
|
+
|
|
11
|
+
def _connect(self):
|
|
12
|
+
try:
|
|
13
|
+
parsed = urlparse(self.uri)
|
|
14
|
+
db_name = parsed.path.lstrip('/')
|
|
15
|
+
|
|
16
|
+
if not db_name:
|
|
17
|
+
db_name = 'admin'
|
|
18
|
+
|
|
19
|
+
auth_source = 'admin'
|
|
20
|
+
|
|
21
|
+
if parsed.query:
|
|
22
|
+
query_params = dict(param.split('=')
|
|
23
|
+
for param in parsed.query.split('&') if '=' in param)
|
|
24
|
+
auth_source = query_params.get('authSource', 'admin')
|
|
25
|
+
|
|
26
|
+
client = MongoClient(
|
|
27
|
+
host=parsed.hostname,
|
|
28
|
+
port=parsed.port or 27017,
|
|
29
|
+
username=parsed.username,
|
|
30
|
+
password=parsed.password,
|
|
31
|
+
authSource=auth_source,
|
|
32
|
+
serverSelectionTimeoutMS=5000
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
client.admin.command('ping')
|
|
36
|
+
return client[db_name]
|
|
37
|
+
|
|
38
|
+
except Exception as e:
|
|
39
|
+
print(f"❌ MongoDB Connection Error: {e}")
|
|
40
|
+
return None
|
|
41
|
+
|
|
42
|
+
def get_tables(self):
|
|
43
|
+
db = self._connect()
|
|
44
|
+
if db is None:
|
|
45
|
+
return []
|
|
46
|
+
try:
|
|
47
|
+
return db.list_collection_names()
|
|
48
|
+
except Exception as e:
|
|
49
|
+
print(f"❌ Error getting collections: {e}")
|
|
50
|
+
return []
|
|
51
|
+
|
|
52
|
+
def read_table(self, collection_name):
|
|
53
|
+
db = self._connect()
|
|
54
|
+
if db is None:
|
|
55
|
+
return pd.DataFrame()
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
data = list(db[collection_name].find())
|
|
59
|
+
if not data:
|
|
60
|
+
print(f"❌ Collection '{collection_name}' is empty.")
|
|
61
|
+
return pd.DataFrame()
|
|
62
|
+
|
|
63
|
+
df = pd.DataFrame(data)
|
|
64
|
+
if "_id" in df.columns:
|
|
65
|
+
df = df.drop(columns="_id")
|
|
66
|
+
|
|
67
|
+
return df.fillna(0)
|
|
68
|
+
except Exception as e:
|
|
69
|
+
print(f"❌ Error reading collection '{collection_name}': {e}")
|
|
70
|
+
return pd.DataFrame()
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import pyodbc
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseMSSQL(BaseModel):
|
|
7
|
+
def __init__(self, mssql_uri):
|
|
8
|
+
super().__init__(mssql_uri)
|
|
9
|
+
|
|
10
|
+
def _parse_mssql_uri(self, uri=None):
|
|
11
|
+
if uri is None:
|
|
12
|
+
uri = self.uri
|
|
13
|
+
uri = uri.replace("mssql://", "")
|
|
14
|
+
if uri.startswith("@") or "@" not in uri:
|
|
15
|
+
if uri.startswith("@"):
|
|
16
|
+
uri = uri[1:]
|
|
17
|
+
host_port, db_name = uri.split("/", 1)
|
|
18
|
+
if ":" in host_port:
|
|
19
|
+
host, port = host_port.split(":")
|
|
20
|
+
else:
|
|
21
|
+
host, port = host_port, "1433"
|
|
22
|
+
return {"auth": "windows", "host": host, "port": port, "database": db_name}
|
|
23
|
+
else:
|
|
24
|
+
user_pass, host_db = uri.split("@", 1)
|
|
25
|
+
user, password = user_pass.split(":", 1)
|
|
26
|
+
host_port, db_name = host_db.split("/", 1)
|
|
27
|
+
if ":" in host_port:
|
|
28
|
+
host, port = host_port.split(":")
|
|
29
|
+
else:
|
|
30
|
+
host, port = host_port, "1433"
|
|
31
|
+
return {
|
|
32
|
+
"auth": "sql",
|
|
33
|
+
"host": host,
|
|
34
|
+
"port": port,
|
|
35
|
+
"database": db_name,
|
|
36
|
+
"user": user,
|
|
37
|
+
"password": password
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
def _connect(self):
|
|
41
|
+
cfg = self._parse_mssql_uri()
|
|
42
|
+
if cfg["auth"] == "windows":
|
|
43
|
+
conn_str = f"DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={cfg['host']},{cfg['port']};DATABASE={cfg['database']};Trusted_Connection=yes;"
|
|
44
|
+
else:
|
|
45
|
+
conn_str = f"DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={cfg['host']},{cfg['port']};DATABASE={cfg['database']};UID={cfg['user']};PWD={cfg['password']};"
|
|
46
|
+
return pyodbc.connect(conn_str)
|
|
47
|
+
|
|
48
|
+
def get_tables(self):
|
|
49
|
+
conn = self._connect()
|
|
50
|
+
cur = conn.cursor()
|
|
51
|
+
cur.execute(
|
|
52
|
+
"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE TABLE'")
|
|
53
|
+
tables = [r[0] for r in cur.fetchall()]
|
|
54
|
+
conn.close()
|
|
55
|
+
return tables
|
|
56
|
+
|
|
57
|
+
def read_table(self, table_name):
|
|
58
|
+
conn = self._connect()
|
|
59
|
+
df = pd.read_sql(f"SELECT * FROM [{table_name}]", conn)
|
|
60
|
+
conn.close()
|
|
61
|
+
return df.fillna(0)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from mysqlSaver import Connection
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseMySQL(BaseModel):
|
|
7
|
+
def __init__(self, mysql_uri):
|
|
8
|
+
super().__init__(mysql_uri)
|
|
9
|
+
|
|
10
|
+
def _parse_mysql_uri(self, uri=None):
|
|
11
|
+
if uri is None:
|
|
12
|
+
uri = self.uri
|
|
13
|
+
uri = uri.replace("mysql://", "")
|
|
14
|
+
user_pass, host_db = uri.split("@")
|
|
15
|
+
user, password = user_pass.split(":")
|
|
16
|
+
host_port, db_name = host_db.split("/")
|
|
17
|
+
|
|
18
|
+
if ":" in host_port:
|
|
19
|
+
host, port = host_port.split(":")
|
|
20
|
+
port = int(port)
|
|
21
|
+
else:
|
|
22
|
+
host, port = host_port, 3306
|
|
23
|
+
|
|
24
|
+
return host, port, user, password, db_name
|
|
25
|
+
|
|
26
|
+
def _connect(self, db_name=None):
|
|
27
|
+
host, port, user, password, uri_db = self._parse_mysql_uri()
|
|
28
|
+
if db_name is None:
|
|
29
|
+
db_name = uri_db
|
|
30
|
+
return Connection.connect(host, port, user, password, db_name)
|
|
31
|
+
|
|
32
|
+
def get_tables(self):
|
|
33
|
+
conn = self._connect()
|
|
34
|
+
cursor = conn.cursor()
|
|
35
|
+
cursor.execute("SHOW TABLES")
|
|
36
|
+
tables = [row[0] for row in cursor.fetchall()]
|
|
37
|
+
conn.close()
|
|
38
|
+
return tables
|
|
39
|
+
|
|
40
|
+
def read_table(self, table_name):
|
|
41
|
+
conn = self._connect()
|
|
42
|
+
cursor = conn.cursor()
|
|
43
|
+
cursor.execute(f"SELECT * FROM `{table_name}`")
|
|
44
|
+
data = cursor.fetchall()
|
|
45
|
+
columns = [desc[0] for desc in cursor.description]
|
|
46
|
+
conn.close()
|
|
47
|
+
|
|
48
|
+
df = pd.DataFrame(data, columns=columns)
|
|
49
|
+
if df.empty:
|
|
50
|
+
print(f"❌ Table '{table_name}' is empty.")
|
|
51
|
+
return df.fillna(0)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import oracledb
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseOracle(BaseModel):
|
|
7
|
+
def __init__(self, oracle_uri):
|
|
8
|
+
super().__init__(oracle_uri)
|
|
9
|
+
|
|
10
|
+
def _parse_oracle_uri(self):
|
|
11
|
+
uri = self.uri.replace("oracle://", "")
|
|
12
|
+
user_pass, host_db = uri.split("@")
|
|
13
|
+
user, password = user_pass.split(":")
|
|
14
|
+
host_port, db_name = host_db.split("/")
|
|
15
|
+
if ":" in host_port:
|
|
16
|
+
host, port = host_port.split(":")
|
|
17
|
+
else:
|
|
18
|
+
host, port = host_port, "1521"
|
|
19
|
+
return user, password, host, port, db_name
|
|
20
|
+
|
|
21
|
+
def _connect(self):
|
|
22
|
+
user, password, host, port, db_name = self._parse_oracle_uri()
|
|
23
|
+
dsn = f"{host}:{port}/{db_name}"
|
|
24
|
+
return oracledb.connect(user=user, password=password, dsn=dsn)
|
|
25
|
+
|
|
26
|
+
def get_tables(self):
|
|
27
|
+
with self._connect() as conn:
|
|
28
|
+
cursor = conn.cursor()
|
|
29
|
+
cursor.execute("SELECT table_name FROM user_tables")
|
|
30
|
+
tables = [r[0] for r in cursor.fetchall()]
|
|
31
|
+
return tables
|
|
32
|
+
|
|
33
|
+
def read_table(self, table_name):
|
|
34
|
+
with self._connect() as conn:
|
|
35
|
+
df = pd.read_sql(f'SELECT * FROM "{table_name}"', conn)
|
|
36
|
+
return df.fillna(0)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import psycopg2
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BasePostgresSQL(BaseModel):
|
|
7
|
+
def __init__(self, pg_uri):
|
|
8
|
+
super().__init__(pg_uri)
|
|
9
|
+
|
|
10
|
+
def _connect(self):
|
|
11
|
+
user_pass, host_db = self.uri.replace(
|
|
12
|
+
"postgresql://", "").split("@")
|
|
13
|
+
user, password = user_pass.split(":")
|
|
14
|
+
host_port, db_name = host_db.split("/")
|
|
15
|
+
if ":" in host_port:
|
|
16
|
+
host, port = host_port.split(":")
|
|
17
|
+
port = int(port)
|
|
18
|
+
else:
|
|
19
|
+
host, port = host_port, 5432
|
|
20
|
+
try:
|
|
21
|
+
return psycopg2.connect(host=host, port=port, user=user, password=password, dbname=db_name)
|
|
22
|
+
except Exception as e:
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
def get_tables(self):
|
|
26
|
+
conn = self._connect()
|
|
27
|
+
if conn is None:
|
|
28
|
+
return []
|
|
29
|
+
cursor = conn.cursor()
|
|
30
|
+
cursor.execute(
|
|
31
|
+
"SELECT table_name FROM information_schema.tables WHERE table_schema='public'")
|
|
32
|
+
tables = [row[0] for row in cursor.fetchall()]
|
|
33
|
+
cursor.close()
|
|
34
|
+
conn.close()
|
|
35
|
+
return tables
|
|
36
|
+
|
|
37
|
+
def read_table(self, table_name):
|
|
38
|
+
conn = self._connect()
|
|
39
|
+
if conn is None:
|
|
40
|
+
return pd.DataFrame()
|
|
41
|
+
df = pd.read_sql(f'SELECT * FROM "{table_name}"', conn)
|
|
42
|
+
conn.close()
|
|
43
|
+
return df.fillna(0)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import redis
|
|
2
|
+
import pandas as pd
|
|
3
|
+
import json
|
|
4
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class BaseRedis(BaseModel):
|
|
8
|
+
def __init__(self, redis_uri):
|
|
9
|
+
super().__init__(redis_uri)
|
|
10
|
+
|
|
11
|
+
def _connect(self):
|
|
12
|
+
try:
|
|
13
|
+
conn = redis.from_url(self.uri)
|
|
14
|
+
conn.ping()
|
|
15
|
+
return conn
|
|
16
|
+
except Exception as e:
|
|
17
|
+
return None
|
|
18
|
+
|
|
19
|
+
def get_tables(self):
|
|
20
|
+
conn = self._connect()
|
|
21
|
+
if conn is None:
|
|
22
|
+
return []
|
|
23
|
+
try:
|
|
24
|
+
keys = conn.keys('*')
|
|
25
|
+
return [key.decode('utf-8') if isinstance(key, bytes) else key for key in keys]
|
|
26
|
+
except Exception as e:
|
|
27
|
+
return []
|
|
28
|
+
|
|
29
|
+
def read_table(self, table_name):
|
|
30
|
+
conn = self._connect()
|
|
31
|
+
if conn is None:
|
|
32
|
+
return pd.DataFrame()
|
|
33
|
+
try:
|
|
34
|
+
value = conn.get(table_name)
|
|
35
|
+
if value is None:
|
|
36
|
+
return pd.DataFrame()
|
|
37
|
+
|
|
38
|
+
if isinstance(value, bytes):
|
|
39
|
+
value = value.decode('utf-8')
|
|
40
|
+
|
|
41
|
+
data = json.loads(value)
|
|
42
|
+
|
|
43
|
+
if isinstance(data, dict) and all(str(k).isdigit() for k in data.keys()):
|
|
44
|
+
data = list(data.values())
|
|
45
|
+
|
|
46
|
+
if isinstance(data, list):
|
|
47
|
+
df = pd.DataFrame(data)
|
|
48
|
+
elif isinstance(data, dict):
|
|
49
|
+
df = pd.DataFrame([data])
|
|
50
|
+
else:
|
|
51
|
+
return pd.DataFrame()
|
|
52
|
+
|
|
53
|
+
return df.fillna(0)
|
|
54
|
+
except Exception as e:
|
|
55
|
+
return pd.DataFrame()
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import sqlite3
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from py_auto_migrate.base_models.base import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class BaseSQLite(BaseModel):
|
|
7
|
+
def __init__(self, sqlite_path):
|
|
8
|
+
super().__init__(sqlite_path)
|
|
9
|
+
|
|
10
|
+
def _connect(self):
|
|
11
|
+
return sqlite3.connect(self.uri)
|
|
12
|
+
|
|
13
|
+
def get_tables(self):
|
|
14
|
+
conn = self._connect()
|
|
15
|
+
cursor = conn.cursor()
|
|
16
|
+
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
|
|
17
|
+
tables = [row[0] for row in cursor.fetchall()]
|
|
18
|
+
cursor.close()
|
|
19
|
+
conn.close()
|
|
20
|
+
return tables
|
|
21
|
+
|
|
22
|
+
def read_table(self, table_name):
|
|
23
|
+
conn = self._connect()
|
|
24
|
+
df = pd.read_sql(f'SELECT * FROM "{table_name}"', conn)
|
|
25
|
+
conn.close()
|
|
26
|
+
return df.fillna(0)
|