DataLiteCore swift package

This commit is contained in:
2025-04-24 23:48:46 +03:00
parent b0e52a72b7
commit 6f955b2c43
70 changed files with 7939 additions and 1 deletions

View File

@@ -0,0 +1,50 @@
import Testing
import DataLiteCore
struct BinaryFloatingPointTests {
@Test func testFloatToSQLiteRawValue() {
let floatValue: Float = 3.14
let rawValue = floatValue.sqliteRawValue
#expect(rawValue == .real(Double(floatValue)))
}
@Test func testDoubleToSQLiteRawValue() {
let doubleValue: Double = 3.14
let rawValue = doubleValue.sqliteRawValue
#expect(rawValue == .real(doubleValue))
}
@Test func testFloatInitializationFromSQLiteRawValue() {
let realValue: SQLiteRawValue = .real(3.14)
let floatValue = Float(realValue)
#expect(floatValue != nil)
#expect(floatValue == 3.14)
let intValue: SQLiteRawValue = .int(42)
let floatFromInt = Float(intValue)
#expect(floatFromInt != nil)
#expect(floatFromInt == 42.0)
}
@Test func testDoubleInitializationFromSQLiteRawValue() {
let realValue: SQLiteRawValue = .real(3.14)
let doubleValue = Double(realValue)
#expect(doubleValue != nil)
#expect(doubleValue == 3.14)
let intValue: SQLiteRawValue = .int(42)
let doubleFromInt = Double(intValue)
#expect(doubleFromInt != nil)
#expect(doubleFromInt == 42.0)
}
@Test func testInitializationFailureFromInvalidSQLiteRawValue() {
let nullValue: SQLiteRawValue = .null
#expect(Float(nullValue) == nil)
#expect(Double(nullValue) == nil)
let textValue: SQLiteRawValue = .text("Invalid")
#expect(Float(textValue) == nil)
#expect(Double(textValue) == nil)
}
}

View File

@@ -0,0 +1,43 @@
import Testing
import Foundation
import DataLiteCore
struct BinaryIntegerTests {
@Test func testIntegerToSQLiteRawValue() {
#expect(Int(42).sqliteRawValue == .int(42))
#expect(Int8(42).sqliteRawValue == .int(42))
#expect(Int16(42).sqliteRawValue == .int(42))
#expect(Int32(42).sqliteRawValue == .int(42))
#expect(Int64(42).sqliteRawValue == .int(42))
#expect(UInt(42).sqliteRawValue == .int(42))
#expect(UInt8(42).sqliteRawValue == .int(42))
#expect(UInt16(42).sqliteRawValue == .int(42))
#expect(UInt32(42).sqliteRawValue == .int(42))
#expect(UInt64(42).sqliteRawValue == .int(42))
}
@Test func testIntegerInitializationFromSQLiteRawValue() {
#expect(Int(SQLiteRawValue.int(42)) == 42)
#expect(Int8(SQLiteRawValue.int(42)) == 42)
#expect(Int16(SQLiteRawValue.int(42)) == 42)
#expect(Int32(SQLiteRawValue.int(42)) == 42)
#expect(Int64(SQLiteRawValue.int(42)) == 42)
#expect(UInt(SQLiteRawValue.int(42)) == 42)
#expect(UInt8(SQLiteRawValue.int(42)) == 42)
#expect(UInt16(SQLiteRawValue.int(42)) == 42)
#expect(UInt32(SQLiteRawValue.int(42)) == 42)
#expect(UInt64(SQLiteRawValue.int(42)) == 42)
}
@Test func testInvalidIntegerInitialization() {
#expect(Int(SQLiteRawValue.real(3.14)) == nil)
#expect(Int8(SQLiteRawValue.text("test")) == nil)
#expect(UInt32(SQLiteRawValue.blob(Data([0x01, 0x02]))) == nil)
// Out-of-range conversion
let largeValue = Int64.max
#expect(Int8(exactly: largeValue) == nil)
}
}

View File

@@ -0,0 +1,22 @@
import Testing
import Foundation
import DataLiteCore
struct BoolTests {
@Test func testBoolToSQLiteRawValue() {
#expect(true.sqliteRawValue == .int(1))
#expect(false.sqliteRawValue == .int(0))
}
@Test func testSQLiteRawValueToBool() {
#expect(Bool(.int(1)) == true)
#expect(Bool(.int(0)) == false)
#expect(Bool(.int(-1)) == nil)
#expect(Bool(.int(2)) == nil)
#expect(Bool(.real(1.0)) == nil)
#expect(Bool(.text("true")) == nil)
#expect(Bool(.blob(Data())) == nil)
#expect(Bool(.null) == nil)
}
}

View File

