{"id":13468267,"url":"https://github.com/vapor/mysql-nio","last_synced_at":"2025-09-14T22:16:24.291Z","repository":{"id":40351225,"uuid":"171034222","full_name":"vapor/mysql-nio","owner":"vapor","description":"🐬 Non-blocking, event-driven Swift client for MySQL.","archived":false,"fork":false,"pushed_at":"2025-08-28T14:29:30.000Z","size":376,"stargazers_count":99,"open_issues_count":19,"forks_count":28,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-08-28T18:26:28.436Z","etag":null,"topics":["mysql","non-blocking","server-side-swift","swift","swiftnio","vapor"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vapor.png","metadata":{"funding":{"github":["vapor"],"open_collective":"vapor"},"files":{"readme":"README.md","changelog":null,"contributing":".github/contributing.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-16T17:59:54.000Z","updated_at":"2025-08-28T14:29:28.000Z","dependencies_parsed_at":"2024-04-19T05:33:11.179Z","dependency_job_id":"4cf58d06-9723-4d1a-8a06-c75f5667bb06","html_url":"https://github.com/vapor/mysql-nio","commit_stats":{"total_commits":90,"total_committers":16,"mean_commits":5.625,"dds":0.5444444444444445,"last_synced_commit":"5180069eb857ed775cb254face751414ff77128e"},"previous_names":[],"tags_count":39,"template":false,"template_full_name":null,"purl":"pkg:github/vapor/mysql-nio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fmysql-nio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fmysql-nio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fmysql-nio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fmysql-nio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vapor","download_url":"https://codeload.github.com/vapor/mysql-nio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vapor%2Fmysql-nio/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275176407,"owners_count":25418438,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-14T02:00:10.474Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mysql","non-blocking","server-side-swift","swift","swiftnio","vapor"],"created_at":"2024-07-31T15:01:07.889Z","updated_at":"2025-09-14T22:16:24.281Z","avatar_url":"https://github.com/vapor.png","language":"Swift","funding_links":["https://github.com/sponsors/vapor","https://opencollective.com/vapor"],"categories":["Swift"],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://design.vapor.codes/images/vapor-mysqlnio.svg\" height=\"96\" alt=\"MySQLNIO\"\u003e\n\u003cbr\u003e\n\u003cbr\u003e\n\u003ca href=\"https://docs.vapor.codes/4.0/\"\u003e\u003cimg src=\"https://design.vapor.codes/images/readthedocs.svg\" alt=\"Documentation\"\u003e\u003c/a\u003e\n\u003ca href=\"https://discord.gg/vapor\"\u003e\u003cimg src=\"https://design.vapor.codes/images/discordchat.svg\" alt=\"Team Chat\"\u003e\u003c/a\u003e\n\u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://design.vapor.codes/images/mitlicense.svg\" alt=\"MIT License\"\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/vapor/mysql-nio/actions/workflows/test.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/vapor/mysql-nio/test.yml?event=push\u0026style=plastic\u0026logo=github\u0026label=test\u0026logoColor=%23ccc\" alt=\"Continuous Integration\"\u003e\u003c/a\u003e\n\u003ca href=\"https://codecov.io/github/vapor/mysql-nio\"\u003e\u003cimg src=\"https://img.shields.io/codecov/c/github/vapor/mysql-nio?style=plastic\u0026logo=codecov\u0026label=Codecov\"\u003e\u003c/a\u003e\n\u003ca href=\"https://swift.org\"\u003e\u003cimg src=\"https://design.vapor.codes/images/swift510up.svg\" alt=\"Swift 5.10+\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cbr\u003e\n\n🐬 Non-blocking, event-driven Swift client for MySQL built on [SwiftNIO](https://github.com/apple/swift-nio).\n\n## Using MySQLNIO\n\nUse standard SwiftPM syntax to include MySQLNIO as a dependency in your `Package.swift` file.\n\n```swift\n.package(url: \"https://github.com/vapor/mysql-nio.git\", from: \"1.0.0\")\n```\n\n### Supported Platforms\n\nMySQLNIO supports the following platforms:\n\n- Ubuntu 20.04+\n- macOS 10.15+\n- iOS 13+\n- tvOS 13+ and watchOS 7+ (experimental)\n\n## Overview\n\nMySQLNIO is a client package for connecting to, authorizing, and querying a MySQL server. At the heart of this module are NIO channel handlers for parsing and serializing messages in MySQL's proprietary wire protocol. These channel handlers are combined in a request / response style connection type that provides a convenient, client-like interface for performing queries. \n\nSupport for both simple (text) and parameterized (prepared statement) querying is provided out of the box alongside a `MySQLData` type that handles conversion between MySQL's wire format and native Swift types.\n\n### Motivation\n\nMost Swift implementations of MySQL clients are based on the [libmysqlclient](https://dev.mysql.com/doc/c-api/5.7/en/c-api-implementations.html) C library which handles transport internally. Building a library directly on top of MySQL's wire protocol using SwiftNIO should yield a more reliable, maintainable, and performant interface for MySQL databases.\n\n### Goals\n\nThis package is meant to be a low-level, unopinionated MySQL wire-protocol implementation for Swift. The hope is that higher level packages can share MySQLNIO as a foundation for interacting with MySQL servers without needing to duplicate complex logic.\n\nBecause of this, MySQLNIO excludes some important concepts for the sake of simplicity, such as:\n\n- Connection pooling\n- Swift `Codable` integration\n- Query building\n\nIf you are looking for a MySQL client package to use in your project, take a look at these higher-level packages built on top of MySQLNIO:\n\n- [`vapor/mysql-kit`](https://github.com/vapor/mysql-kit)\n\n### Dependencies\n\nThis package has four dependencies:\n\n- [`apple/swift-nio`](https://github.com/apple/swift-nio) for IO\n- [`apple/swift-nio-ssl`](https://github.com/apple/swift-nio-ssl) for TLS\n- [`apple/swift-log`](https://github.com/apple/swift-log) for logging\n- [`apple/swift-crypto`](https://github.com/apple/swift-crypto) for cryptography\n\nThis package has no additional system dependencies.\n\n## API Docs\n\nCheck out the [MySQLNIO API docs](https://api.vapor.codes/mysqlnio/documentation/mysqlnio/) for a detailed look at all of the classes, structs, protocols, and more.\n\n## Getting Started\n\nThis section will provide a quick look at using MySQLNIO.\n\n### Creating a Connection\n\nThe first step to making a query is creating a new `MySQLConnection`. The minimum requirements to create one are a `SocketAddress`, `EventLoop`, and credentials. \n\n```swift\nimport MySQLNIO\n\nlet eventLoop: any EventLoop = ...\nlet conn = try await MySQLConnection(\n    to: .makeAddressResolvingHost(\"my.mysql.server\", port: 3306),\n    username: \"test_username\",\n    database: \"test_database\",\n    password: \"test_password\",\n    on: eventLoop\n).get()\n```\n\nThere are a few ways to create a `SocketAddress`:\n\n- `init(ipAddress: String, port: Int)`\n- `init(unixDomainSocketPath: String)`\n- `makeAddressResolvingHost(_ host: String, port: Int)`\n\nThere are also some additional arguments you can supply to `connect`. \n\n- `tlsConfiguration` An optional `TLSConfiguration` struct. This will be used if the MySQL server supports TLS. Pass `nil` to opt-out of TLS.\n- `serverHostname` An optional `String` to use in conjunction with `tlsConfiguration` to specify the server's hostname. \n\n`connect` will return a `MySQLConnection`, or an error if it could not connect.\n\n### Database Protocol\n\nInteraction with a server revolves around the `MySQLDatabase` protocol. This protocol includes methods like `query(_:)` for executing SQL queries and reading the resulting rows. \n\n`MySQLConnection` is the default implementation of `MySQLDatabase` provided by this package. Assume the client here is the connection from the previous example.\n\n```swift\nimport MySQLNIO\n\nlet db: any MySQLDatabase = ...\n// now we can use client to do queries\n```\n\n### Simple Query\n\nSimple (text) queries allow you to execute a SQL string on the connected MySQL server. These queries do not support binding parameters, so any values sent must be escaped manually.\n\nThese queries are most useful for schema or transactional queries, or simple selects. Note that values returned by simple queries will be transferred in the less efficient text format. \n\n`simpleQuery` has two overloads, one that returns an array of rows, and one that accepts a closure for handling each row as it is returned.\n\n```swift\nlet rows = try await db.simpleQuery(\"SELECT @@version\").get()\nprint(rows) // [[\"@@version\": \"8.x.x\"]]\n\ntry await db.simpleQuery(\"SELECT @@version\") { row in\n    print(row) // [\"@@version\": \"8.x.x\"]\n}.get()\n```\n\n### Parameterized Query\n\nParameterized (prepared statement) queries allow you to execute a SQL string on the connected MySQL server. These queries support passing bound parameters as a separate argument. Each parameter is represented in the SQL string using placeholders (`?`). \n\nThese queries are most useful for selecting, inserting, and updating data. Data for these queries is transferred using the highly efficient binary format. \n\nJust like `simpleQuery`, `query` also offers two overloads. One that returns an array of rows, and one that accepts a closure for handling each row as it is returned.\n\n```swift\nlet rows = try await db.query(\"SELECT * FROM planets WHERE name = ?\", [\"Earth\"]).get()\nprint(rows) // [[\"id\": 42, \"name\": \"Earth\"]]\n\ntry await db.query(\"SELECT * FROM planets WHERE name = ?\", [\"Earth\"]) { row in\n    print(row) // [\"id\": 42, \"name\": \"Earth\"]\n}.get()\n```\n\n### Rows and Data\n\nBoth `simpleQuery` and `query` return the same `MySQLRow` type. Columns can be fetched from the row using the `column(_:table:)` method.\n\n```swift\nlet row: any MySQLRow = ...\nlet version = row.column(\"name\")\nprint(version) // MySQLData?\n```\n\n`MySQLRow` columns are stored as `MySQLData`. This struct contains the raw bytes returned by MySQL as well as some information for parsing them, such as:\n\n- MySQL data type\n- Wire format: binary or text\n- Value as array of bytes\n\n`MySQLData` has a variety of convenience methods for converting column data to usable Swift types.\n\n```swift\nlet data: MySQLData = ...\n\nprint(data.string) // String?\n\nprint(data.int) // Int?\nprint(data.int8) // Int8?\nprint(data.int16) // Int16?\nprint(data.int32) // Int32?\nprint(data.int64) // Int64?\n\nprint(data.uint) // UInt?\nprint(data.uint8) // UInt8?\nprint(data.uint16) // UInt16?\nprint(data.uint32) // UInt32?\nprint(data.uint64) // UInt64?\n\nprint(data.bool) // Bool?\n\ntry print(data.json(as: Foo.self)) // Foo?\n\nprint(data.float) // Float?\nprint(data.double) // Double?\n\nprint(data.date) // Date?\nprint(data.uuid) // UUID?\nprint(data.decimal) // Decimal?\n\nprint(data.time) // MySQLTime?\n```\n\n`MySQLData` is also used for sending data _to_ the server via parameterized values. To create `MySQLData` from a Swift type, use the available intializer methods. \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvapor%2Fmysql-nio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvapor%2Fmysql-nio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvapor%2Fmysql-nio/lists"}