Skip to content

Commit

Permalink
Make dumpTables able to print views
Browse files Browse the repository at this point in the history
  • Loading branch information
groue committed Oct 28, 2023
1 parent 42fd327 commit ba320a0
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 10 deletions.
2 changes: 1 addition & 1 deletion GRDB/Core/Database.swift
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ let SQLITE_TRANSIENT = unsafeBitCast(OpaquePointer(bitPattern: -1), to: sqlite3_
/// - ``dumpContent(format:to:)``
/// - ``dumpRequest(_:format:to:)``
/// - ``dumpSQL(_:format:to:)``
/// - ``dumpTables(_:format:tableHeader:to:)``
/// - ``dumpTables(_:format:tableHeader:stableOrder:to:)``
/// - ``DumpFormat``
/// - ``DumpTableHeaderOptions``
///
Expand Down
2 changes: 1 addition & 1 deletion GRDB/Core/DatabaseReader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import Dispatch
/// - ``dumpContent(format:to:)``
/// - ``dumpRequest(_:format:to:)``
/// - ``dumpSQL(_:format:to:)``
/// - ``dumpTables(_:format:tableHeader:to:)``
/// - ``dumpTables(_:format:tableHeader:stableOrder:to:)``
/// - ``DumpFormat``
/// - ``DumpTableHeaderOptions``
///
Expand Down
34 changes: 29 additions & 5 deletions GRDB/Dump/Database+Dump.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ extension Database {
try _dumpRequest(request, format: format, to: &dumpStream)
}

/// Prints the contents of the provided tables.
/// Prints the contents of the provided tables and views.
///
/// For example:
///
Expand All @@ -80,17 +80,29 @@ extension Database {
/// - tables: The table names.
/// - format: The output format.
/// - tableHeader: Options for printing table names.
/// - stableOrder: A boolean value that controls the ordering of
/// rows fetched from views. If false (the default), rows are
/// printed in the order specified by the view (which may be
/// undefined). It true, outputted rows are always printed in the
/// same stable order. The purpose of this stable order is to make
/// the output suitable for testing.
/// - stream: A stream for text output, which directs output to the
/// console by default.
public func dumpTables(
_ tables: [String],
format: some DumpFormat = .debug(),
tableHeader: DumpTableHeaderOptions = .automatic,
stableOrder: Bool = false,
to stream: (any TextOutputStream)? = nil)
throws
{
var dumpStream = DumpStream(stream)
try _dumpTables(tables, format: format, tableHeader: tableHeader, to: &dumpStream)
try _dumpTables(
tables,
format: format,
tableHeader: tableHeader,
stableOrder: stableOrder,
to: &dumpStream)
}

/// Prints the contents of the database.
Expand Down Expand Up @@ -186,7 +198,8 @@ extension Database {
func _dumpTables(
_ tables: [String],
format: some DumpFormat,
tableHeader: DumpTableHeaderOptions = .automatic,
tableHeader: DumpTableHeaderOptions,
stableOrder: Bool,
to stream: inout DumpStream)
throws
{
Expand All @@ -203,10 +216,21 @@ extension Database {
} else {
stream.write("\n")
}

if header {
stream.writeln(table)
}
try _dumpRequest(Table(table).orderByPrimaryKey(), format: format, to: &stream)

if try tableExists(table) {
// Always sort tables by primary key
try _dumpRequest(Table(table).orderByPrimaryKey(), format: format, to: &stream)
} else if stableOrder {
// View with stable order
try _dumpRequest(Table(table).all().withStableOrder(), format: format, to: &stream)
} else {
// Use view ordering, if any (no guarantee of stable order).
try _dumpRequest(Table(table).all(), format: format, to: &stream)
}
}
}

Expand Down Expand Up @@ -246,7 +270,7 @@ extension Database {
}
if tables.isEmpty { return }
stream.write("\n")
try _dumpTables(tables, format: format, tableHeader: .always, to: &stream)
try _dumpTables(tables, format: format, tableHeader: .always, stableOrder: true, to: &stream)
}
}

Expand Down
16 changes: 14 additions & 2 deletions GRDB/Dump/DatabaseReader+dump.swift
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ extension DatabaseReader {
}
}

/// Prints the contents of the provided tables.
/// Prints the contents of the provided tables and views.
///
/// For example:
///
Expand All @@ -72,17 +72,29 @@ extension DatabaseReader {
/// - tables: The table names.
/// - format: The output format.
/// - tableHeader: Options for printing table names.
/// - stableOrder: A boolean value that controls the ordering of
/// rows fetched from views. If false (the default), rows are
/// printed in the order specified by the view (which may be
/// undefined). It true, outputted rows are always printed in the
/// same stable order. The purpose of this stable order is to make
/// the output suitable for testing.
/// - stream: A stream for text output, which directs output to the
/// console by default.
public func dumpTables(
_ tables: [String],
format: some DumpFormat = .debug(),
tableHeader: DumpTableHeaderOptions = .automatic,
stableOrder: Bool = false,
to stream: (any TextOutputStream)? = nil)
throws
{
try unsafeReentrantRead { db in
try db.dumpTables(tables, format: format, tableHeader: tableHeader, to: stream)
try db.dumpTables(
tables,
format: format,
tableHeader: tableHeader,
stableOrder: stableOrder,
to: stream)
}
}

Expand Down
62 changes: 61 additions & 1 deletion Tests/GRDBTests/DatabaseDumpTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1072,7 +1072,7 @@ final class DatabaseDumpTests: GRDBTestCase {
}
}

func test_dumpTables_single() throws {
func test_dumpTables_single_table() throws {
try makeRugbyDatabase().read { db in
do {
// Default format
Expand All @@ -1099,6 +1099,66 @@ final class DatabaseDumpTests: GRDBTestCase {
}
}

func test_dumpTables_single_view() throws {
try makeRugbyDatabase().write { db in
try db.create(view: "playerName", as: Player
.orderByPrimaryKey()
.select(Column("name")))

do {
// Default order: use the view ordering
do {
// Default format
let stream = TestStream()
try db.dumpTables(["playerName"], to: stream)
XCTAssertEqual(stream.output, """
Antoine Dupond
Owen Farrell
Gwendal Roué
""")
}
do {
// Custom format
let stream = TestStream()
try db.dumpTables(["playerName"], format: .json(), to: stream)
XCTAssertEqual(stream.output, """
[{"name":"Antoine Dupond"},
{"name":"Owen Farrell"},
{"name":"Gwendal Roué"}]
""")
}
}

do {
// Stable order
do {
// Default format
let stream = TestStream()
try db.dumpTables(["playerName"], stableOrder: true, to: stream)
XCTAssertEqual(stream.output, """
Antoine Dupond
Gwendal Roué
Owen Farrell
""")
}
do {
// Custom format
let stream = TestStream()
try db.dumpTables(["playerName"], format: .json(), stableOrder: true, to: stream)
XCTAssertEqual(stream.output, """
[{"name":"Antoine Dupond"},
{"name":"Gwendal Roué"},
{"name":"Owen Farrell"}]
""")
}
}
}
}

func test_dumpTables_multiple() throws {
try makeRugbyDatabase().read { db in
do {
Expand Down

0 comments on commit ba320a0

Please sign in to comment.