Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions mindsdb/api/executor/planner/plan_join.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,14 @@ def resolve_table(self, table):
# try to use default namespace
integration = self.planner.default_namespace
if len(table.parts) > 0:
if table.parts[0] in self.planner.databases:
integration = table.parts.pop(0)
# if not quoted check in lower case
part = table.parts[0]
if part not in self.planner.databases and not table.is_quoted[0]:
part = part.lower()

if part in self.planner.databases:
integration = part
table.parts.pop(0)
table.is_quoted.pop(0)
else:
integration = self.planner.default_namespace
Expand Down
23 changes: 16 additions & 7 deletions mindsdb/api/executor/planner/query_planner.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,13 +78,13 @@ def __init__(
if integrations is not None:
for integration in integrations:
if isinstance(integration, dict):
integration_name = integration["name"].lower()
integration_name = integration["name"]
# it is project of system database
if integration["type"] != "data":
_projects.add(integration_name)
continue
else:
integration_name = integration.lower()
integration_name = integration
integration = {"name": integration}
self.integrations[integration_name] = integration

Expand Down Expand Up @@ -175,9 +175,12 @@ def _prepare_integration_select(node, is_table, is_target, parent_query, **kwarg
return

# cut integration part
if len(node.parts) > 1 and node.parts[0].lower() == database:
node.parts.pop(0)
node.is_quoted.pop(0)
if len(node.parts) > 1:
if (node.is_quoted[0] and node.parts[0] == database) or (
not node.is_quoted[0] and node.parts[0].lower() == database.lower()
):
node.parts.pop(0)
node.is_quoted.pop(0)

if not hasattr(parent_query, "from_table"):
return
Expand Down Expand Up @@ -258,8 +261,14 @@ def resolve_database_table(self, node: Identifier):

err_msg_suffix = ""
if len(parts) > 1:
if parts[0].lower() in self.databases:
database = parts.pop(0).lower()
# if not quoted check in lower case
part = parts[0]
if part not in self.databases and not node.is_quoted[0]:
part = part.lower()

if part in self.databases:
database = part
parts.pop(0)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be good also pop node.is_quoted, to keep node consistent

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, added

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, parts is copy of node.parts, we can't change node.is_quoted
rolled it back

else:
err_msg_suffix = f"'{parts[0].lower()}' is not valid database name."

Expand Down
69 changes: 69 additions & 0 deletions tests/unit/executor/test_base_queires.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,75 @@ def test_joins_different_db(self, data_handler):
assert ret["c"][0] == 1 # alias is the same as column
assert ret["col1"][0] == 7

@patch("mindsdb.integrations.handlers.postgres_handler.Handler")
def test_db_mixed_case(self, data_handler):
df = pd.DataFrame(
[
{"a": 6, "c": 1},
{"a": 4, "c": 2},
{"a": 2, "c": 3},
]
)
# mixed case
self.set_handler(data_handler, name="mixDb", tables={"tbl": df, "mixTbl": df})
self.set_handler(data_handler, name="mixDb2", tables={"tbl": df, "mixTbl": df})

# --- works with right case (with quotes and without)
self.run_sql("""
SELECT * FROM `mixDb`.tbl as t1
JOIN `mixDb2`.tbl as t2 on t1.c=t2.c
""")

self.run_sql("""
SELECT * FROM mixDb.tbl as t1
JOIN mixDb2.tbl as t2 on t1.c=t2.c
""")

self.run_sql("SELECT * FROM mixDb.tbl")

self.run_sql("SELECT * FROM `mixDb`.tbl")

# --- doesn't work with wrong case
with pytest.raises(Exception):
self.run_sql("""
SELECT * FROM mixdb.tbl as t1
JOIN mixDb2.tbl as t2 on t1.c=t2.c
""")

with pytest.raises(Exception):
self.run_sql("""
SELECT * FROM `mixdb`.tbl as t1
JOIN `mixDb2`.tbl as t2 on t1.c=t2.c
""")

with pytest.raises(Exception):
self.run_sql("SELECT * FROM mixdb.tbl")

with pytest.raises(Exception):
self.run_sql("SELECT * FROM `mixdb`.tbl")

# lower case
self.set_handler(data_handler, name="low_db", tables={"tbl": df, "mixTbl": df})
self.set_handler(data_handler, name="low_db2", tables={"tbl": df, "mixTbl": df})

# --- works with any case if not quoted
self.run_sql("""
SELECT * FROM low_DB.tbl as t1
JOIN low_DB2.tbl as t2 on t1.c=t2.c
""")

self.run_sql("SELECT * FROM low_DB.tbl")

# -- doesn't work quoted
with pytest.raises(Exception):
self.run_sql("""
SELECT * FROM `low_DB`.tbl as t1
JOIN `low_DB2`.tbl as t2 on t1.c=t2.c
""")

with pytest.raises(Exception):
self.run_sql("SELECT * FROM `low_DB`.tbl")

@patch("mindsdb.integrations.handlers.postgres_handler.Handler")
def test_implicit_join(self, data_handler):
df1 = pd.DataFrame(
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/planner/test_insert_from_select.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_insert_from_select_with_table_plan(self):
plan = plan_query(query, integrations=["INT_1", "INT_2"])

step_1 = FetchDataframeStep(
integration="int_2",
integration="INT_2",
query=Select(
targets=[Star()],
from_table=Identifier("table_2"),
Expand All @@ -65,7 +65,7 @@ def test_insert_from_select_with_table_and_columns_plan(self):
plan = plan_query(query, integrations=["INT_1", "INT_2"])

step_1 = FetchDataframeStep(
integration="int_2",
integration="INT_2",
query=Select(
targets=[
Identifier("column_1", alias=Identifier("column_1")),
Expand Down Expand Up @@ -105,7 +105,7 @@ def test_insert_from_select_with_table_and_columns_and_where_plan(self):
),
),
)
plan = plan_query(query, integrations=["INT_1", "INT_2"])
plan = plan_query(query, integrations=["int_1", "int_2"])

step_1 = FetchDataframeStep(
integration="int_2",
Expand Down
Loading