Skip to content

Commit 74379a8

Browse files
committed
docs(sql): emphasize the need to close a raw_sql cursor only when using SELECT statements
1 parent 4aac015 commit 74379a8

File tree

2 files changed

+62
-6
lines changed

2 files changed

+62
-6
lines changed

ibis/backends/base/sql/__init__.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,16 @@ def raw_sql(self, query: str):
136136
::: {.callout-tip}
137137
## Consider using [`.sql`](#ibis.backends.base.sql.BaseSQLBackend.sql) instead
138138
139-
If your query is a SELECT statement, you should use the
139+
If your query is a `SELECT` statement you can use the
140140
[backend `.sql`](#ibis.backends.base.sql.BaseSQLBackend.sql) method to avoid
141-
having to release the cursor returned from this method manually.
141+
having to manually release the cursor returned from this method.
142142
143-
::: {.callout-warning collapse="true"}
144-
## The returned cursor object must be **manually released** if you use `raw_sql`.
143+
::: {.callout-warning}
144+
## The cursor returned from this method must be **manually released**
145+
146+
You **do not** need to call `.close()` on the cursor when running DDL
147+
or DML statements like `CREATE`, `INSERT` or `DROP`, only when using
148+
`SELECT` statements.
145149
146150
To release a cursor, call the `close` method on the returned cursor
147151
object.
@@ -166,7 +170,7 @@ def raw_sql(self, query: str):
166170
Parameters
167171
----------
168172
query
169-
DDL or DML statement
173+
SQL query string
170174
171175
Examples
172176
--------

ibis/backends/base/sql/alchemy/__init__.py

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,59 @@ def _handle_failed_column_type_inference(
589589
)
590590
return table
591591

592-
def raw_sql(self, query):
592+
def raw_sql(self, query: str | sa.sql.ClauseElement):
593+
"""Execute a query and return the cursor used for execution.
594+
595+
::: {.callout-tip}
596+
## Consider using [`.sql`](#ibis.backends.base.sql.BaseSQLBackend.sql) instead
597+
598+
If your query is a `SELECT` statement you can use the
599+
[backend `.sql`](#ibis.backends.base.sql.BaseSQLBackend.sql) method to avoid
600+
having to manually release the cursor returned from this method.
601+
602+
::: {.callout-warning}
603+
## The cursor returned from this method must be **manually released**
604+
605+
You **do not** need to call `.close()` on the cursor when running DDL
606+
or DML statements like `CREATE`, `INSERT` or `DROP`, only when using
607+
`SELECT` statements.
608+
609+
To release a cursor, call the `close` method on the returned cursor
610+
object.
611+
612+
You can close the cursor by explicitly calling its `close` method:
613+
614+
```python
615+
cursor = con.raw_sql("SELECT ...")
616+
cursor.close()
617+
```
618+
619+
Or you can use a context manager:
620+
621+
```python
622+
with con.raw_sql("SELECT ...") as cursor:
623+
...
624+
```
625+
:::
626+
627+
:::
628+
629+
Parameters
630+
----------
631+
query
632+
SQL query or SQLAlchemy expression to execute
633+
634+
Examples
635+
--------
636+
>>> con = ibis.connect("duckdb://")
637+
>>> with con.raw_sql("SELECT 1") as cursor:
638+
... result = cursor.fetchall()
639+
...
640+
>>> result
641+
[(1,)]
642+
>>> cursor.closed
643+
True
644+
"""
593645
return self.con.connect().execute(
594646
sa.text(query) if isinstance(query, str) else query
595647
)

0 commit comments

Comments
 (0)