DataLiteCore swift package
This commit is contained in:
105
Sources/DataLiteCore/Structures/Pragma.swift
Normal file
105
Sources/DataLiteCore/Structures/Pragma.swift
Normal file
@@ -0,0 +1,105 @@
|
||||
import Foundation
|
||||
|
||||
/// A type representing SQLite pragmas.
|
||||
///
|
||||
/// The `Pragma` structure provides a convenient way to work with
|
||||
/// SQLite pragmas, which are special commands used to control various aspects
|
||||
/// of the SQLite database engine. For more information on SQLite pragmas,
|
||||
/// visit the [SQLite Pragma Documentation](https://www.sqlite.org/pragma.html).
|
||||
///
|
||||
/// ## Topics
|
||||
///
|
||||
/// ### Initializers
|
||||
///
|
||||
/// - ``init(rawValue:)``
|
||||
/// - ``init(stringLiteral:)``
|
||||
///
|
||||
/// ### Instances
|
||||
///
|
||||
/// - ``applicationID``
|
||||
/// - ``foreignKeys``
|
||||
/// - ``journalMode``
|
||||
/// - ``synchronous``
|
||||
/// - ``userVersion``
|
||||
public struct Pragma: RawRepresentable, CustomStringConvertible, ExpressibleByStringLiteral, Sendable {
|
||||
// MARK: - Properties
|
||||
|
||||
/// The raw string value of the pragma.
|
||||
///
|
||||
/// This is the underlying string that represents the pragma, which can be used
|
||||
/// directly in SQL queries.
|
||||
public var rawValue: String
|
||||
|
||||
/// A textual representation of the pragma.
|
||||
///
|
||||
/// This provides a description of the pragma as a string.
|
||||
public var description: String {
|
||||
rawValue
|
||||
}
|
||||
|
||||
// MARK: - Instances
|
||||
|
||||
/// Represents the `application_id` pragma.
|
||||
///
|
||||
/// This pragma allows you to query or set the application ID associated with the
|
||||
/// SQLite database file. The application ID is a 32-bit integer that can be used for
|
||||
/// versioning or identification purposes. For more details, see
|
||||
/// [application_id](https://www.sqlite.org/pragma.html#pragma_application_id).
|
||||
public static let applicationID: Pragma = "application_id"
|
||||
|
||||
/// Represents the `foreign_keys` pragma.
|
||||
///
|
||||
/// This pragma controls the enforcement of foreign key constraints in SQLite.
|
||||
/// Foreign key constraints are disabled by default, but you can enable them
|
||||
/// by using this pragma. For more details, see
|
||||
/// [foreign_keys](https://www.sqlite.org/pragma.html#pragma_foreign_keys).
|
||||
public static let foreignKeys: Pragma = "foreign_keys"
|
||||
|
||||
/// Represents the `journal_mode` pragma.
|
||||
///
|
||||
/// This pragma is used to query or configure the journal mode for the database connection.
|
||||
/// The journal mode determines how transactions are logged, influencing both the
|
||||
/// performance and recovery behavior of the database. For more details, see
|
||||
/// [journal_mode](https://www.sqlite.org/pragma.html#pragma_journal_mode).
|
||||
public static let journalMode: Pragma = "journal_mode"
|
||||
|
||||
/// Represents the `synchronous` pragma.
|
||||
///
|
||||
/// This pragma is used to query or configure the synchronous mode for the database connection.
|
||||
/// The synchronous mode controls how the database synchronizes with the disk during write operations,
|
||||
/// affecting both performance and durability. For more details, see
|
||||
/// [synchronous](https://www.sqlite.org/pragma.html#pragma_synchronous).
|
||||
public static let synchronous: Pragma = "synchronous"
|
||||
|
||||
/// Represents the `user_version` pragma.
|
||||
///
|
||||
/// This pragma is commonly used to query or set the user version number associated
|
||||
/// with the database file. It is useful for schema versioning or implementing custom
|
||||
/// database management strategies. For more details, see
|
||||
/// [user_version](https://www.sqlite.org/pragma.html#pragma_user_version).
|
||||
public static let userVersion: Pragma = "user_version"
|
||||
|
||||
public static let busyTimeout: Pragma = "busy_timeout"
|
||||
|
||||
// MARK: - Inits
|
||||
|
||||
/// Initializes a `Pragma` instance with the provided raw value.
|
||||
///
|
||||
/// - Parameter rawValue: The raw string value of the pragma.
|
||||
///
|
||||
/// This initializer allows you to create a `Pragma` instance with any raw string
|
||||
/// that represents a valid SQLite pragma.
|
||||
public init(rawValue: String) {
|
||||
self.rawValue = rawValue
|
||||
}
|
||||
|
||||
/// Initializes a `Pragma` instance with the provided string literal.
|
||||
///
|
||||
/// - Parameter value: The string literal representing the pragma.
|
||||
///
|
||||
/// This initializer allows you to create a `Pragma` instance using a string literal,
|
||||
/// providing a convenient syntax for common pragmas.
|
||||
public init(stringLiteral value: String) {
|
||||
self.rawValue = value
|
||||
}
|
||||
}
|
||||
273
Sources/DataLiteCore/Structures/SQLScript.swift
Normal file
273
Sources/DataLiteCore/Structures/SQLScript.swift
Normal file
@@ -0,0 +1,273 @@
|
||||
import Foundation
|
||||
|
||||
/// A structure representing a collection of SQL queries.
|
||||
///
|
||||
/// ## Overview
|
||||
///
|
||||
/// `SQLScript` is a structure for loading and processing SQL scripts, representing a collection
|
||||
/// where each element is an individual SQL query. It allows loading scripts from a file via URL,
|
||||
/// from the app bundle, or from a string, and provides convenient access to individual SQL queries
|
||||
/// and the ability to iterate over them.
|
||||
///
|
||||
/// ## Usage Examples
|
||||
///
|
||||
/// ### Loading from a File
|
||||
///
|
||||
/// To load a SQL script from a file in your project, use the following code. In this example,
|
||||
/// we load a file named `sample_script.sql` from the main app bundle.
|
||||
///
|
||||
/// ```swift
|
||||
/// do {
|
||||
/// guard let sqlScript = try SQLScript(
|
||||
/// byResource: "sample_script",
|
||||
/// extension: "sql"
|
||||
/// ) else {
|
||||
/// throw NSError(
|
||||
/// domain: "SomeDomain",
|
||||
/// code: -1,
|
||||
/// userInfo: [:]
|
||||
/// )
|
||||
/// }
|
||||
///
|
||||
/// for (index, statement) in sqlScript.enumerated() {
|
||||
/// print("Query \(index + 1):")
|
||||
/// print(statement)
|
||||
/// print("--------------------")
|
||||
/// }
|
||||
/// } catch {
|
||||
/// print("Error: \(error.localizedDescription)")
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ### Loading from a String
|
||||
///
|
||||
/// If the SQL queries are already contained in a string, you can create an instance of `SQLScript`
|
||||
/// by passing the string to the initializer. Below is an example where we create a SQL script
|
||||
/// with two queries: creating a table and inserting data.
|
||||
///
|
||||
/// ```swift
|
||||
/// do {
|
||||
/// let sqlString = """
|
||||
/// CREATE TABLE users (
|
||||
/// id INTEGER PRIMARY KEY,
|
||||
/// username TEXT NOT NULL,
|
||||
/// email TEXT NOT NULL
|
||||
/// );
|
||||
/// INSERT INTO users (id, username, email)
|
||||
/// VALUES (1, 'john_doe', 'john@example.com');
|
||||
/// """
|
||||
///
|
||||
/// let sqlScript = try SQLScript(string: sqlString)
|
||||
///
|
||||
/// for (index, statement) in sqlScript.enumerated() {
|
||||
/// print("Query \(index + 1):")
|
||||
/// print(statement)
|
||||
/// print("--------------------")
|
||||
/// }
|
||||
/// } catch {
|
||||
/// print("Error: \(error.localizedDescription)")
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## SQL Format and Syntax
|
||||
///
|
||||
/// `SQLScript` is designed to handle SQL scripts that contain one or more SQL queries. Each query
|
||||
/// must end with a semicolon (`;`), which indicates the end of the statement.
|
||||
///
|
||||
/// **Supported Features:**
|
||||
///
|
||||
/// - **Command Separation:** Each query ends with a semicolon (`;`), marking the end of the command.
|
||||
/// - **Formatting:** SQLScript removes lines containing only whitespace or comments, keeping
|
||||
/// only the valid SQL queries in the collection.
|
||||
/// - **Comment Support:** Single-line (`--`) and multi-line (`/* */`) comments are supported.
|
||||
///
|
||||
/// **Example of a correctly formatted SQL script:**
|
||||
///
|
||||
/// ```sql
|
||||
/// -- Create users table
|
||||
/// CREATE TABLE users (
|
||||
/// id INTEGER PRIMARY KEY,
|
||||
/// username TEXT NOT NULL,
|
||||
/// email TEXT NOT NULL
|
||||
/// );
|
||||
///
|
||||
/// -- Insert data into users table
|
||||
/// INSERT INTO users (id, username, email)
|
||||
/// VALUES (1, 'john_doe', 'john@example.com');
|
||||
///
|
||||
/// /* Update user data */
|
||||
/// UPDATE users
|
||||
/// SET email = 'john.doe@example.com'
|
||||
/// WHERE id = 1;
|
||||
/// ```
|
||||
///
|
||||
/// - Important: Nested comments are not supported, so avoid placing multi-line comments inside
|
||||
/// other multi-line comments.
|
||||
///
|
||||
/// - Important: `SQLScript` does not support SQL scripts containing transactions.
|
||||
/// To execute an `SQLScript`, use the method ``Connection/execute(sql:)``, which executes
|
||||
/// each statement individually in autocommit mode.
|
||||
///
|
||||
/// If you need to execute the entire `SQLScript` within a single transaction, use the methods
|
||||
/// ``Connection/beginTransaction(_:)``, ``Connection/commitTransaction()``, and
|
||||
/// ``Connection/rollbackTransaction()`` to manage the transaction explicitly.
|
||||
///
|
||||
/// If your SQL script includes transaction statements (e.g., BEGIN, COMMIT, ROLLBACK),
|
||||
/// execute the entire script using ``Connection/execute(raw:)``.
|
||||
///
|
||||
/// - Important: This class is not designed to work with untrusted user data. Never insert
|
||||
/// user-provided data directly into SQL queries without proper sanitization or parameterization.
|
||||
/// Unfiltered data can lead to SQL injection attacks, which pose a security risk to your data and
|
||||
/// database. For more information about SQL injection risks, see the OWASP documentation:
|
||||
/// [SQL Injection](https://owasp.org/www-community/attacks/SQL_Injection).
|
||||
public struct SQLScript: Collection, ExpressibleByStringLiteral {
|
||||
/// The type representing the index in the collection of SQL queries.
|
||||
///
|
||||
/// This type is used to access elements in the `SQLScript` collection. The index is an
|
||||
/// integer (`Int`) indicating the position of the SQL query in the collection.
|
||||
public typealias Index = Int
|
||||
|
||||
/// The type representing an element in the collection of SQL queries.
|
||||
///
|
||||
/// This type defines that each element in the `SQLScript` collection is a string (`String`).
|
||||
/// Each element represents a separate SQL query that can be loaded and processed.
|
||||
public typealias Element = String
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// An array containing SQL queries.
|
||||
private var elements: [Element]
|
||||
|
||||
/// The starting index of the collection of SQL queries.
|
||||
///
|
||||
/// This property returns the index of the first element in the collection. The starting
|
||||
/// index is used to initialize iterators and access the elements of the collection. If
|
||||
/// the collection is empty, this value will equal `endIndex`.
|
||||
public var startIndex: Index {
|
||||
elements.startIndex
|
||||
}
|
||||
|
||||
/// The end index of the collection of SQL queries.
|
||||
///
|
||||
/// This property returns the index that indicates the position following the last element
|
||||
/// of the collection. The end index is used for iterating over the collection and marks
|
||||
/// the point where the collection ends. If the collection is empty, this value will equal
|
||||
/// `startIndex`.
|
||||
public var endIndex: Index {
|
||||
elements.endIndex
|
||||
}
|
||||
|
||||
/// The number of SQL queries in the collection.
|
||||
///
|
||||
/// This property returns the total number of SQL queries stored in the collection. The
|
||||
/// value will be 0 if the collection is empty. Use this property to know how many queries
|
||||
/// can be processed or iterated over.
|
||||
public var count: Int {
|
||||
elements.count
|
||||
}
|
||||
|
||||
/// A Boolean value indicating whether the collection is empty.
|
||||
///
|
||||
/// This property returns `true` if there are no SQL queries in the collection, and `false`
|
||||
/// otherwise. Use this property to check for the presence of SQL queries before performing
|
||||
/// operations that require elements in the collection.
|
||||
public var isEmpty: Bool {
|
||||
elements.isEmpty
|
||||
}
|
||||
|
||||
// MARK: - Inits
|
||||
|
||||
/// Initializes an instance of `SQLScript`, loading SQL queries from a resource file.
|
||||
///
|
||||
/// This initializer looks for a file with the specified name and extension in the given
|
||||
/// bundle and loads its contents as SQL queries.
|
||||
///
|
||||
/// - If `name` is `nil`, the first found resource file with the specified extension will
|
||||
/// be loaded.
|
||||
/// - If `extension` is an empty string or `nil`, it is assumed that the extension does
|
||||
/// not exist, and the first found file that exactly matches the name will be loaded.
|
||||
/// - Returns `nil` if the specified file is not found.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - name: The name of the resource file containing SQL queries.
|
||||
/// - extension: The extension of the resource file. Defaults to `nil`.
|
||||
/// - bundle: The bundle from which to load the resource file. Defaults to `.main`.
|
||||
///
|
||||
/// - Throws: An error if the file cannot be loaded or processed.
|
||||
public init?(
|
||||
byResource name: String?,
|
||||
extension: String? = nil,
|
||||
in bundle: Bundle = .main
|
||||
) throws {
|
||||
guard let url = bundle.url(
|
||||
forResource: name,
|
||||
withExtension: `extension`
|
||||
) else { return nil }
|
||||
try self.init(contentsOf: url)
|
||||
}
|
||||
|
||||
/// Initializes an instance of `SQLScript`, loading SQL queries from the specified file.
|
||||
///
|
||||
/// This initializer takes a URL to a file and loads its contents as SQL queries.
|
||||
///
|
||||
/// - Parameter url: The URL of the file containing SQL queries.
|
||||
///
|
||||
/// - Throws: An error if the file cannot be loaded or processed.
|
||||
public init(contentsOf url: URL) throws {
|
||||
try self.init(string: .init(contentsOf: url, encoding: .utf8))
|
||||
}
|
||||
|
||||
/// Initializes an instance of `SQLScript` from a string literal.
|
||||
///
|
||||
/// This initializer allows you to create a `SQLScript` instance directly from a string literal.
|
||||
/// The string is parsed into individual SQL queries, removing comments and empty lines.
|
||||
///
|
||||
/// - Parameter value: The string literal containing SQL queries. Each query should be separated
|
||||
/// by semicolons (`;`), and the string can include comments and empty lines, which will
|
||||
/// be ignored during initialization.
|
||||
///
|
||||
/// - Warning: The string literal should represent valid SQL queries. Invalid syntax or
|
||||
/// improperly formatted SQL may lead to an error at runtime.
|
||||
public init(stringLiteral value: StringLiteralType) {
|
||||
self.init(string: value)
|
||||
}
|
||||
|
||||
/// Initializes an instance of `SQLScript` by parsing SQL queries from the specified string.
|
||||
///
|
||||
/// This initializer takes a string containing SQL queries and extracts individual queries,
|
||||
/// removing comments and empty lines.
|
||||
///
|
||||
/// - Parameter string: The string containing SQL queries.
|
||||
public init(string: String) {
|
||||
elements = string
|
||||
.removingComments()
|
||||
.trimmingLines()
|
||||
.splitStatements()
|
||||
}
|
||||
|
||||
// MARK: - Collection Methods
|
||||
|
||||
/// Accesses the element at the specified position in the collection.
|
||||
///
|
||||
/// - Parameter index: The index of the SQL query in the collection. The index must be within the
|
||||
/// bounds of the collection. If an out-of-bounds index is provided, a runtime error will occur.
|
||||
///
|
||||
/// - Returns: The SQL query as a string at the specified index.
|
||||
public subscript(index: Index) -> Element {
|
||||
elements[index]
|
||||
}
|
||||
|
||||
/// Returns the index after the given index.
|
||||
///
|
||||
/// This method is used for iterating through the collection. It provides the next valid
|
||||
/// index following the specified index.
|
||||
///
|
||||
/// - Parameter i: The index of the current element.
|
||||
///
|
||||
/// - Returns: The index of the next element in the collection. If `i` is the last
|
||||
/// index in the collection, this method returns `endIndex`, which is one past the
|
||||
/// last valid index.
|
||||
public func index(after i: Index) -> Index {
|
||||
elements.index(after: i)
|
||||
}
|
||||
}
|
||||
225
Sources/DataLiteCore/Structures/SQLiteRow.swift
Normal file
225
Sources/DataLiteCore/Structures/SQLiteRow.swift
Normal file
@@ -0,0 +1,225 @@
|
||||
import Foundation
|
||||
import OrderedCollections
|
||||
|
||||
/// A structure representing a single row in an SQLite database, providing ordered access to columns and their values.
|
||||
///
|
||||
/// The `SQLiteRow` structure allows for convenient access to the data stored in a row of an SQLite
|
||||
/// database, using an ordered dictionary to maintain the insertion order of columns. This makes it
|
||||
/// easy to retrieve, update, and manage the values associated with each column in the row.
|
||||
///
|
||||
/// ```swift
|
||||
/// let row = SQLiteRow()
|
||||
/// row["name"] = "John Doe"
|
||||
/// row["age"] = 30
|
||||
/// print(row.description)
|
||||
/// // Outputs: ["name": 'John Doe', "age": 30]
|
||||
/// ```
|
||||
///
|
||||
/// ## Topics
|
||||
///
|
||||
/// ### Type Aliases
|
||||
///
|
||||
/// - ``Elements``
|
||||
/// - ``Column``
|
||||
/// - ``Value``
|
||||
/// - ``Index``
|
||||
/// - ``Element``
|
||||
public struct SQLiteRow: Collection, CustomStringConvertible, Equatable {
|
||||
// MARK: - Type Aliases
|
||||
|
||||
/// A type for the internal storage of column names and their associated values in a database row.
|
||||
///
|
||||
/// This ordered dictionary is used to store column data for a row, retaining the insertion order
|
||||
/// of columns as they appear in the SQLite database. Each key-value pair corresponds to a column name
|
||||
/// and its associated value, represented by `SQLiteRawValue`.
|
||||
///
|
||||
/// - Key: `String` representing the name of the column.
|
||||
/// - Value: `SQLiteRawValue` representing the value of the column in the row.
|
||||
public typealias Elements = OrderedDictionary<String, SQLiteRawValue>
|
||||
|
||||
/// A type representing the name of a column in a database row.
|
||||
///
|
||||
/// This type alias provides a convenient way to refer to column names within a row.
|
||||
/// Each `Column` is a `String` key that corresponds to a specific column in the SQLite row,
|
||||
/// matching the key type of the `Elements` dictionary.
|
||||
public typealias Column = Elements.Key
|
||||
|
||||
/// A type representing the value of a column in a database row.
|
||||
///
|
||||
/// This type alias provides a convenient way to refer to the data stored in a column.
|
||||
/// Each `Value` is of type `SQLiteRawValue`, which corresponds to the value associated
|
||||
/// with a specific column in the SQLite row, matching the value type of the `Elements` dictionary.
|
||||
public typealias Value = Elements.Value
|
||||
|
||||
/// A type representing the index of a column in a database row.
|
||||
///
|
||||
/// This type alias provides a convenient way to refer to the position of a column
|
||||
/// within the ordered collection of columns. Each `Index` is an integer that corresponds
|
||||
/// to the index of a specific column in the SQLite row, matching the index type of the `Elements` dictionary.
|
||||
public typealias Index = Elements.Index
|
||||
|
||||
/// A type representing a column-value pair in a database row.
|
||||
///
|
||||
/// This type alias defines an element as a tuple consisting of a `Column` and its associated
|
||||
/// `Value`. Each `Element` encapsulates a single column name and its corresponding value,
|
||||
/// providing a clear structure for accessing and managing data within the SQLite row.
|
||||
public typealias Element = (column: Column, value: Value)
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
/// An ordered dictionary that stores the columns and their associated values in the row.
|
||||
///
|
||||
/// This private property holds the internal representation of the row's data as an
|
||||
/// `OrderedDictionary`, maintaining the insertion order of columns. It is used to
|
||||
/// facilitate access to the row's columns and values, ensuring that the original
|
||||
/// order from the SQLite database is preserved.
|
||||
private var elements: Elements
|
||||
|
||||
/// The starting index of the row, which is always zero.
|
||||
///
|
||||
/// This property indicates the initial position of the row's elements. Since the
|
||||
/// elements in the row are indexed starting from zero, this property consistently
|
||||
/// returns zero, allowing for predictable iteration through the row's data.
|
||||
///
|
||||
/// - Complexity: `O(1)`
|
||||
public var startIndex: Index {
|
||||
0
|
||||
}
|
||||
|
||||
/// The ending index of the row, which is equal to the number of columns.
|
||||
///
|
||||
/// This property indicates the position one past the last element in the row.
|
||||
/// It returns the count of columns in the row, allowing for proper iteration
|
||||
/// through the row's data in a collection context. The `endIndex` is useful
|
||||
/// for determining the bounds of the row's elements when traversing or accessing them.
|
||||
///
|
||||
/// - Complexity: `O(1)`
|
||||
public var endIndex: Index {
|
||||
elements.count
|
||||
}
|
||||
|
||||
/// A Boolean value indicating whether the row is empty.
|
||||
///
|
||||
/// This property returns `true` if the row contains no columns; otherwise, it returns `false`.
|
||||
/// It provides a quick way to check if there are any data present in the row, which can be
|
||||
/// useful for validation or conditional logic when working with database rows.
|
||||
///
|
||||
/// - Complexity: `O(1)`
|
||||
public var isEmpty: Bool {
|
||||
elements.isEmpty
|
||||
}
|
||||
|
||||
/// The number of columns in the row.
|
||||
///
|
||||
/// This property returns the total count of columns stored in the row. It reflects
|
||||
/// the number of column-value pairs in the `elements` dictionary, providing a convenient
|
||||
/// way to determine how much data is present in the row. This is useful for iteration
|
||||
/// and conditional checks when working with database rows.
|
||||
///
|
||||
/// - Complexity: `O(1)`
|
||||
public var count: Int {
|
||||
elements.count
|
||||
}
|
||||
|
||||
/// A textual description of the row, showing the columns and values.
|
||||
///
|
||||
/// This property returns a string representation of the row, including all column names
|
||||
/// and their associated values. The description is generated from the `elements` dictionary,
|
||||
/// providing a clear and concise overview of the row's data, which can be helpful for debugging
|
||||
/// and logging purposes.
|
||||
public var description: String {
|
||||
elements.description
|
||||
}
|
||||
|
||||
/// A list of column names in the row, preserving their insertion order.
|
||||
///
|
||||
/// Useful for dynamically generating SQL queries (e.g. `INSERT INTO ... (columns)`).
|
||||
///
|
||||
/// - Complexity: `O(1)`
|
||||
public var columns: [String] {
|
||||
elements.keys.elements
|
||||
}
|
||||
|
||||
/// A list of SQL named parameters in the form `:column`, preserving column order.
|
||||
///
|
||||
/// Useful for generating placeholders in SQL queries (e.g. `VALUES (:column1, :column2, ...)`)
|
||||
/// to match the row's structure.
|
||||
///
|
||||
/// - Complexity: `O(n)`
|
||||
public var namedParameters: [String] {
|
||||
elements.keys.map { ":\($0)" }
|
||||
}
|
||||
|
||||
// MARK: - Inits
|
||||
|
||||
/// Initializes an empty row.
|
||||
///
|
||||
/// This initializer creates a new instance of `SQLiteRow` with no columns or values.
|
||||
public init() {
|
||||
elements = [:]
|
||||
}
|
||||
|
||||
// MARK: - Subscripts
|
||||
|
||||
/// Accesses the element at the specified index.
|
||||
///
|
||||
/// This subscript allows you to retrieve a column-value pair from the row by its index.
|
||||
/// It returns an `Element`, which is a tuple containing the column name and its associated
|
||||
/// value. The index must be valid; otherwise, it will trigger a runtime error.
|
||||
///
|
||||
/// - Parameter index: The index of the element to access.
|
||||
/// - Returns: A tuple containing the column name and its associated value.
|
||||
///
|
||||
/// - Complexity: `O(1)`
|
||||
public subscript(index: Index) -> Element {
|
||||
let element = elements.elements[index]
|
||||
return (element.key, element.value)
|
||||
}
|
||||
|
||||
/// Accesses the value for the specified column.
|
||||
///
|
||||
/// This subscript allows you to retrieve or set the value associated with a given column name.
|
||||
/// It returns an optional `Value`, which is the value stored in the row for the specified column.
|
||||
/// If the column does not exist, it returns `nil`. When setting a value, the column will be created
|
||||
/// if it does not already exist.
|
||||
///
|
||||
/// - Parameter column: The name of the column to access.
|
||||
/// - Returns: The value associated with the specified column, or `nil` if the column does not exist.
|
||||
///
|
||||
/// - Complexity: On average, the complexity is O(1) for lookups and amortized O(1) for updates.
|
||||
public subscript(column: Column) -> Value? {
|
||||
get { elements[column] }
|
||||
set { elements[column] = newValue }
|
||||
}
|
||||
|
||||
// MARK: - Methods
|
||||
|
||||
/// Returns the index immediately after the given index.
|
||||
///
|
||||
/// This method provides the next valid index in the row's collection after the specified index.
|
||||
/// It increments the given index by one, allowing for iteration through the row's elements
|
||||
/// in a collection context. If the provided index is the last valid index, this method
|
||||
/// will return an index that may not be valid for the collection, so it should be used
|
||||
/// in conjunction with bounds checking.
|
||||
///
|
||||
/// - Parameter i: A valid index of the row.
|
||||
/// - Returns: The index immediately after `i`.
|
||||
///
|
||||
/// - Complexity: `O(1)`
|
||||
public func index(after i: Index) -> Index {
|
||||
i + 1
|
||||
}
|
||||
|
||||
/// Checks if the row contains a value for the specified column.
|
||||
///
|
||||
/// This method determines whether a column with the given name exists in the row. It is
|
||||
/// useful for validating the presence of data before attempting to access it.
|
||||
///
|
||||
/// - Parameter column: The name of the column to check for.
|
||||
/// - Returns: `true` if the column exists; otherwise, `false`.
|
||||
///
|
||||
/// - Complexity: On average, the complexity is `O(1)`.
|
||||
public func contains(_ column: Column) -> Bool {
|
||||
elements.keys.contains(column)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user