Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """The sql component."""
2 
3 from __future__ import annotations
4 
5 import logging
6 
7 import sqlparse
8 import voluptuous as vol
9 
10 from homeassistant.components.recorder import CONF_DB_URL, get_instance
12  CONF_STATE_CLASS,
13  DEVICE_CLASSES_SCHEMA,
14  STATE_CLASSES_SCHEMA,
15 )
16 from homeassistant.config_entries import ConfigEntry
17 from homeassistant.const import (
18  CONF_DEVICE_CLASS,
19  CONF_ICON,
20  CONF_NAME,
21  CONF_UNIQUE_ID,
22  CONF_UNIT_OF_MEASUREMENT,
23  CONF_VALUE_TEMPLATE,
24  Platform,
25 )
26 from homeassistant.core import HomeAssistant
27 from homeassistant.helpers import discovery
30  CONF_AVAILABILITY,
31  CONF_PICTURE,
32 )
33 from homeassistant.helpers.typing import ConfigType
34 
35 from .const import CONF_COLUMN_NAME, CONF_QUERY, DOMAIN, PLATFORMS
36 from .util import redact_credentials
37 
38 _LOGGER = logging.getLogger(__name__)
39 
40 
41 def validate_sql_select(value: str) -> str:
42  """Validate that value is a SQL SELECT query."""
43  if len(query := sqlparse.parse(value.lstrip().lstrip(";"))) > 1:
44  raise vol.Invalid("Multiple SQL queries are not supported")
45  if len(query) == 0 or (query_type := query[0].get_type()) == "UNKNOWN":
46  raise vol.Invalid("Invalid SQL query")
47  if query_type != "SELECT":
48  _LOGGER.debug("The SQL query %s is of type %s", query, query_type)
49  raise vol.Invalid("Only SELECT queries allowed")
50  return str(query[0])
51 
52 
53 QUERY_SCHEMA = vol.Schema(
54  {
55  vol.Required(CONF_COLUMN_NAME): cv.string,
56  vol.Required(CONF_NAME): cv.template,
57  vol.Required(CONF_QUERY): vol.All(cv.string, validate_sql_select),
58  vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
59  vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
60  vol.Optional(CONF_UNIQUE_ID): cv.string,
61  vol.Optional(CONF_DB_URL): cv.string,
62  vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
63  vol.Optional(CONF_STATE_CLASS): STATE_CLASSES_SCHEMA,
64  vol.Optional(CONF_AVAILABILITY): cv.template,
65  vol.Optional(CONF_ICON): cv.template,
66  vol.Optional(CONF_PICTURE): cv.template,
67  }
68 )
69 
70 CONFIG_SCHEMA = vol.Schema(
71  {vol.Optional(DOMAIN): vol.All(cv.ensure_list, [QUERY_SCHEMA])},
72  extra=vol.ALLOW_EXTRA,
73 )
74 
75 
77  hass: HomeAssistant, entry: ConfigEntry
78 ) -> None:
79  """Remove db url from config if it matches recorder database."""
80  hass.config_entries.async_update_entry(
81  entry,
82  options={
83  key: value for key, value in entry.options.items() if key != CONF_DB_URL
84  },
85  )
86 
87 
88 async def async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
89  """Update listener for options."""
90  await hass.config_entries.async_reload(entry.entry_id)
91 
92 
93 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
94  """Set up SQL from yaml config."""
95  if (conf := config.get(DOMAIN)) is None:
96  return True
97 
98  for sensor_conf in conf:
99  await discovery.async_load_platform(
100  hass, Platform.SENSOR, DOMAIN, sensor_conf, config
101  )
102 
103  return True
104 
105 
106 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
107  """Set up SQL from a config entry."""
108  _LOGGER.debug(
109  "Comparing %s and %s",
110  redact_credentials(entry.options.get(CONF_DB_URL)),
111  redact_credentials(get_instance(hass).db_url),
112  )
113  if entry.options.get(CONF_DB_URL) == get_instance(hass).db_url:
115 
116  entry.async_on_unload(entry.add_update_listener(async_update_listener))
117 
118  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
119 
120  return True
121 
122 
123 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
124  """Unload SQL config entry."""
125 
126  return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
None remove_configured_db_url_if_not_needed(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:78
None async_update_listener(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:88
bool async_setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:93
str validate_sql_select(str value)
Definition: __init__.py:41
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:123
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:106
str redact_credentials(str url)
Definition: __init__.py:98
Recorder get_instance(HomeAssistant hass)
Definition: recorder.py:74