> ## Documentation Index
> Fetch the complete documentation index at: https://docs.activeviam.com/llms.txt
> Use this file to discover all available pages before exploring further.

# JdbcLoad

<span id="atoti_jdbc.JdbcLoad" />

> atoti\_jdbc.JdbcLoad(<br />
>     *query*: [str](https://docs.python.org/3/library/stdtypes.html#str),<br />
>     *url*: Annotated\[[str](https://docs.python.org/3/library/stdtypes.html#str), AfterValidator(normalize\_jdbc\_url)],<br />
>     \*,<br />
>     *driver*: Annotated\[[str](https://docs.python.org/3/library/stdtypes.html#str) | [None](https://docs.python.org/3/library/constants.html#None), AfterValidator(\_validate\_driver)] = `None`,<br />
>     *parameters*: FrozenSequence\[Constant] = `()`,<br />
> )

The definition of a JDBC query.

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> from atoti_jdbc import JdbcLoad
>>> url = f"h2:{database_path};USER=root;PASSWORD=pass"
>>> jdbc_load = JdbcLoad("SELECT * FROM MYTABLE", url=url)
```

Inferring data types:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> data_types = session.tables.infer_data_types(jdbc_load)
>>> data_types
{'ID': 'int', 'CITY': 'String', 'MY_VALUE': 'long'}
```

Creating a table from the inferred data types:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> table = session.create_table("Cities", data_types=data_types, keys={"ID"})
```

Loading query results into the table:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> table.load(jdbc_load)
>>> table.head().sort_index()
        CITY  MY_VALUE
ID
1      Paris       100
2     London        80
3   New York        90
4     Berlin        70
5    Jakarta        75
```

Using a parametrized query:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> table.drop()
>>> table.load(
...     JdbcLoad(
...         "SELECT * FROM MYTABLE WHERE City IN (?, ?)",
...         parameters=["Paris", "New York"],
...         url=url,
...     )
... )
>>> table.head().sort_index()
        CITY  MY_VALUE
ID
1      Paris       100
3   New York        90
```

The [`load()`](./atoti.Table.load#atoti.Table.load) outcome depends on the *error\_handling* argument.
For instance, the following SQLite database has a table with a **MY\_VALUE** column typed as integer but with a string on row #3:

```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
>>> import sqlite3
>>> query = "SELECT * FROM MYTABLE"
>>> url = f"sqlite:{database_path}"
>>> with sqlite3.connect(database_path) as connection:
...     pd.read_sql(query, connection).set_index("ID")
        CITY    MY_VALUE
ID
1      Paris         100
2     London          80
3   New York  wrong type
4     Berlin          70
5    Jakarta          75
```

* `"fail"` raises an error on the first invalid row and interrupts the load:
  ```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
  >>> table.drop()
  >>> table += (0, "Rome", 42)
  >>> table.head()
      CITY  MY_VALUE
  ID
  0   Rome        42
  >>> jdbc_load = JdbcLoad(query, url=url)
  >>> with session.tables.data_transaction():  
  ...     table.load(jdbc_load, error_handling="fail")
  Traceback (most recent call last):
      ...
  py4j.protocol.Py4JError: ...Caused by: java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Number...
  >>> table.head()
      CITY  MY_VALUE
  ID
  0   Rome        42
  >>> exception_message = "Caused by: java.lang.ClassCastException: class java.lang.String cannot be cast to class java.lang.Number"
  >>> _count_transaction_exceptions(exception_message) > 0
  True
  ```
* `"warn"` skips the invalid rows and raises a Python warning:
  ```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
  >>> from warnings import catch_warnings, simplefilter
  >>> table.drop()
  >>> with (
  ...     session.tables.data_transaction(),
  ...     catch_warnings(record=True) as warnings,
  ... ):
  ...     simplefilter("always")
  ...     table.load(jdbc_load, error_handling="warn")
  >>> [warning.message for warning in warnings]
  [UserWarning("Some errors occurred while loading data into t['Cities'].")]
  >>> table.head().sort_index()
         CITY  MY_VALUE
  ID
  1     Paris       100
  2    London        80
  4    Berlin        70
  5   Jakarta        75
  >>> _count_transaction_exceptions(exception_message) > 0
  True
  ```
* `"log"` skips the invalid rows and logs the errors:
  ```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
  >>> table.drop()
  >>> with session.tables.data_transaction():
  ...     table.load(jdbc_load, error_handling="log")
  >>> table.head().sort_index()
         CITY  MY_VALUE
  ID
  1     Paris       100
  2    London        80
  4    Berlin        70
  5   Jakarta        75
  >>> _count_transaction_exceptions(exception_message) > 0
  True
  ```
* `"skip"` skips the invalid rows without logging:
  ```pycon theme={"languages":{"custom":["/engine/python-sdk/0.9/languages/pycon.tmLanguage.json"]}}
  >>> table.drop()
  >>> with session.tables.data_transaction():
  ...     table.load(jdbc_load, error_handling="skip")
  >>> table.head().sort_index()
         CITY  MY_VALUE
  ID
  1     Paris       100
  2    London        80
  4    Berlin        70
  5   Jakarta        75
  >>> _count_transaction_exceptions(exception_message)
  0
  ```

<Callout icon="link">
  **See also**:
  The other [`DataLoad`](./atoti.data_load.DataLoad#atoti.data_load.DataLoad) implementations.
</Callout>

### Attributes

<h4 id="atoti_jdbc.JdbcLoad.parameters">
  *parameters*
</h4>

The query parameters, sometimes also called *bind variables*.

<h4 id="atoti_jdbc.JdbcLoad.driver">
  *driver*
</h4>

The Java class name of the [`driver`](./atoti_jdbc.driver#module-atoti_jdbc.driver) to use.

This defines Hibernate’s [DRIVER](https://javadoc.io/static/org.hibernate/hibernate-core/5.6.15.Final/org/hibernate/cfg/AvailableSettings.html#DRIVER) option.

Inferred from [`url`](#atoti_jdbc.JdbcLoad.url) if `None`.

<h4 id="atoti_jdbc.JdbcLoad.url">
  *url*
</h4>

The JDBC connection string of the database.

The `"jdbc"` scheme is optional but the database specific scheme (such as `"h2"`) is mandatory.
For instance:

* `"h2:/home/user/database/file/path;USER=username;PASSWORD=passwd"`
* `"postgresql://postgresql.db.server:5430/example?user=username&password=passwd"`

More examples can be found [here](https://www.baeldung.com/java-jdbc-url-format).

This defines Hibernate’s [URL](https://javadoc.io/static/org.hibernate/hibernate-core/5.6.15.Final/org/hibernate/cfg/AvailableSettings.html#URL) option.

<h4 id="atoti_jdbc.JdbcLoad.query">
  *query*
</h4>

The query (usually SQL) to execute.
