dbt-cube-sync 0.1.0a8__py3-none-any.whl → 0.1.0a10__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.

Potentially problematic release.


This version of dbt-cube-sync might be problematic. Click here for more details.

@@ -60,13 +60,19 @@ class SupersetConnector(BaseConnector):
60
60
  """Authenticate and get JWT token"""
61
61
  login_url = f"{self.base_url}/api/v1/security/login"
62
62
  payload = {
63
- "username": self.config['username'],
64
63
  "password": self.config['password'],
65
64
  "provider": "db",
66
- "refresh": True
65
+ "refresh": "true",
66
+ "username": self.config['username']
67
67
  }
68
-
68
+
69
69
  response = self.session.post(login_url, json=payload)
70
+ if response.status_code == 401:
71
+ raise Exception(
72
+ f"Superset authentication failed (401). "
73
+ f"Check username/password and ensure provider='{payload['provider']}' is correct. "
74
+ f"Response: {response.text}"
75
+ )
70
76
  response.raise_for_status()
71
77
 
72
78
  data = response.json()
@@ -1,17 +1,16 @@
1
1
  """
2
- Database inspector - fetches column types using SQLAlchemy MetaData reflection.
2
+ Database inspector - fetches column types using SQLAlchemy or direct SQL.
3
3
 
4
- Uses SQLAlchemy's Table(..., autoload_with=engine) for portable, database-agnostic
5
- column type extraction. This approach works consistently across PostgreSQL, MySQL,
6
- Snowflake, BigQuery, Redshift, and other databases.
4
+ Uses Redshift-specific queries for Redshift databases (which don't support
5
+ standard PostgreSQL reflection), and SQLAlchemy reflection for other databases.
7
6
  """
8
7
  from typing import Dict, Optional
9
- from sqlalchemy import create_engine, MetaData, Table
8
+ from sqlalchemy import create_engine, MetaData, Table, text
10
9
  from sqlalchemy.engine import Engine
11
10
 
12
11
 
13
12
  class DatabaseInspector:
14
- """Inspects database schema to extract column type information using SQLAlchemy reflection."""
13
+ """Inspects database schema to extract column type information."""
15
14
 
16
15
  def __init__(self, sqlalchemy_uri: str):
17
16
  """
@@ -20,8 +19,9 @@ class DatabaseInspector:
20
19
  Args:
21
20
  sqlalchemy_uri: SQLAlchemy connection URI (e.g., postgresql://user:pass@host:port/db)
22
21
  """
