Fix sql integration issues 5.0 beta (#71063)
Co-authored-by: Paulus Schoutsen <balloob@gmail.com>
This commit is contained in:
parent
755020ff63
commit
c90eb4d6b4
6 changed files with 48 additions and 31 deletions
|
@ -23,17 +23,12 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DATA_SCHEMA = vol.Schema(
|
DATA_SCHEMA = vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_DB_URL): selector.TextSelector(selector.TextSelectorConfig()),
|
vol.Required(CONF_NAME, default="Select SQL Query"): selector.TextSelector(),
|
||||||
vol.Required(CONF_COLUMN_NAME): selector.TextSelector(
|
vol.Optional(CONF_DB_URL): selector.TextSelector(),
|
||||||
selector.TextSelectorConfig()
|
vol.Required(CONF_COLUMN_NAME): selector.TextSelector(),
|
||||||
),
|
vol.Required(CONF_QUERY): selector.TextSelector(),
|
||||||
vol.Required(CONF_QUERY): selector.TextSelector(selector.TextSelectorConfig()),
|
vol.Optional(CONF_UNIT_OF_MEASUREMENT): selector.TextSelector(),
|
||||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): selector.TextSelector(
|
vol.Optional(CONF_VALUE_TEMPLATE): selector.TemplateSelector(),
|
||||||
selector.TextSelectorConfig()
|
|
||||||
),
|
|
||||||
vol.Optional(CONF_VALUE_TEMPLATE): selector.TemplateSelector(
|
|
||||||
selector.TemplateSelectorConfig()
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -109,8 +104,7 @@ class SQLConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
column = user_input[CONF_COLUMN_NAME]
|
column = user_input[CONF_COLUMN_NAME]
|
||||||
uom = user_input.get(CONF_UNIT_OF_MEASUREMENT)
|
uom = user_input.get(CONF_UNIT_OF_MEASUREMENT)
|
||||||
value_template = user_input.get(CONF_VALUE_TEMPLATE)
|
value_template = user_input.get(CONF_VALUE_TEMPLATE)
|
||||||
|
name = user_input[CONF_NAME]
|
||||||
name = f"Select {column} SQL query"
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
validate_sql_select(query)
|
validate_sql_select(query)
|
||||||
|
@ -182,17 +176,17 @@ class SQLOptionsFlowHandler(config_entries.OptionsFlow):
|
||||||
description={
|
description={
|
||||||
"suggested_value": self.entry.options[CONF_DB_URL]
|
"suggested_value": self.entry.options[CONF_DB_URL]
|
||||||
},
|
},
|
||||||
): selector.selector({"text": {}}),
|
): selector.TextSelector(),
|
||||||
vol.Required(
|
vol.Required(
|
||||||
CONF_QUERY,
|
CONF_QUERY,
|
||||||
description={"suggested_value": self.entry.options[CONF_QUERY]},
|
description={"suggested_value": self.entry.options[CONF_QUERY]},
|
||||||
): selector.selector({"text": {}}),
|
): selector.TextSelector(),
|
||||||
vol.Required(
|
vol.Required(
|
||||||
CONF_COLUMN_NAME,
|
CONF_COLUMN_NAME,
|
||||||
description={
|
description={
|
||||||
"suggested_value": self.entry.options[CONF_COLUMN_NAME]
|
"suggested_value": self.entry.options[CONF_COLUMN_NAME]
|
||||||
},
|
},
|
||||||
): selector.selector({"text": {}}),
|
): selector.TextSelector(),
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_UNIT_OF_MEASUREMENT,
|
CONF_UNIT_OF_MEASUREMENT,
|
||||||
description={
|
description={
|
||||||
|
@ -200,7 +194,7 @@ class SQLOptionsFlowHandler(config_entries.OptionsFlow):
|
||||||
CONF_UNIT_OF_MEASUREMENT
|
CONF_UNIT_OF_MEASUREMENT
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
): selector.selector({"text": {}}),
|
): selector.TextSelector(),
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_VALUE_TEMPLATE,
|
CONF_VALUE_TEMPLATE,
|
||||||
description={
|
description={
|
||||||
|
@ -208,7 +202,7 @@ class SQLOptionsFlowHandler(config_entries.OptionsFlow):
|
||||||
CONF_VALUE_TEMPLATE
|
CONF_VALUE_TEMPLATE
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
): selector.selector({"text": {}}),
|
): selector.TemplateSelector(),
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
errors=errors,
|
errors=errors,
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"db_url": "Database URL",
|
"db_url": "Database URL",
|
||||||
|
"name": "[%key:common::config_flow::data::name%]",
|
||||||
"query": "Select Query",
|
"query": "Select Query",
|
||||||
"column": "Column",
|
"column": "Column",
|
||||||
"unit_of_measurement": "Unit of Measure",
|
"unit_of_measurement": "Unit of Measure",
|
||||||
|
@ -19,6 +20,7 @@
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"db_url": "Database URL, leave empty to use default HA database",
|
"db_url": "Database URL, leave empty to use default HA database",
|
||||||
|
"name": "Name that will be used for Config Entry and also the Sensor",
|
||||||
"query": "Query to run, needs to start with 'SELECT'",
|
"query": "Query to run, needs to start with 'SELECT'",
|
||||||
"column": "Column for returned query to present as state",
|
"column": "Column for returned query to present as state",
|
||||||
"unit_of_measurement": "Unit of Measure (optional)",
|
"unit_of_measurement": "Unit of Measure (optional)",
|
||||||
|
@ -32,6 +34,7 @@
|
||||||
"init": {
|
"init": {
|
||||||
"data": {
|
"data": {
|
||||||
"db_url": "[%key:component::sql::config::step::user::data::db_url%]",
|
"db_url": "[%key:component::sql::config::step::user::data::db_url%]",
|
||||||
|
"name": "[%key:component::sql::config::step::user::data::name%]",
|
||||||
"query": "[%key:component::sql::config::step::user::data::query%]",
|
"query": "[%key:component::sql::config::step::user::data::query%]",
|
||||||
"column": "[%key:component::sql::config::step::user::data::column%]",
|
"column": "[%key:component::sql::config::step::user::data::column%]",
|
||||||
"unit_of_measurement": "[%key:component::sql::config::step::user::data::unit_of_measurement%]",
|
"unit_of_measurement": "[%key:component::sql::config::step::user::data::unit_of_measurement%]",
|
||||||
|
@ -39,6 +42,7 @@
|
||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"db_url": "[%key:component::sql::config::step::user::data_description::db_url%]",
|
"db_url": "[%key:component::sql::config::step::user::data_description::db_url%]",
|
||||||
|
"name": "[%key:component::sql::config::step::user::data_description::name%]",
|
||||||
"query": "[%key:component::sql::config::step::user::data_description::query%]",
|
"query": "[%key:component::sql::config::step::user::data_description::query%]",
|
||||||
"column": "[%key:component::sql::config::step::user::data_description::column%]",
|
"column": "[%key:component::sql::config::step::user::data_description::column%]",
|
||||||
"unit_of_measurement": "[%key:component::sql::config::step::user::data_description::unit_of_measurement%]",
|
"unit_of_measurement": "[%key:component::sql::config::step::user::data_description::unit_of_measurement%]",
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
"data": {
|
"data": {
|
||||||
"column": "Column",
|
"column": "Column",
|
||||||
"db_url": "Database URL",
|
"db_url": "Database URL",
|
||||||
|
"name": "Name",
|
||||||
"query": "Select Query",
|
"query": "Select Query",
|
||||||
"unit_of_measurement": "Unit of Measure",
|
"unit_of_measurement": "Unit of Measure",
|
||||||
"value_template": "Value Template"
|
"value_template": "Value Template"
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"column": "Column for returned query to present as state",
|
"column": "Column for returned query to present as state",
|
||||||
"db_url": "Database URL, leave empty to use default HA database",
|
"db_url": "Database URL, leave empty to use default HA database",
|
||||||
|
"name": "Name that will be used for Config Entry and also the Sensor",
|
||||||
"query": "Query to run, needs to start with 'SELECT'",
|
"query": "Query to run, needs to start with 'SELECT'",
|
||||||
"unit_of_measurement": "Unit of Measure (optional)",
|
"unit_of_measurement": "Unit of Measure (optional)",
|
||||||
"value_template": "Value Template (optional)"
|
"value_template": "Value Template (optional)"
|
||||||
|
@ -38,6 +40,7 @@
|
||||||
"data": {
|
"data": {
|
||||||
"column": "Column",
|
"column": "Column",
|
||||||
"db_url": "Database URL",
|
"db_url": "Database URL",
|
||||||
|
"name": "Name",
|
||||||
"query": "Select Query",
|
"query": "Select Query",
|
||||||
"unit_of_measurement": "Unit of Measure",
|
"unit_of_measurement": "Unit of Measure",
|
||||||
"value_template": "Value Template"
|
"value_template": "Value Template"
|
||||||
|
@ -45,6 +48,7 @@
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"column": "Column for returned query to present as state",
|
"column": "Column for returned query to present as state",
|
||||||
"db_url": "Database URL, leave empty to use default HA database",
|
"db_url": "Database URL, leave empty to use default HA database",
|
||||||
|
"name": "Name that will be used for Config Entry and also the Sensor",
|
||||||
"query": "Query to run, needs to start with 'SELECT'",
|
"query": "Query to run, needs to start with 'SELECT'",
|
||||||
"unit_of_measurement": "Unit of Measure (optional)",
|
"unit_of_measurement": "Unit of Measure (optional)",
|
||||||
"value_template": "Value Template (optional)"
|
"value_template": "Value Template (optional)"
|
||||||
|
|
|
@ -6,19 +6,28 @@ from typing import Any
|
||||||
from homeassistant.components.recorder import CONF_DB_URL
|
from homeassistant.components.recorder import CONF_DB_URL
|
||||||
from homeassistant.components.sql.const import CONF_COLUMN_NAME, CONF_QUERY, DOMAIN
|
from homeassistant.components.sql.const import CONF_COLUMN_NAME, CONF_QUERY, DOMAIN
|
||||||
from homeassistant.config_entries import SOURCE_USER
|
from homeassistant.config_entries import SOURCE_USER
|
||||||
from homeassistant.const import CONF_UNIT_OF_MEASUREMENT
|
from homeassistant.const import CONF_NAME, CONF_UNIT_OF_MEASUREMENT
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
ENTRY_CONFIG = {
|
ENTRY_CONFIG = {
|
||||||
CONF_DB_URL: "sqlite://",
|
CONF_DB_URL: "sqlite://",
|
||||||
|
CONF_NAME: "Get Value",
|
||||||
CONF_QUERY: "SELECT 5 as value",
|
CONF_QUERY: "SELECT 5 as value",
|
||||||
CONF_COLUMN_NAME: "value",
|
CONF_COLUMN_NAME: "value",
|
||||||
CONF_UNIT_OF_MEASUREMENT: "MiB",
|
CONF_UNIT_OF_MEASUREMENT: "MiB",
|
||||||
}
|
}
|
||||||
|
|
||||||
ENTRY_CONFIG_INVALID_QUERY = {
|
ENTRY_CONFIG_INVALID_QUERY = {
|
||||||
|
CONF_DB_URL: "sqlite://",
|
||||||
|
CONF_NAME: "Get Value",
|
||||||
|
CONF_QUERY: "UPDATE 5 as value",
|
||||||
|
CONF_COLUMN_NAME: "size",
|
||||||
|
CONF_UNIT_OF_MEASUREMENT: "MiB",
|
||||||
|
}
|
||||||
|
|
||||||
|
ENTRY_CONFIG_INVALID_QUERY_OPT = {
|
||||||
CONF_DB_URL: "sqlite://",
|
CONF_DB_URL: "sqlite://",
|
||||||
CONF_QUERY: "UPDATE 5 as value",
|
CONF_QUERY: "UPDATE 5 as value",
|
||||||
CONF_COLUMN_NAME: "size",
|
CONF_COLUMN_NAME: "size",
|
||||||
|
@ -27,6 +36,7 @@ ENTRY_CONFIG_INVALID_QUERY = {
|
||||||
|
|
||||||
ENTRY_CONFIG_NO_RESULTS = {
|
ENTRY_CONFIG_NO_RESULTS = {
|
||||||
CONF_DB_URL: "sqlite://",
|
CONF_DB_URL: "sqlite://",
|
||||||
|
CONF_NAME: "Get Value",
|
||||||
CONF_QUERY: "SELECT kalle as value from no_table;",
|
CONF_QUERY: "SELECT kalle as value from no_table;",
|
||||||
CONF_COLUMN_NAME: "value",
|
CONF_COLUMN_NAME: "value",
|
||||||
CONF_UNIT_OF_MEASUREMENT: "MiB",
|
CONF_UNIT_OF_MEASUREMENT: "MiB",
|
||||||
|
|
|
@ -14,7 +14,12 @@ from homeassistant.data_entry_flow import (
|
||||||
RESULT_TYPE_FORM,
|
RESULT_TYPE_FORM,
|
||||||
)
|
)
|
||||||
|
|
||||||
from . import ENTRY_CONFIG, ENTRY_CONFIG_INVALID_QUERY, ENTRY_CONFIG_NO_RESULTS
|
from . import (
|
||||||
|
ENTRY_CONFIG,
|
||||||
|
ENTRY_CONFIG_INVALID_QUERY,
|
||||||
|
ENTRY_CONFIG_INVALID_QUERY_OPT,
|
||||||
|
ENTRY_CONFIG_NO_RESULTS,
|
||||||
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
|
|
||||||
|
@ -40,14 +45,14 @@ async def test_form(hass: HomeAssistant) -> None:
|
||||||
print(ENTRY_CONFIG)
|
print(ENTRY_CONFIG)
|
||||||
|
|
||||||
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
assert result2["title"] == "Select value SQL query"
|
assert result2["title"] == "Get Value"
|
||||||
assert result2["options"] == {
|
assert result2["options"] == {
|
||||||
"db_url": "sqlite://",
|
"db_url": "sqlite://",
|
||||||
|
"name": "Get Value",
|
||||||
"query": "SELECT 5 as value",
|
"query": "SELECT 5 as value",
|
||||||
"column": "value",
|
"column": "value",
|
||||||
"unit_of_measurement": "MiB",
|
"unit_of_measurement": "MiB",
|
||||||
"value_template": None,
|
"value_template": None,
|
||||||
"name": "Select value SQL query",
|
|
||||||
}
|
}
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
@ -67,14 +72,14 @@ async def test_import_flow_success(hass: HomeAssistant) -> None:
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
assert result2["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
assert result2["title"] == "Select value SQL query"
|
assert result2["title"] == "Get Value"
|
||||||
assert result2["options"] == {
|
assert result2["options"] == {
|
||||||
"db_url": "sqlite://",
|
"db_url": "sqlite://",
|
||||||
|
"name": "Get Value",
|
||||||
"query": "SELECT 5 as value",
|
"query": "SELECT 5 as value",
|
||||||
"column": "value",
|
"column": "value",
|
||||||
"unit_of_measurement": "MiB",
|
"unit_of_measurement": "MiB",
|
||||||
"value_template": None,
|
"value_template": None,
|
||||||
"name": "Select value SQL query",
|
|
||||||
}
|
}
|
||||||
assert len(mock_setup_entry.mock_calls) == 1
|
assert len(mock_setup_entry.mock_calls) == 1
|
||||||
|
|
||||||
|
@ -158,14 +163,14 @@ async def test_flow_fails_invalid_query(hass: HomeAssistant) -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result5["type"] == RESULT_TYPE_CREATE_ENTRY
|
assert result5["type"] == RESULT_TYPE_CREATE_ENTRY
|
||||||
assert result5["title"] == "Select value SQL query"
|
assert result5["title"] == "Get Value"
|
||||||
assert result5["options"] == {
|
assert result5["options"] == {
|
||||||
"db_url": "sqlite://",
|
"db_url": "sqlite://",
|
||||||
|
"name": "Get Value",
|
||||||
"query": "SELECT 5 as value",
|
"query": "SELECT 5 as value",
|
||||||
"column": "value",
|
"column": "value",
|
||||||
"unit_of_measurement": "MiB",
|
"unit_of_measurement": "MiB",
|
||||||
"value_template": None,
|
"value_template": None,
|
||||||
"name": "Select value SQL query",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -176,11 +181,11 @@ async def test_options_flow(hass: HomeAssistant) -> None:
|
||||||
data={},
|
data={},
|
||||||
options={
|
options={
|
||||||
"db_url": "sqlite://",
|
"db_url": "sqlite://",
|
||||||
|
"name": "Get Value",
|
||||||
"query": "SELECT 5 as value",
|
"query": "SELECT 5 as value",
|
||||||
"column": "value",
|
"column": "value",
|
||||||
"unit_of_measurement": "MiB",
|
"unit_of_measurement": "MiB",
|
||||||
"value_template": None,
|
"value_template": None,
|
||||||
"name": "Select value SQL query",
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
@ -223,11 +228,11 @@ async def test_options_flow_fails_db_url(hass: HomeAssistant) -> None:
|
||||||
data={},
|
data={},
|
||||||
options={
|
options={
|
||||||
"db_url": "sqlite://",
|
"db_url": "sqlite://",
|
||||||
|
"name": "Get Value",
|
||||||
"query": "SELECT 5 as value",
|
"query": "SELECT 5 as value",
|
||||||
"column": "value",
|
"column": "value",
|
||||||
"unit_of_measurement": "MiB",
|
"unit_of_measurement": "MiB",
|
||||||
"value_template": None,
|
"value_template": None,
|
||||||
"name": "Select value SQL query",
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
@ -267,11 +272,11 @@ async def test_options_flow_fails_invalid_query(
|
||||||
data={},
|
data={},
|
||||||
options={
|
options={
|
||||||
"db_url": "sqlite://",
|
"db_url": "sqlite://",
|
||||||
|
"name": "Get Value",
|
||||||
"query": "SELECT 5 as value",
|
"query": "SELECT 5 as value",
|
||||||
"column": "value",
|
"column": "value",
|
||||||
"unit_of_measurement": "MiB",
|
"unit_of_measurement": "MiB",
|
||||||
"value_template": None,
|
"value_template": None,
|
||||||
"name": "Select size SQL query",
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
entry.add_to_hass(hass)
|
entry.add_to_hass(hass)
|
||||||
|
@ -287,7 +292,7 @@ async def test_options_flow_fails_invalid_query(
|
||||||
|
|
||||||
result2 = await hass.config_entries.options.async_configure(
|
result2 = await hass.config_entries.options.async_configure(
|
||||||
result["flow_id"],
|
result["flow_id"],
|
||||||
user_input=ENTRY_CONFIG_INVALID_QUERY,
|
user_input=ENTRY_CONFIG_INVALID_QUERY_OPT,
|
||||||
)
|
)
|
||||||
|
|
||||||
assert result2["type"] == RESULT_TYPE_FORM
|
assert result2["type"] == RESULT_TYPE_FORM
|
||||||
|
|
|
@ -52,7 +52,7 @@ async def test_import_query(hass: HomeAssistant) -> None:
|
||||||
|
|
||||||
assert hass.config_entries.async_entries(DOMAIN)
|
assert hass.config_entries.async_entries(DOMAIN)
|
||||||
options = hass.config_entries.async_entries(DOMAIN)[0].options
|
options = hass.config_entries.async_entries(DOMAIN)[0].options
|
||||||
assert options[CONF_NAME] == "Select value SQL query"
|
assert options[CONF_NAME] == "count_tables"
|
||||||
|
|
||||||
|
|
||||||
async def test_query_value_template(hass: HomeAssistant) -> None:
|
async def test_query_value_template(hass: HomeAssistant) -> None:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue