class_docstr: A connection to a SQL database using a SQLAlchemy Engine. Initialize using ``st.connection("<name>", type="sql")``.
  
  SQLConnection provides the ``query()`` convenience method, which can be used to
  run simple read-only queries with both caching and simple error handling/retries.
  More complex DB interactions can be performed by using the ``.session`` property
  to receive a regular SQLAlchemy Session.
  
  SQLConnections should always be created using ``st.connection()``, **not**
  initialized directly. Connection parameters for a SQLConnection can be specified
  using either ``st.secrets`` or ``**kwargs``. Some frequently used parameters include:
  
  - **url** or arguments for `sqlalchemy.engine.URL.create()
    <https://docs.sqlalchemy.org/en/20/core/engines.html#sqlalchemy.engine.URL.create>`_.
    Most commonly it includes a dialect, host, database, username and password.
  
  - **create_engine_kwargs** can be passed via ``st.secrets``, such as for
    `snowflake-sqlalchemy <https://github.com/snowflakedb/snowflake-sqlalchemy#key-pair-authentication-support>`_
    or `Google BigQuery <https://github.com/googleapis/python-bigquery-sqlalchemy#authentication>`_.
    These can also be passed directly as ``**kwargs`` to connection().
  
  - **autocommit=True** to run with isolation level ``AUTOCOMMIT``. Default is False.
  
  Example
  -------
  >>> import streamlit as st
  >>>
  >>> conn = st.connection("sql")
  >>> df = conn.query("select * from pet_owners")
  >>> st.dataframe(df)
class_docstr_tok: ["A","connection","to","a","SQL","database","using","a","SQLAlchemy","Engine",".","Initialize","using","``","st.connection","(","``","<","name",">","''",",","type=","''","sql","''",")","``",".","SQLConnection","provides","the","``","query","(",")","``","convenience","method",",","which","can","be","used","to","run","simple","read-only","queries","with","both","caching","and","simple","error","handling\/retries",".","More","complex","DB","interactions","can","be","performed","by","using","the","``",".session","``","property","to","receive","a","regular","SQLAlchemy","Session",".","SQLConnections","should","always","be","created","using","``","st.connection","(",")","``",",","*","*","not","*","*","initialized","directly",".","Connection","parameters","for","a","SQLConnection","can","be","specified","using","either","``","st.secrets","``","or","``","*","*","kwargs","``",".","Some","frequently","used","parameters","include",":","-","*","*","url","*","*","or","arguments","for","`","sqlalchemy.engine.URL.create","(",")","<","https",":","\/\/docs.sqlalchemy.org\/en\/20\/core\/engines.html","#","sqlalchemy.engine.URL.create",">","`","_",".","Most","commonly","it","includes","a","dialect",",","host",",","database",",","username","and","password",".","-","*","*","create_engine_kwargs","*","*","can","be","passed","via","``","st.secrets","``",",","such","as","for","`","snowflake-sqlalchemy","<","https",":","\/\/github.com\/snowflakedb\/snowflake-sqlalchemy","#","key-pair-authentication-support",">","`","_","or","`","Google","BigQuery","<","https",":","\/\/github.com\/googleapis\/python-bigquery-sqlalchemy","#","authentication",">","`","_",".","These","can","also","be","passed","directly","as","``","*","*","kwargs","``","to","connection","(",")",".","-","*","*","autocommit=True","*","*","to","run","with","isolation","level","``","AUTOCOMMIT","``",".","Default","is","False",".","Example","--","--","--","-",">",">",">","import","streamlit","as","st",">",">",">",">",">",">","conn","=","st.connection","(","``","sql","''",")",">",">",">","df","=","conn.query","(","``","select","*","from","pet_owners","''",")",">",">",">","st.dataframe","(","df",")"]
docstr: Run a read-only query.
  
  This method implements both query result caching (with caching behavior
  identical to that of using ``@st.cache_data``) as well as simple error handling/retries.
  
  .. note::
      Queries that are run without a specified ttl are cached indefinitely.
  
  Aside from the ``ttl`` kwarg, all kwargs passed to this function are passed down
  to |pandas.read_sql|_
  and have the behavior described in the pandas documentation.
  
  .. |pandas.read_sql| replace:: ``pandas.read_sql``
  .. _pandas.read_sql: https://pandas.pydata.org/docs/reference/api/pandas.read_sql.html
  
  Parameters
  ----------
  sql : str
      The read-only SQL query to execute.
  show_spinner : boolean or string
      Enable the spinner. The default is to show a spinner when there is a
      "cache miss" and the cached resource is being created. If a string, the value
      of the show_spinner param will be used for the spinner text.
  ttl : float, int, timedelta or None
      The maximum number of seconds to keep results in the cache, or
      None if cached results should not expire. The default is None.
  index_col : str, list of str, or None
      Column(s) to set as index(MultiIndex). Default is None.
  chunksize : int or None
      If specified, return an iterator where chunksize is the number of
      rows to include in each chunk. Default is None.
  params : list, tuple, dict or None
      List of parameters to pass to the execute method. The syntax used to pass
      parameters is database driver dependent. Check your database driver
      documentation for which of the five syntax styles, described in `PEP 249
      paramstyle <https://peps.python.org/pep-0249/#paramstyle>`_, is supported.
      Default is None.
  **kwargs: dict
      Additional keyword arguments are passed to |pandas.read_sql|_.
  
      .. |pandas.read_sql| replace:: ``pandas.read_sql``
      .. _pandas.read_sql: https://pandas.pydata.org/docs/reference/api/pandas.read_sql.html
  
  Returns
  -------
  pandas.DataFrame
      The result of running the query, formatted as a pandas DataFrame.
  
  Example
  -------
  >>> import streamlit as st
  >>>
  >>> conn = st.connection("sql")
  >>> df = conn.query("select * from pet_owners where owner = :owner", ttl=3600, params={"owner":"barbara"})
  >>> st.dataframe(df)
docstr_tok: ["Run","a","read-only","query",".","This","method","implements","both","query","result","caching","(","with","caching","behavior","identical","to","that","of","using","``","@","st.cache_data","``",")","as","well","as","simple","error","handling\/retries",".","..","note",":",":","Queries","that","are","run","without","a","specified","ttl","are","cached","indefinitely",".","Aside","from","the","``","ttl","``","kwarg",",","all","kwargs","passed","to","this","function","are","passed","down","to","|pandas.read_sql|_","and","have","the","behavior","described","in","the","pandas","documentation",".","..","|pandas.read_sql|","replace",":",":","``","pandas.read_sql","``","..","_pandas.read_sql",":","https",":","\/\/pandas.pydata.org\/docs\/reference\/api\/pandas.read_sql.html","Parameters","--","--","--","--","--","sql",":","str","The","read-only","SQL","query","to","execute",".","show_spinner",":","boolean","or","string","Enable","the","spinner",".","The","default","is","to","show","a","spinner","when","there","is","a","``","cache","miss","''","and","the","cached","resource","is","being","created",".","If","a","string",",","the","value","of","the","show_spinner","param","will","be","used","for","the","spinner","text",".","ttl",":","float",",","int",",","timedelta","or","None","The","maximum","number","of","seconds","to","keep","results","in","the","cache",",","or","None","if","cached","results","should","not","expire",".","The","default","is","None",".","index_col",":","str",",","list","of","str",",","or","None","Column","(","s",")","to","set","as","index","(","MultiIndex",")",".","Default","is","None",".","chunksize",":","int","or","None","If","specified",",","return","an","iterator","where","chunksize","is","the","number","of","rows","to","include","in","each","chunk",".","Default","is","None",".","params",":","list",",","tuple",",","dict","or","None","List","of","parameters","to","pass","to","the","execute","method",".","The","syntax","used","to","pass","parameters","is","database","driver","dependent",".","Check","your","database","driver","documentation","for","which","of","the","five","syntax","styles",",","described","in","`","PEP","249","paramstyle","<","https",":","\/\/peps.python.org\/pep-0249\/","#","paramstyle",">","`","_",",","is","supported",".","Default","is","None",".","*","*","kwargs",":","dict","Additional","keyword","arguments","are","passed","to","|pandas.read_sql|_",".","..","|pandas.read_sql|","replace",":",":","``","pandas.read_sql","``","..","_pandas.read_sql",":","https",":","\/\/pandas.pydata.org\/docs\/reference\/api\/pandas.read_sql.html","Returns","--","--","--","-","pandas.DataFrame","The","result","of","running","the","query",",","formatted","as","a","pandas","DataFrame",".","Example","--","--","--","-",">",">",">","import","streamlit","as","st",">",">",">",">",">",">","conn","=","st.connection","(","``","sql","''",")",">",">",">","df","=","conn.query","(","``","select","*","from","pet_owners","where","owner","=",":","owner","''",",","ttl=3600",",","params=","{","``","owner","''",":","''","barbara","''","}",")",">",">",">","st.dataframe","(","df",")"]
code: def query(
      self,
      sql: str,
      *,  # keyword-only arguments:
      show_spinner: bool | str = "Running `sql.query(...)`.",
      ttl: Optional[Union[float, int, timedelta]] = None,
      index_col: Optional[Union[str, List[str]]] = None,
      chunksize: Optional[int] = None,
      params=None,
      **kwargs,
  ) -> pd.DataFrame:
      """Run a read-only query.
  
      This method implements both query result caching (with caching behavior
      identical to that of using ``@st.cache_data``) as well as simple error handling/retries.
  
      .. note::
          Queries that are run without a specified ttl are cached indefinitely.
  
      Aside from the ``ttl`` kwarg, all kwargs passed to this function are passed down
      to |pandas.read_sql|_
      and have the behavior described in the pandas documentation.
  
      .. |pandas.read_sql| replace:: ``pandas.read_sql``
      .. _pandas.read_sql: https://pandas.pydata.org/docs/reference/api/pandas.read_sql.html
  
      Parameters
      ----------
      sql : str
          The read-only SQL query to execute.
      show_spinner : boolean or string
          Enable the spinner. The default is to show a spinner when there is a
          "cache miss" and the cached resource is being created. If a string, the value
          of the show_spinner param will be used for the spinner text.
      ttl : float, int, timedelta or None
          The maximum number of seconds to keep results in the cache, or
          None if cached results should not expire. The default is None.
      index_col : str, list of str, or None
          Column(s) to set as index(MultiIndex). Default is None.
      chunksize : int or None
          If specified, return an iterator where chunksize is the number of
          rows to include in each chunk. Default is None.
      params : list, tuple, dict or None
          List of parameters to pass to the execute method. The syntax used to pass
          parameters is database driver dependent. Check your database driver
          documentation for which of the five syntax styles, described in `PEP 249
          paramstyle <https://peps.python.org/pep-0249/#paramstyle>`_, is supported.
          Default is None.
      **kwargs: dict
          Additional keyword arguments are passed to |pandas.read_sql|_.
  
          .. |pandas.read_sql| replace:: ``pandas.read_sql``
          .. _pandas.read_sql: https://pandas.pydata.org/docs/reference/api/pandas.read_sql.html
  
      Returns
      -------
      pandas.DataFrame
          The result of running the query, formatted as a pandas DataFrame.
  
      Example
      -------
      >>> import streamlit as st
      >>>
      >>> conn = st.connection("sql")
      >>> df = conn.query("select * from pet_owners where owner = :owner", ttl=3600, params={"owner":"barbara"})
      >>> st.dataframe(df)
      """
  
      from sqlalchemy import text
      from sqlalchemy.exc import (
          DatabaseError,
          InternalError,
          OperationalError,
      )
      from tenacity import (
          retry,
          retry_if_exception_type,
          stop_after_attempt,
          wait_fixed,
      )
  
      @retry(
          after=lambda _: self.reset(),
          stop=stop_after_attempt(3),
          reraise=True,
          retry=retry_if_exception_type(
              (DatabaseError, InternalError, OperationalError)
          ),
          wait=wait_fixed(1),
      )
      def _query(
          sql: str,
          index_col=None,
          chunksize=None,
          params=None,
          **kwargs,
      ) -> pd.DataFrame:
          instance = self._instance.connect()
          return pd.read_sql(
              text(sql),
              instance,
              index_col=index_col,
              chunksize=chunksize,
              params=params,
              **kwargs,
          )
  
      # We modify our helper function's `__qualname__` here to work around default
      # `@st.cache_data` behavior. Otherwise, `.query()` being called with different
      # `ttl` values will reset the cache with each call, and the query caches won't
      # be scoped by connection.
      ttl_str = (
          str(  # Avoid adding extra `.` characters to `__qualname__`
              ttl
          ).replace(".", "_")
      )
      _query.__qualname__ = (
          f"{_query.__qualname__}_{self._connection_name}_{ttl_str}"
      )
      _query = cache_data(
          show_spinner=show_spinner,
          ttl=ttl,
      )(_query)
  
      return _query(
          sql,
          index_col=index_col,
          chunksize=chunksize,
          params=params,
          **kwargs,
      )
  
file_path: streamlit/lib/streamlit/connections/sql_connection.py
imports: from __future__ import annotations
  from collections import ChainMap
  from copy import deepcopy
  from datetime import timedelta
  from typing import TYPE_CHECKING, List, Optional, Union, cast
  import pandas
  from streamlit.connections import BaseConnection
  from streamlit.connections.util import extract_from_dict
  from streamlit.errors import StreamlitAPIException
  from streamlit.runtime.caching import cache_data
label_desc: Use image node_id 2 for calling the SQLConnection obj's underlying member method code with example usage: obj.query(sql) and returns: _query, pd