OHMySQL icon indicating copy to clipboard operation
OHMySQL copied to clipboard

Swift + MySQL = ❤️

OHMySQL

License License Documentation

The library supports Objective-C and Swift, iOS and macOS. You can connect to your remote MySQL database using OHMySQL API. It allows you doing queries in easy and object-oriented way. Common queries such as SELECT, INSERT, DELETE, JOIN are wrapped by Objective-C code and you don't need to dive into MySQL C API.

★★ Every star is appreciated! ★★

  • Goal
  • Support
  • Features
  • Requirements
  • How To Get Started
  • Installation
  • Usage
    • Query Context
    • Execute Query
    • SELECT
    • INSERT
    • UPDATE
    • DELETE
    • JOINs
    • Object Mapping
    • Set up SSL
  • Communication
  • License

Goal

If you are interested in and want to know how it can be applied in your project too.

Support

I wish to support the library and extend API and functionality. If you donate me some money 💵, it keeps me motivated and happy 🙂 You may support me via PayPal or let me know any other method convenient for you.

Features

  • [x] Easy to integrate and use
  • [x] Many functionality features
  • [x] Requires minimal knowledge in SQL
  • [x] Supports iOS and macOS
  • [x] Clean code with unit tests
  • [x] Complete documentation and support

Requirements

  • iOS 14.0+ / macOS 11.0+ (for more previous versions use 2.1.3)
  • Xcode 12.0+

How To Get Started

Installation

You can use CocoaPods. Add the following line to your Podfile:

pod 'OHMySQL' --repo-update

If you are using Swift do not forget to add use_frameworks! at the top of Podfile. Add platform, example platform :osx, '11.0'.

Usage

Connect to the database.

let user = MySQLConfiguration(userName: "root", password: "root", serverName: "localhost", dbName: "dbname", port: 3306, socket: "/mysql/mysql.sock")
let coordinator = MySQLStoreCoordinator(user: user!)
coordinator.encoding = .UTF8MB4
coordinator.connect()
OHMySQLConfiguration *config = [[OHMySQLConfiguration alloc] initWithUserName:@"root"
                                                                     password:@"root"
                                                                   serverName:@"localhost"
                                                                       dbName:@"dbname"
                                                                         port:3306
                                                                       socket:@"/mysql/mysql.sock"];
OHMySQLStoreCoordinator *coordinator = [[OHMySQLStoreCoordinator alloc] initWithUser:config];
[coordinator connect];

To end a connection:

coordinator.disconnect()
[coordinator disconnect];

Query Context

To execute a query you have to create the context:

let context = MySQLQueryContext()
context.storeCoordinator = coordinator
OHMySQLQueryContext *queryContext = [OHMySQLQueryContext new];
queryContext.storeCoordinator = coordinator;

You will use this context to execute queries or manipulate the objects.

Execute Query

let dropQueryString = "DROP TABLE `MyTable`"
let dropQueryRequest = MySQLQueryRequest(queryString: dropQueryString)
try? self.mainQueryContext.execute(dropQueryRequest)
NSString *dropQueryString = @"DROP TABLE `MyTable`";
OHMySQLQueryRequest *dropQueryRequest = [[OHMySQLQueryRequest alloc] initWithQueryString:dropQueryString];
    
NSError *error;
[self.mainQueryContext executeQueryRequest:dropQueryRequest error:&error];

SELECT

The response contains array of dictionaries (like JSON).

let query = MySQLQueryRequestFactory.select("tasks", condition: nil)
let response = try? MySQLContainer.shared.mainQueryContext?.executeQueryRequestAndFetchResult(query)
OHMySQLQueryRequest *query = [OHMySQLQueryRequestFactory SELECT:@"tasks" condition:nil];
NSError *error = nil;
NSArray *tasks = [queryContext executeQueryRequestAndFetchResult:query error:&error];

You will get a response like this:

[{ @"id": @1, @"name": @"Task name", @"description": @"Task description", @"status": [NSNull null] }]

INSERT

let query = MySQLQueryRequestFactory.insert("tasks", set: ["name": "Something", "desctiption": "new task"])
try? mainQueryContext?.execute(query)
OHMySQLQueryRequest *query = [OHMySQLQueryRequestFactory INSERT:@"tasks" set:@{ @"name": @"Something", @"desctiption": @"new task" }];
NSError error;
[queryContext executeQueryRequest:query error:&error];

UPDATE

let query = MySQLQueryRequestFactory.update("tasks", set: ["name": "Something"], condition: "id=7")
try? mainQueryContext?.execute(query)
OHMySQLQueryRequest *query = [OHMySQLQueryRequestFactory UPDATE:@"tasks" set:@{ @"name": @"Something", @"description": @"new task update" } condition:@"id=5"];
NSError error;
[queryContext executeQueryRequest:query error:&error];

DELETE

let query = MySQLQueryRequestFactory.delete("tasks", condition: "id=10")
try? mainQueryContext?.execute(query)
OHMySQLQueryRequest *query = [OHMySQLQueryRequestFactory DELETE:@"tasks" condition:@"id=10"];
NSError error;
[queryContext executeQueryRequest:query error:&error];

JOINs

The response contains array of dictionaries (like JSON). You can do 4 types of joins (INNER, RIGHT, LEFT, FULL) using string constants.

let query = MySQLQueryRequestFactory.joinType(OHJoinInner, fromTable: "tasks", columnNames: ["id", "name", "description"], joinOn: ["subtasks": "tasks.id=subtasks.parentId"])
let result = try? mainQueryContext?.executeQueryRequestAndFetchResult(query)
OHMySQLQueryRequest *query = [OHMySQLQueryRequestFactory JOINType:OHJoinInner					
                                                        fromTable:@"tasks" 
                                                      columnNames:@[@"id", @"name", @"description"] 
                                                           joinOn:@{ @"subtasks":@"tasks.id=subtasks.parentId" }];
NSArray *results = [queryContext executeQueryRequestAndFetchResult:query error:nil];

Object Mapping

You have to implement the protocol OHMappingProtocol for your models. Insertion looks like the following (in this example the NSManagedObject instance). The library has only a primary logic for mapping, so I would recommend you writing a mapping logic by yourself. If you are using Swift you cannot use fundamental number types (Int, Double), only NSNumber (due to run-time).

mainQueryContext?.insertObject(task)
try? mainQueryContext?.save()
[queryContext insertObject:task];
BOOL result = [queryContext save:nil];

You can update/delete the objects easily.

let task = Task()
task.name = "sample"
mainQueryContext?.updateObject(task)
mainQueryContext?.deleteObject(task)

try? mainQueryContext?.save()
// You don't need to specify primary index here.  It'll be updated automatically.
OHTask *task = [OHTask new];
task.name = @"Code cleanup";
task.taskDescription = @"Delete unused classes and files";
task.status = 0;
[queryContext updateObject:task];
...
task.name = @"Something";
task.status = 1;
[task update];
...
[queryContext deleteObject:task];
BOOL result = [queryContext save:nil];

Communication

License

OHMySQL is released under the MIT license. See LICENSE for details.