@@ -0,0 +1,22 @@
import Testing
import Foundation
import DataLiteCore
struct DataSQLiteRawRepresentableTests {
@Test func testDataToSQLiteRawValue() {
let data = Data([0x01, 0x02, 0x03])
#expect(data.sqliteRawValue == .blob(data))
}
@Test func testSQLiteRawValueToData() {
let data = Data([0x01, 0x02, 0x03])
let rawValue = SQLiteRawValue.blob(data)
#expect(Data(rawValue) == data)
#expect(Data(.int(1)) == nil)
#expect(Data(.real(1.0)) == nil)
#expect(Data(.text("blob")) == nil)
#expect(Data(.null) == nil)
}
}

View File

@@ -0,0 +1,32 @@
import Testing
import Foundation
import DataLiteCore
struct DateSQLiteRawRepresentableTests {
@Test func testDateToSQLiteRawValue() {
let date = Date(timeIntervalSince1970: 1609459200)
let formatter = ISO8601DateFormatter()
let dateString = formatter.string(from: date)
#expect(date.sqliteRawValue == .text(dateString))
}
@Test func testSQLiteRawValueToDate() {
let date = Date(timeIntervalSince1970: 1609459200)
let formatter = ISO8601DateFormatter()
let dateString = formatter.string(from: date)
let rawText = SQLiteRawValue.text(dateString)
#expect(Date(rawText) == date)
let rawInt = SQLiteRawValue.int(1609459200)
#expect(Date(rawInt) == date)
let rawReal = SQLiteRawValue.real(1609459200)
#expect(Date(rawReal) == date)
#expect(Date(.blob(Data([0x01, 0x02, 0x03]))) == nil)
#expect(Date(.null) == nil)
#expect(Date(.text("Invalid date format")) == nil)
}
}

View File

@@ -0,0 +1,27 @@
import Testing
import Foundation
import DataLiteCore
struct RawRepresentableTests {
@Test func testRawRepresentableToSQLiteRawValue() {
let color: Color = .green
#expect(color.sqliteRawValue == .int(1))
}
@Test func testSQLiteRawValueToRawRepresentable() {
#expect(Color(.int(2)) == .blue)
#expect(Color(.int(42)) == nil)
#expect(Color(.text("red")) == nil)
#expect(Color(.blob(Data([0x01, 0x02]))) == nil)
#expect(Color(.null) == nil)
}
}
private extension RawRepresentableTests {
enum Color: Int, SQLiteRawRepresentable {
case red
case green
case blue
}
}

View File

