Skip to content

Commit

Permalink
Update dbt-core to 1.5 and implement support for model contracts (#163)
Browse files Browse the repository at this point in the history
Update dbt-core to 1.5.9 and implement support for constraints
* Update changelog
* Fix unit test error
     - The error was: `AttributeError: 'Namespace' object has no attribute 'MACRO_DEBUGGING'`
* Allow Unix socket connection rather than just TCP (#165)
  • Loading branch information
mwallace582 authored Jan 11, 2024
1 parent 732f201 commit 49c9e85
Show file tree
Hide file tree
Showing 17 changed files with 963 additions and 21 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
### Features
- Migrate CircleCI to GitHub Actions ([#120](https://github.com/dbeatty10/dbt-mysql/issues/120))
- Support dbt v1.4 ([#146](https://github.com/dbeatty10/dbt-mysql/pull/146))
- Support dbt v1.5 ([#145](https://github.com/dbeatty10/dbt-mysql/issues/145))
- Support connecting via UNIX sockets ([#164](https://github.com/dbeatty10/dbt-mysql/issues/164))

### Fixes
- Fix incremental composite keys ([#144](https://github.com/dbeatty10/dbt-mysql/issues/144))
Expand All @@ -11,7 +13,7 @@
- [@lpezet](https://github.com/lpezet) ([#146](https://github.com/dbeatty10/dbt-mysql/pull/146))
- [@moszutij](https://github.com/moszutij) ([#146](https://github.com/dbeatty10/dbt-mysql/pull/146), [#144](https://github.com/dbeatty10/dbt-mysql/issues/144))
- [@wesen](https://github.com/wesen) ([#146](https://github.com/dbeatty10/dbt-mysql/pull/146))
- [@mwallace582](https://github.com/mwallace582) ([#162](https://github.com/dbeatty10/dbt-mysql/pull/162))
- [@mwallace582](https://github.com/mwallace582) ([#162](https://github.com/dbeatty10/dbt-mysql/pull/162), [#163](https://github.com/dbeatty10/dbt-mysql/pull/163), [#164](https://github.com/dbeatty10/dbt-mysql/issues/164))


## dbt-mysql 1.1.0 (Feb 5, 2023)
Expand Down
8 changes: 8 additions & 0 deletions dbt/adapters/mariadb/column.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@

@dataclass
class MariaDBColumn(Column):
TYPE_LABELS = {
"STRING": "TEXT",
"VAR_STRING": "TEXT",
"LONG": "INTEGER",
"LONGLONG": "INTEGER",
"INT": "INTEGER",
"TIMESTAMP": "DATETIME",
}
table_database: Optional[str] = None
table_schema: Optional[str] = None
table_name: Optional[str] = None
Expand Down
17 changes: 15 additions & 2 deletions dbt/adapters/mariadb/connections.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from contextlib import contextmanager

import mysql.connector
import mysql.connector.constants

import dbt.exceptions
from dbt.adapters.sql import SQLConnectionManager
Expand All @@ -16,7 +17,8 @@

@dataclass(init=False)
class MariaDBCredentials(Credentials):
server: str
server: Optional[str] = None
unix_socket: Optional[str] = None
port: Optional[int] = None
database: Optional[str] = None
schema: str
Expand Down Expand Up @@ -61,6 +63,7 @@ def _connection_keys(self):
"""
return (
"server",
"unix_socket",
"port",
"database",
"schema",
Expand All @@ -80,14 +83,18 @@ def open(cls, connection):
credentials = cls.get_credentials(connection.credentials)
kwargs = {}

kwargs["host"] = credentials.server
kwargs["user"] = credentials.username
kwargs["passwd"] = credentials.password
kwargs["buffered"] = True

if credentials.ssl_disabled:
kwargs["ssl_disabled"] = credentials.ssl_disabled

if credentials.server:
kwargs["host"] = credentials.server
elif credentials.unix_socket:
kwargs["unix_socket"] = credentials.unix_socket

if credentials.port:
kwargs["port"] = credentials.port

Expand Down Expand Up @@ -172,3 +179,9 @@ def get_response(cls, cursor) -> AdapterResponse:
rows_affected=num_rows,
code=code
)

@classmethod
def data_type_code_to_name(cls, type_code: int) -> str:
field_type_values = mysql.connector.constants.FieldType.desc.values()
mapping = {code: name for (code, name) in field_type_values}
return mapping[type_code]
20 changes: 18 additions & 2 deletions dbt/adapters/mariadb/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from dbt.adapters.mariadb import MariaDBRelation
from dbt.adapters.mariadb import MariaDBColumn
from dbt.adapters.base import BaseRelation
from dbt.contracts.graph.nodes import ConstraintType
from dbt.adapters.base.impl import ConstraintSupport
from dbt.clients.agate_helper import DEFAULT_TYPE_TESTER
from dbt.events import AdapterLogger
from dbt.utils import executor
Expand All @@ -27,6 +29,19 @@ class MariaDBAdapter(SQLAdapter):
Column = MariaDBColumn
ConnectionManager = MariaDBConnectionManager

CONSTRAINT_SUPPORT = {
ConstraintType.check: ConstraintSupport.ENFORCED,
ConstraintType.not_null: ConstraintSupport.ENFORCED,
ConstraintType.unique: ConstraintSupport.ENFORCED,
ConstraintType.primary_key: ConstraintSupport.ENFORCED,
# While Foreign Keys are indeed supported, they're not supported in
# CREATE TABLE AS SELECT statements, which is what DBT uses.
#
# It is possible to use a `post-hook` to add a foreign key after the
# table is created.
ConstraintType.foreign_key: ConstraintSupport.NOT_SUPPORTED,
}

@classmethod
def date_function(cls):
return "current_date()"
Expand All @@ -36,7 +51,8 @@ def convert_datetime_type(cls, agate_table: agate.Table,
col_idx: int) -> str:
return "timestamp"

def quote(self, identifier):
@classmethod
def quote(cls, identifier: str) -> str:
return "`{}`".format(identifier)

def list_relations_without_caching(
Expand Down Expand Up @@ -157,7 +173,7 @@ def _get_one_catalog(

columns: List[Dict[str, Any]] = []
for relation in self.list_relations(database, schema):
logger.debug("Getting table schema for relation {}", relation)
logger.debug("Getting table schema for relation {}", str(relation))
columns.extend(self._get_columns_for_catalog(relation))
return agate.Table.from_object(columns,
column_types=DEFAULT_TYPE_TESTER)
Expand Down
8 changes: 8 additions & 0 deletions dbt/adapters/mysql/column.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@

@dataclass
class MySQLColumn(Column):
TYPE_LABELS = {
"STRING": "TEXT",
"VAR_STRING": "TEXT",
"LONG": "INTEGER",
"LONGLONG": "INTEGER",
"INT": "INTEGER",
"TIMESTAMP": "DATETIME",
}
table_database: Optional[str] = None
table_schema: Optional[str] = None
table_name: Optional[str] = None
Expand Down
17 changes: 15 additions & 2 deletions dbt/adapters/mysql/connections.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from contextlib import contextmanager

import mysql.connector
import mysql.connector.constants

import dbt.exceptions
from dbt.adapters.sql import SQLConnectionManager
Expand All @@ -16,7 +17,8 @@

@dataclass(init=False)
class MySQLCredentials(Credentials):
server: str
server: Optional[str] = None
unix_socket: Optional[str] = None
port: Optional[int] = None
database: Optional[str] = None
schema: str
Expand Down Expand Up @@ -60,6 +62,7 @@ def _connection_keys(self):
"""
return (
"server",
"unix_socket",
"port",
"database",
"schema",
Expand All @@ -79,11 +82,15 @@ def open(cls, connection):
credentials = cls.get_credentials(connection.credentials)
kwargs = {}

kwargs["host"] = credentials.server
kwargs["user"] = credentials.username
kwargs["passwd"] = credentials.password
kwargs["buffered"] = True

if credentials.server:
kwargs["host"] = credentials.server
elif credentials.unix_socket:
kwargs["unix_socket"] = credentials.unix_socket

if credentials.port:
kwargs["port"] = credentials.port

Expand Down Expand Up @@ -168,3 +175,9 @@ def get_response(cls, cursor) -> AdapterResponse:
rows_affected=num_rows,
code=code
)

@classmethod
def data_type_code_to_name(cls, type_code: int) -> str:
field_type_values = mysql.connector.constants.FieldType.desc.values()
mapping = {code: name for (code, name) in field_type_values}
return mapping[type_code]
20 changes: 18 additions & 2 deletions dbt/adapters/mysql/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from dbt.adapters.mysql import MySQLRelation
from dbt.adapters.mysql import MySQLColumn
from dbt.adapters.base import BaseRelation
from dbt.contracts.graph.nodes import ConstraintType
from dbt.adapters.base.impl import ConstraintSupport
from dbt.clients.agate_helper import DEFAULT_TYPE_TESTER
from dbt.events import AdapterLogger
from dbt.utils import executor
Expand All @@ -27,6 +29,19 @@ class MySQLAdapter(SQLAdapter):
Column = MySQLColumn
ConnectionManager = MySQLConnectionManager

CONSTRAINT_SUPPORT = {
ConstraintType.check: ConstraintSupport.ENFORCED,
ConstraintType.not_null: ConstraintSupport.ENFORCED,
ConstraintType.unique: ConstraintSupport.ENFORCED,
ConstraintType.primary_key: ConstraintSupport.ENFORCED,
# While Foreign Keys are indeed supported, they're not supported in
# CREATE TABLE AS SELECT statements, which is what DBT uses.
#
# It is possible to use a `post-hook` to add a foreign key after the
# table is created.
ConstraintType.foreign_key: ConstraintSupport.NOT_SUPPORTED,
}

@classmethod
def date_function(cls):
return "current_date()"
Expand All @@ -36,7 +51,8 @@ def convert_datetime_type(cls, agate_table: agate.Table,
col_idx: int) -> str:
return "timestamp"

def quote(self, identifier):
@classmethod
def quote(cls, identifier: str) -> str:
return "`{}`".format(identifier)

def list_relations_without_caching(
Expand Down Expand Up @@ -157,7 +173,7 @@ def _get_one_catalog(

columns: List[Dict[str, Any]] = []
for relation in self.list_relations(database, schema):
logger.debug("Getting table schema for relation {}", relation)
logger.debug("Getting table schema for relation {}", str(relation))
columns.extend(self._get_columns_for_catalog(relation))
return agate.Table.from_object(columns,
column_types=DEFAULT_TYPE_TESTER)
Expand Down
8 changes: 8 additions & 0 deletions dbt/adapters/mysql5/column.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@

@dataclass
class MySQLColumn(Column):
TYPE_LABELS = {
"STRING": "TEXT",
"VAR_STRING": "TEXT",
"LONG": "INTEGER",
"LONGLONG": "INTEGER",
"INT": "INTEGER",
"TIMESTAMP": "DATETIME",
}
table_database: Optional[str] = None
table_schema: Optional[str] = None
table_name: Optional[str] = None
Expand Down
17 changes: 15 additions & 2 deletions dbt/adapters/mysql5/connections.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from contextlib import contextmanager

import mysql.connector
import mysql.connector.constants

import dbt.exceptions
from dbt.adapters.sql import SQLConnectionManager
Expand All @@ -16,7 +17,8 @@

@dataclass(init=False)
class MySQLCredentials(Credentials):
server: str
server: Optional[str] = None
unix_socket: Optional[str] = None
port: Optional[int] = None
database: Optional[str] = None
schema: str
Expand Down Expand Up @@ -61,6 +63,7 @@ def _connection_keys(self):
"""
return (
"server",
"unix_socket",
"port",
"database",
"schema",
Expand All @@ -80,14 +83,18 @@ def open(cls, connection):
credentials = cls.get_credentials(connection.credentials)
kwargs = {}

kwargs["host"] = credentials.server
kwargs["user"] = credentials.username
kwargs["passwd"] = credentials.password
kwargs["buffered"] = True

if credentials.ssl_disabled:
kwargs["ssl_disabled"] = credentials.ssl_disabled

if credentials.server:
kwargs["host"] = credentials.server
elif credentials.unix_socket:
kwargs["unix_socket"] = credentials.unix_socket

if credentials.port:
kwargs["port"] = credentials.port

Expand Down Expand Up @@ -172,3 +179,9 @@ def get_response(cls, cursor) -> AdapterResponse:
rows_affected=num_rows,
code=code
)

@classmethod
def data_type_code_to_name(cls, type_code: int) -> str:
field_type_values = mysql.connector.constants.FieldType.desc.values()
mapping = {code: name for (code, name) in field_type_values}
return mapping[type_code]
20 changes: 18 additions & 2 deletions dbt/adapters/mysql5/impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
from dbt.adapters.mysql5 import MySQLRelation
from dbt.adapters.mysql5 import MySQLColumn
from dbt.adapters.base import BaseRelation
from dbt.contracts.graph.nodes import ConstraintType
from dbt.adapters.base.impl import ConstraintSupport
from dbt.clients.agate_helper import DEFAULT_TYPE_TESTER
from dbt.events import AdapterLogger
from dbt.utils import executor
Expand All @@ -27,6 +29,19 @@ class MySQLAdapter(SQLAdapter):
Column = MySQLColumn
ConnectionManager = MySQLConnectionManager

CONSTRAINT_SUPPORT = {
ConstraintType.check: ConstraintSupport.NOT_SUPPORTED,
ConstraintType.not_null: ConstraintSupport.ENFORCED,
ConstraintType.unique: ConstraintSupport.ENFORCED,
ConstraintType.primary_key: ConstraintSupport.ENFORCED,
# While Foreign Keys are indeed supported, they're not supported in
# CREATE TABLE AS SELECT statements, which is what DBT uses.
#
# It is possible to use a `post-hook` to add a foreign key after the
# table is created.
ConstraintType.foreign_key: ConstraintSupport.NOT_SUPPORTED,
}

@classmethod
def date_function(cls):
return "current_date()"
Expand All @@ -36,7 +51,8 @@ def convert_datetime_type(cls, agate_table: agate.Table,
col_idx: int) -> str:
return "timestamp"

def quote(self, identifier):
@classmethod
def quote(cls, identifier: str) -> str:
return "`{}`".format(identifier)

def list_relations_without_caching(
Expand Down Expand Up @@ -156,7 +172,7 @@ def _get_one_catalog(

columns: List[Dict[str, Any]] = []
for relation in self.list_relations(database, schema):
logger.debug("Getting table schema for relation {}", relation)
logger.debug("Getting table schema for relation {}", str(relation))
columns.extend(self._get_columns_for_catalog(relation))
return agate.Table.from_object(columns,
column_types=DEFAULT_TYPE_TESTER)
Expand Down
Loading

0 comments on commit 49c9e85

Please sign in to comment.