6161/// ### Batch Delete
6262///
6363/// - ``deleteAll(_:)``
64+ /// - ``deleteAndFetchIds(_:)``
6465/// - ``deleteAndFetchCursor(_:)``
6566/// - ``deleteAndFetchAll(_:)``
6667/// - ``deleteAndFetchSet(_:)``
@@ -528,7 +529,7 @@ extension QueryInterfaceRequest {
528529 ///
529530 /// - important: Make sure you check the documentation of the `RETURNING`
530531 /// clause, which describes important limitations and caveats:
531- /// <https://www.sqlite.org/lang_returning.html>.
532+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
532533 ///
533534 /// - parameter db: A database connection.
534535 /// - parameter selection: The returned columns (must not be empty).
@@ -561,7 +562,7 @@ extension QueryInterfaceRequest {
561562 ///
562563 /// - important: Make sure you check the documentation of the `RETURNING`
563564 /// clause, which describes important limitations and caveats:
564- /// <https://www.sqlite.org/lang_returning.html>.
565+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
565566 ///
566567 /// - parameter db: A database connection.
567568 /// - returns: A ``RecordCursor`` over the deleted records.
@@ -588,7 +589,7 @@ extension QueryInterfaceRequest {
588589 ///
589590 /// - important: Make sure you check the documentation of the `RETURNING`
590591 /// clause, which describes important limitations and caveats:
591- /// <https://www.sqlite.org/lang_returning.html>.
592+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
592593 ///
593594 /// - parameter db: A database connection.
594595 /// - returns: An array of deleted records.
@@ -614,7 +615,7 @@ extension QueryInterfaceRequest {
614615 ///
615616 /// - important: Make sure you check the documentation of the `RETURNING`
616617 /// clause, which describes important limitations and caveats:
617- /// <https://www.sqlite.org/lang_returning.html>.
618+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
618619 ///
619620 /// - parameter db: A database connection.
620621 /// - returns: A set of deleted records.
@@ -625,6 +626,41 @@ extension QueryInterfaceRequest {
625626 {
626627 try Set ( deleteAndFetchCursor ( db) )
627628 }
629+
630+ /// Executes a `DELETE RETURNING` statement and returns the set of
631+ /// deleted ids.
632+ ///
633+ /// For example:
634+ ///
635+ /// ```swift
636+ /// // Fetch the ids of deleted players
637+ /// // DELETE FROM player RETURNING id
638+ /// let request = Player.all()
639+ /// let deletedPlayerIds = try request.deleteAndFetchIds(db)
640+ /// ```
641+ ///
642+ /// - important: Make sure you check the documentation of the `RETURNING`
643+ /// clause, which describes important limitations and caveats:
644+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats>.
645+ ///
646+ /// - parameter db: A database connection.
647+ /// - returns: A set of deleted ids.
648+ /// - throws: A ``DatabaseError`` whenever an SQLite error occurs.
649+ @available ( iOS 13 , macOS 10 . 15 , tvOS 13 , watchOS 6 , * ) // Identifiable
650+ public func deleteAndFetchIds( _ db: Database )
651+ throws -> Set < RowDecoder . ID >
652+ where RowDecoder: TableRecord & Identifiable ,
653+ RowDecoder. ID: Hashable & DatabaseValueConvertible & StatementColumnConvertible
654+ {
655+ let primaryKey = try db. primaryKey ( RowDecoder . databaseTableName)
656+ GRDBPrecondition (
657+ primaryKey. columns. count == 1 ,
658+ " Fetching id requires a single-column primary key in the table \( databaseTableName) " )
659+
660+ let statement = try deleteAndFetchStatement ( db, selection: [ Column ( primaryKey. columns [ 0 ] ) ] )
661+
662+ return try RowDecoder . ID. fetchSet ( statement)
663+ }
628664#else
629665 /// Returns a `DELETE RETURNING` prepared statement.
630666 ///
@@ -640,7 +676,7 @@ extension QueryInterfaceRequest {
640676 ///
641677 /// - important: Make sure you check the documentation of the `RETURNING`
642678 /// clause, which describes important limitations and caveats:
643- /// <https://www.sqlite.org/lang_returning.html>.
679+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
644680 ///
645681 /// - parameter db: A database connection.
646682 /// - parameter selection: The returned columns (must not be empty).
@@ -674,7 +710,7 @@ extension QueryInterfaceRequest {
674710 ///
675711 /// - important: Make sure you check the documentation of the `RETURNING`
676712 /// clause, which describes important limitations and caveats:
677- /// <https://www.sqlite.org/lang_returning.html>.
713+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
678714 ///
679715 /// - parameter db: A database connection.
680716 /// - returns: A ``RecordCursor`` over the deleted records.
@@ -702,7 +738,7 @@ extension QueryInterfaceRequest {
702738 ///
703739 /// - important: Make sure you check the documentation of the `RETURNING`
704740 /// clause, which describes important limitations and caveats:
705- /// <https://www.sqlite.org/lang_returning.html>.
741+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
706742 ///
707743 /// - parameter db: A database connection.
708744 /// - returns: An array of deleted records.
@@ -729,7 +765,7 @@ extension QueryInterfaceRequest {
729765 ///
730766 /// - important: Make sure you check the documentation of the `RETURNING`
731767 /// clause, which describes important limitations and caveats:
732- /// <https://www.sqlite.org/lang_returning.html>.
768+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
733769 ///
734770 /// - parameter db: A database connection.
735771 /// - returns: A set of deleted records.
@@ -741,6 +777,41 @@ extension QueryInterfaceRequest {
741777 {
742778 try Set ( deleteAndFetchCursor ( db) )
743779 }
780+
781+ /// Executes a `DELETE RETURNING` statement and returns the set of
782+ /// deleted ids.
783+ ///
784+ /// For example:
785+ ///
786+ /// ```swift
787+ /// // Fetch the ids of deleted players
788+ /// // DELETE FROM player RETURNING id
789+ /// let request = Player.all()
790+ /// let deletedPlayerIds = try request.deleteAndFetchIds(db)
791+ /// ```
792+ ///
793+ /// - important: Make sure you check the documentation of the `RETURNING`
794+ /// clause, which describes important limitations and caveats:
795+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats>.
796+ ///
797+ /// - parameter db: A database connection.
798+ /// - returns: A set of deleted ids.
799+ /// - throws: A ``DatabaseError`` whenever an SQLite error occurs.
800+ @available ( iOS 15 , macOS 12 , tvOS 15 , watchOS 8 , * ) // SQLite 3.35.0+
801+ public func deleteAndFetchIds( _ db: Database )
802+ throws -> Set < RowDecoder . ID >
803+ where RowDecoder: TableRecord & Identifiable ,
804+ RowDecoder. ID: Hashable & DatabaseValueConvertible & StatementColumnConvertible
805+ {
806+ let primaryKey = try db. primaryKey ( RowDecoder . databaseTableName)
807+ GRDBPrecondition (
808+ primaryKey. columns. count == 1 ,
809+ " Fetching id requires a single-column primary key in the table \( databaseTableName) " )
810+
811+ let statement = try deleteAndFetchStatement ( db, selection: [ Column ( primaryKey. columns [ 0 ] ) ] )
812+
813+ return try RowDecoder . ID. fetchSet ( statement)
814+ }
744815#endif
745816}
746817
@@ -844,7 +915,7 @@ extension QueryInterfaceRequest {
844915 ///
845916 /// - important: Make sure you check the documentation of the `RETURNING`
846917 /// clause, which describes important limitations and caveats:
847- /// <https://www.sqlite.org/lang_returning.html>.
918+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
848919 ///
849920 /// - parameter db: A database connection.
850921 /// - parameter conflictResolution: A policy for conflict resolution.
@@ -893,7 +964,7 @@ extension QueryInterfaceRequest {
893964 ///
894965 /// - important: Make sure you check the documentation of the `RETURNING`
895966 /// clause, which describes important limitations and caveats:
896- /// <https://www.sqlite.org/lang_returning.html>.
967+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
897968 ///
898969 /// - parameter db: A database connection.
899970 /// - parameter conflictResolution: A policy for conflict resolution.
@@ -930,7 +1001,7 @@ extension QueryInterfaceRequest {
9301001 ///
9311002 /// - important: Make sure you check the documentation of the `RETURNING`
9321003 /// clause, which describes important limitations and caveats:
933- /// <https://www.sqlite.org/lang_returning.html>.
1004+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
9341005 ///
9351006 /// - parameter db: A database connection.
9361007 /// - parameter conflictResolution: A policy for conflict resolution.
@@ -962,7 +1033,7 @@ extension QueryInterfaceRequest {
9621033 ///
9631034 /// - important: Make sure you check the documentation of the `RETURNING`
9641035 /// clause, which describes important limitations and caveats:
965- /// <https://www.sqlite.org/lang_returning.html>.
1036+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
9661037 ///
9671038 /// - parameter db: A database connection.
9681039 /// - parameter conflictResolution: A policy for conflict resolution.
@@ -996,7 +1067,7 @@ extension QueryInterfaceRequest {
9961067 ///
9971068 /// - important: Make sure you check the documentation of the `RETURNING`
9981069 /// clause, which describes important limitations and caveats:
999- /// <https://www.sqlite.org/lang_returning.html>.
1070+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
10001071 ///
10011072 /// - parameter db: A database connection.
10021073 /// - parameter conflictResolution: A policy for conflict resolution.
@@ -1046,7 +1117,7 @@ extension QueryInterfaceRequest {
10461117 ///
10471118 /// - important: Make sure you check the documentation of the `RETURNING`
10481119 /// clause, which describes important limitations and caveats:
1049- /// <https://www.sqlite.org/lang_returning.html>.
1120+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
10501121 ///
10511122 /// - parameter db: A database connection.
10521123 /// - parameter conflictResolution: A policy for conflict resolution.
@@ -1084,7 +1155,7 @@ extension QueryInterfaceRequest {
10841155 ///
10851156 /// - important: Make sure you check the documentation of the `RETURNING`
10861157 /// clause, which describes important limitations and caveats:
1087- /// <https://www.sqlite.org/lang_returning.html>.
1158+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
10881159 ///
10891160 /// - parameter db: A database connection.
10901161 /// - parameter conflictResolution: A policy for conflict resolution.
@@ -1117,7 +1188,7 @@ extension QueryInterfaceRequest {
11171188 ///
11181189 /// - important: Make sure you check the documentation of the `RETURNING`
11191190 /// clause, which describes important limitations and caveats:
1120- /// <https://www.sqlite.org/lang_returning.html>.
1191+ /// <https://www.sqlite.org/lang_returning.html#limitations_and_caveats >.
11211192 ///
11221193 /// - parameter db: A database connection.
11231194 /// - parameter conflictResolution: A policy for conflict resolution.
0 commit comments