23
- # Add connect_args for Redshift compatibility
24
- if 'redshift' in sqlalchemy_uri.lower():
22
+ self.is_redshift = 'redshift' in sqlalchemy_uri.lower()
23
+
24
+ if self.is_redshift:
25
25
  self.engine: Engine = create_engine(
26
26
  sqlalchemy_uri,
27
27
  connect_args={'sslmode': 'prefer'}
@@ -30,13 +30,62 @@ class DatabaseInspector:
30
30
  self.engine: Engine = create_engine(sqlalchemy_uri)
31
31
 
32
32
  self.metadata = MetaData()
33
- self._table_cache: Dict[str, Table] = {}
33
+ self._table_cache: Dict[str, Dict[str, str]] = {}
34
+
35
+ def _get_redshift_columns(self, schema: str, table_name: str) -> Dict[str, str]:
36
+ """
37
+ Get column types from Redshift using LIMIT 0 query (fastest method).
38
+
39
+ Executes SELECT * FROM table LIMIT 0 and reads column types from cursor description.
40
+ This is very fast because it doesn't scan any data - just returns metadata.
41
+ """
42
+ columns = {}
43
+
44
+ # LIMIT 0 query - returns no rows but gives us column metadata
45
+ query = text(f'SELECT * FROM "{schema}"."{table_name}" LIMIT 0')
46
+
47
+ # Redshift type OID to name mapping (common types)
48
+ redshift_type_map = {
49
+ 16: 'boolean',
50
+ 20: 'bigint',
51
+ 21: 'smallint',
52
+ 23: 'integer',
53
+ 25: 'text',
54
+ 700: 'real',
55
+ 701: 'double precision',
56
+ 1042: 'char',
57
+ 1043: 'varchar',
58
+ 1082: 'date',
59
+ 1083: 'time',
60
+ 1114: 'timestamp',
61
+ 1184: 'timestamptz',
62
+ 1700: 'numeric',
63
+ 2950: 'uuid',
64
+ }
65
+
66
+ try:
67
+ with self.engine.connect() as conn:
68
+ result = conn.execute(query)
69
+ # Get column info from cursor description
70
+ # Format: (name, type_code, display_size, internal_size, precision, scale, null_ok)
71
+ if result.cursor and result.cursor.description:
72
+ for col_desc in result.cursor.description:
73
+ col_name = col_desc[0]
74
+ type_code = col_desc[1]
75
+ # Map type code to type name, fallback to 'varchar' if unknown
76
+ col_type = redshift_type_map.get(type_code, 'varchar')
77
+ columns[col_name] = col_type
78
+
79
+ except Exception as e:
80
+ print(f"Warning: Could not inspect Redshift table {schema}.{table_name}: {e}")
81
+
82
+ return columns
34
83
 
35
84
  def get_table_columns(self, schema: str, table_name: str) -> Dict[str, str]:
36
85
  """
37
86
  Get column names and their data types for a specific table.
38
87
 
39
- Uses SQLAlchemy MetaData reflection for portable column extraction.
88
+ Uses Redshift-specific queries for Redshift, SQLAlchemy reflection for others.
40
89
 
41
90
  Args:
42
91
  schema: Database schema name
@@ -45,30 +94,33 @@ class DatabaseInspector:
45
94
  Returns:
46
95
  Dictionary mapping column names to data types
47
96
  """
48
- columns = {}
49
97
  cache_key = f"{schema}.{table_name}"
50
98
 
51
- try:
52
- # Check cache first
53
- if cache_key in self._table_cache:
54
- table = self._table_cache[cache_key]
55
- else:
56
- # Reflect table using SQLAlchemy MetaData
99
+ # Check cache first
100
+ if cache_key in self._table_cache:
101
+ return self._table_cache[cache_key]
102
+
103
+ columns = {}
104
+
105
+ if self.is_redshift:
106
+ # Use Redshift-specific query
107
+ columns = self._get_redshift_columns(schema, table_name)
108
+ else:
109
+ # Use standard SQLAlchemy reflection
110
+ try:
57
111
  table = Table(
58
112
  table_name,
59
113
  self.metadata,
60
114
  autoload_with=self.engine,
61
115
  schema=schema
62
116
  )
63
- self._table_cache[cache_key] = table
117
+ for column in table.columns:
118
+ columns[column.name] = str(column.type)
64
119
 
65
- # Extract column types
66
- for column in table.columns:
67
- columns[column.name] = str(column.type)
68
-
69
- except Exception as e:
70
- print(f"Warning: Could not inspect table {schema}.{table_name}: {e}")
120
+ except Exception as e:
121
+ print(f"Warning: Could not inspect table {schema}.{table_name}: {e}")
71
122
 
123
+ self._table_cache[cache_key] = columns
72
124
  return columns
73
125
 
74
126
  def reflect_multiple_tables(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dbt-cube-sync
3
- Version: 0.1.0a8
3
+ Version: 0.1.0a10
4
4
  Summary: Synchronization tool for dbt models to Cube.js schemas and BI tools
5
5
  Author: Ponder
6
6
  Requires-Python: >=3.9,<4.0
@@ -4,15 +4,15 @@ dbt_cube_sync/config.py,sha256=qhGE7CxTmh0RhPizgd3x3Yj-3L2LoC00UQIDT0q9FlQ,3858
4
4
  dbt_cube_sync/connectors/__init__.py,sha256=NG6tYZ3CYD5bG_MfNLZrUM8YoBEKArG8-AOmJ8pwvQI,52
5
5
  dbt_cube_sync/connectors/base.py,sha256=JLzerxJdt34z0kWuyieL6UQhf5_dUYPGmwkiRWBuSPY,2802
6
6
  dbt_cube_sync/connectors/powerbi.py,sha256=2Y8fTfh_6Q_Myma1ymipPh1U3HsfQKcktVequXXnIXI,1275
7
- dbt_cube_sync/connectors/superset.py,sha256=5YEqadVZRPFAJkgvhqkse3JuGJkQHfyvT88jy52ow_0,21429
7
+ dbt_cube_sync/connectors/superset.py,sha256=D_pWTN0F84mUosnsm-NG_v9IlVE2dviIDh08WxHEOIA,21709
8
8
  dbt_cube_sync/connectors/tableau.py,sha256=jKve1zErzTbgPOtmPB92ZwZl4I6uEySedM51JiwlGrE,1261
9
9
  dbt_cube_sync/core/__init__.py,sha256=kgsawtU5dqEvnHz6dU8qwJbH3rtIV7QlK2MhtYVDCaY,46
10
10
  dbt_cube_sync/core/cube_generator.py,sha256=DtmaA_dtWmBVJnSWHVoQi-3KEsRc0axHZpCUEcKeYAk,11061
11
- dbt_cube_sync/core/db_inspector.py,sha256=Ccd9ieGNlwHDHdgMVDEOfjs7R9Mjj904OW1P-mDSsyo,3155
11
+ dbt_cube_sync/core/db_inspector.py,sha256=V_cd12FBXj-1gB2JZeYmkQluUO-UYufy_tvfYoJXCGI,5073
12
12
  dbt_cube_sync/core/dbt_parser.py,sha256=KbhDoB0ULP6JDUPZPDVbm9yCtRKrW17ptGoJvVLtueY,12763
13
13
  dbt_cube_sync/core/models.py,sha256=2s5iZ9MEBGfSzkB4HJB5vG0mZqNXNJSfAD3Byw1IVe4,3203
14
14
  dbt_cube_sync/core/state_manager.py,sha256=7uXJtlZBIWj6s6XgAhNlP6UHdfhH0y461iyQlfidqGI,7233
15
- dbt_cube_sync-0.1.0a8.dist-info/METADATA,sha256=fsb721DeeHXUeeeLIihijjIiM6x7Wl8fUTeBMzlyoZo,10680
16
- dbt_cube_sync-0.1.0a8.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
17
- dbt_cube_sync-0.1.0a8.dist-info/entry_points.txt,sha256=iEAB_nZ1AoSeFwSHPY2tr02xmTHLVFKp5CJeFh0AfCw,56
18
- dbt_cube_sync-0.1.0a8.dist-info/RECORD,,
15
+ dbt_cube_sync-0.1.0a10.dist-info/METADATA,sha256=Foy8KI7-ILdZwTvejfjukArtnGNJJg85vwIlQoMS31w,10681
16
+ dbt_cube_sync-0.1.0a10.dist-info/WHEEL,sha256=3ny-bZhpXrU6vSQ1UPG34FoxZBp3lVcvK0LkgUz6VLk,88
17
+ dbt_cube_sync-0.1.0a10.dist-info/entry_points.txt,sha256=iEAB_nZ1AoSeFwSHPY2tr02xmTHLVFKp5CJeFh0AfCw,56
18
+ dbt_cube_sync-0.1.0a10.dist-info/RECORD,,