@@ -0,0 +1,394 @@
import Foundation
import Testing
@testable import DataLiteCore
struct StringSQLTests {
// MARK: - Test Remove Single Line Comments
@Test func testSingleLineCommentAtStart() {
let input = """
-- This is a comment
SELECT * FROM users;
"""
let expected = """
SELECT * FROM users;
"""
#expect(input.removingComments() == expected)
}
@Test func testSingleLineCommentAfterStatement() {
let input = """
SELECT * FROM users; -- This is a comment
"""
let expected = """
SELECT * FROM users;\u{0020}
"""
#expect(input.removingComments() == expected)
}
@Test func testSingleLineCommentBetweenStatementLines() {
let input = """
INSERT INTO users (
id, name
-- comment between statement
) VALUES (1, 'Alice');
"""
let expected = """
INSERT INTO users (
id, name
) VALUES (1, 'Alice');
"""
#expect(input.removingComments() == expected)
}
@Test func testSingleLineCommentAtEnd() {
let input = """
SELECT * FROM users;
-- final comment
"""
let expected = """
SELECT * FROM users;
"""
#expect(input.removingComments() == expected)
}
@Test func testSingleLineCommentWithTabsAndSpaces() {
let input = "SELECT 1;\t -- comment with tab\nSELECT 2;"
let expected = "SELECT 1;\t \nSELECT 2;"
#expect(input.removingComments() == expected)
}
@Test func testSingleLineCommentWithLiterals() {
let input = """
INSERT INTO logs (text) VALUES ('This isn''t -- a comment'); -- trailing comment
"""
let expected = """
INSERT INTO logs (text) VALUES ('This isn''t -- a comment');
"""
#expect(input.removingComments() == expected)
}
// MARK: - Test Remove Multiline Comments
@Test func testMultilineCommentAtStart() {
let input = """
/* This is a
comment at the top */
SELECT * FROM users;
"""
let expected = """
SELECT * FROM users;
"""
#expect(input.removingComments() == expected)
}
@Test func testMultilineCommentAtLineStart() {
let input = """
/* comment */ SELECT * FROM users;
"""
let expected = """
\u{0020}SELECT * FROM users;
"""
#expect(input.removingComments() == expected)
}
@Test func testMultilineCommentInMiddleOfLine() {
let input = """
SELECT /* inline comment */ * FROM users;
"""
let expected = """
SELECT * FROM users;
"""
#expect(input.removingComments() == expected)
}
@Test func testMultilineCommentAtEndOfLine() {
let input = """
SELECT * FROM users; /* trailing comment */
"""
let expected = """
SELECT * FROM users;\u{0020}
"""
#expect(input.removingComments() == expected)
}
@Test func testMultilineCommentBetweenLines() {
let input = """
INSERT INTO users (
id,
/* this field stores username */
username,
email
) VALUES (1, 'alice', 'alice@example.com');
"""
let expected = """
INSERT INTO users (
id,
username,
email
) VALUES (1, 'alice', 'alice@example.com');
"""
#expect(input.removingComments() == expected)
}
@Test func testMultilineCommentAtEndOfFile() {
let input = """
SELECT * FROM users;
/* final block comment */
"""
let expected = """
SELECT * FROM users;
"""
#expect(input.removingComments() == expected)
}
@Test func testMultilineCommentWithLiterals() {
let input = """
INSERT INTO notes (text) VALUES ('This isn''t /* a comment */ either'); /* trailing comment */
"""
let expected = """
INSERT INTO notes (text) VALUES ('This isn''t /* a comment */ either');\u{0020}
"""
#expect(input.removingComments() == expected)
}
// MARK: - Test Trimming Lines
@Test func testTrimmingEmptyFirstLine() {
let input = "\nSELECT * FROM users;"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingEmptyFirstLineWithSpace() {
let input = " \nSELECT * FROM users;"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingEmptyFirstLineWithTab() {
let input = "\t\nSELECT * FROM users;"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingEmptyMiddleLine() {
let input = "SELECT *\n\nFROM users;"
let expected = "SELECT *\nFROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingEmptyMiddleLineWithSpace() {
let input = "SELECT *\n\u{0020}\nFROM users;"
let expected = "SELECT *\nFROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingEmptyMiddleLineWithTab() {
let input = "SELECT *\n\t\nFROM users;"
let expected = "SELECT *\nFROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingEmptyLastLine() {
let input = "SELECT * FROM users;\n"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingEmptyLastLineWithSpace() {
let input = "SELECT * FROM users; \n"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingEmptyLastLineWithTab() {
let input = "SELECT * FROM users;\t\n"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingTrailingSpacesOnly() {
let input = "SELECT * FROM users; "
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingTrailingSpacesAndNewline() {
let input = "SELECT * FROM users; \n"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingTrailingTabsOnly() {
let input = "SELECT * FROM users;\t\t"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingTrailingTabsAndNewline() {
let input = "SELECT * FROM users;\t\t\n"
let expected = "SELECT * FROM users;"
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingMultipleEmptyLinesAndSpaces() {
let input = "\n\n\t\u{0020}\nSELECT * FROM users;\n\n\u{0020}\n\n"
let expected = "SELECT * FROM users;"
print("zzzz\n\(input.trimmingLines())")
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingLiteralPreservesWhitespace() {
let input = "INSERT INTO logs VALUES ('line with\n\nspaces \t \n\n and tabs');"
let expected = input
#expect(input.trimmingLines() == expected)
}
@Test func testTrimmingPreserveLineBreaksInMultilineInsert() {
let input = """
INSERT INTO users (id, username, email)
VALUES \t
(1, 'john_doe', 'john@example.com'),
(2, 'jane_doe', 'jane@example.com');
"""
let expected = """
INSERT INTO users (id, username, email)
VALUES
(1, 'john_doe', 'john@example.com'),
(2, 'jane_doe', 'jane@example.com');
"""
#expect(input.trimmingLines() == expected)
}
// MARK: - Test Split Statements
@Test func testSplitSingleStatement() {
let input = "SELECT * FROM users;"
let expected = ["SELECT * FROM users"]
#expect(input.splitStatements() == expected)
}
@Test func testSplitSingleStatementWithoutSemicolon() {
let input = "SELECT * FROM users"
let expected = ["SELECT * FROM users"]
#expect(input.splitStatements() == expected)
}
@Test func testSplitMultipleStatements() {
let input = """
SELECT * FROM users;
DELETE FROM users WHERE id=123;
DELETE FROM users WHERE id=987;
"""
let expected = [
"SELECT * FROM users",
"DELETE FROM users WHERE id=123",
"DELETE FROM users WHERE id=987"
]
#expect(input.splitStatements() == expected)
}
@Test func testSplitMultipleStatementsLastWithoutSemicolon() {
let input = """
SELECT * FROM users;
DELETE FROM users WHERE id=1;
UPDATE users SET name='Bob' WHERE id=2
"""
let expected = [
"SELECT * FROM users",
"DELETE FROM users WHERE id=1",
"UPDATE users SET name='Bob' WHERE id=2"
]
#expect(input.splitStatements() == expected)
}
@Test func testSplitTextLiteralSemicolon() {
let input = "INSERT INTO logs (msg) VALUES ('Hello; world');"
let expected = ["INSERT INTO logs (msg) VALUES ('Hello; world')"]
#expect(input.splitStatements() == expected)
}
@Test func testSplitTextLiteralEscapingQuotes() {
let input = "INSERT INTO test VALUES ('It''s a test');"
let expected = ["INSERT INTO test VALUES ('It''s a test')"]
#expect(input.splitStatements() == expected)
}
@Test func testSplitMultipleSemicolon() {
let input = "SELECT * FROM users;;SELECT * FROM users;"
let expected = [
"SELECT * FROM users",
"SELECT * FROM users"
]
#expect(input.splitStatements() == expected)
}
@Test(arguments: [
("BEGIN", "END"),
("Begin", "End"),
("begin", "end"),
("bEgIn", "eNd"),
("BeGiN", "EnD")
])
func testSplitWithBeginEnd(begin: String, end: String) {
let input = """
CREATE TABLE KDFMetadata (
id INTEGER PRIMARY KEY,
value TEXT NOT NULL
);
CREATE TRIGGER KDFMetadataLimit
BEFORE INSERT ON KDFMetadata
WHEN (SELECT COUNT(*) FROM KDFMetadata) >= 1
\(begin)
SELECT RAISE(FAIL, 'Only one row allowed in KDFMetadata');
\(end);
"""
let expected = [
"""
CREATE TABLE KDFMetadata (
id INTEGER PRIMARY KEY,
value TEXT NOT NULL
)
""",
"""
CREATE TRIGGER KDFMetadataLimit
BEFORE INSERT ON KDFMetadata
WHEN (SELECT COUNT(*) FROM KDFMetadata) >= 1
\(begin)
SELECT RAISE(FAIL, 'Only one row allowed in KDFMetadata');
\(end)
"""
]
#expect(input.splitStatements() == expected)
}
@Test func testSplitWithSavepoints() {
let input = """
SAVEPOINT sp1;
INSERT INTO users (id, name) VALUES (1, 'Alice');
RELEASE SAVEPOINT sp1;
SAVEPOINT sp2;
UPDATE users SET name = 'Bob' WHERE id = 1;
ROLLBACK TO SAVEPOINT sp2;
RELEASE SAVEPOINT sp2;
"""
let expected = [
"SAVEPOINT sp1",
"INSERT INTO users (id, name) VALUES (1, 'Alice')",
"RELEASE SAVEPOINT sp1",
"SAVEPOINT sp2",
"UPDATE users SET name = 'Bob' WHERE id = 1",
"ROLLBACK TO SAVEPOINT sp2",
"RELEASE SAVEPOINT sp2"
]
#expect(input.splitStatements() == expected)
}
}

View File

@@ -0,0 +1,17 @@
import Testing
import Foundation
import DataLiteCore
struct StringTests {
@Test func testStringToSQLiteRawValue() {
#expect("Hello, SQLite!".sqliteRawValue == .text("Hello, SQLite!"))
}
@Test func testSQLiteRawValueToString() {
#expect(String(SQLiteRawValue.text("Hello, SQLite!")) == "Hello, SQLite!")
#expect(String(SQLiteRawValue.int(42)) == nil)
#expect(String(SQLiteRawValue.blob(Data([0x01, 0x02]))) == nil)
#expect(String(SQLiteRawValue.null) == nil)
}
}

View File

@@ -0,0 +1,20 @@
import Testing
import Foundation
import DataLiteCore
struct UUIDTests {
@Test func testUUIDToSQLiteRawValue() {
let uuid = UUID(uuidString: "123e4567-e89b-12d3-a456-426614174000")!
#expect(uuid.sqliteRawValue == .text("123E4567-E89B-12D3-A456-426614174000"))
}
@Test func testSQLiteRawValueToUUID() {
let raw = SQLiteRawValue.text("123e4567-e89b-12d3-a456-426614174000")
#expect(UUID(raw) == UUID(uuidString: "123e4567-e89b-12d3-a456-426614174000"))
#expect(UUID(.text("invalid-uuid-string")) == nil)
#expect(UUID(.int(42)) == nil)
#expect(UUID(.blob(Data([0x01, 0x02]))) == nil)
#expect(UUID(.null) == nil)
}
}