@@ -589,7 +589,59 @@ def _handle_failed_column_type_inference(
589
589
)
590
590
return table
591
591
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
+ """
593
645
return self .con .connect ().execute (
594
646
sa .text (query ) if isinstance (query , str ) else query
595
647
)
0 commit comments