|
1 |
| -MySQL.jl |
2 |
| -====== |
3 | 1 |
|
4 |
| -[](https://travis-ci.org/JuliaDB/MySQL.jl) |
| 2 | +# MySQL |
5 | 3 |
|
6 |
| -Julia bindings and helper functions for [MariaDB](https://mariadb.org/)/MySQL C library. |
| 4 | +*Package for interfacing with MySQL databases from Julia* |
7 | 5 |
|
8 |
| -# Installation |
| 6 | +| **PackageEvaluator** | **Build Status** | |
| 7 | +|:---------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------:| |
| 8 | +|[![][pkg-0.6-img]][pkg-0.6-url] | [![][travis-img]][travis-url] [![][codecov-img]][codecov-url] | |
9 | 9 |
|
10 |
| -Install [MySQL](http://dev.mysql.com/doc/refman/5.7/en/installing.html). |
11 | 10 |
|
12 |
| -Then in the julia prompt enter: |
| 11 | +## Installation |
| 12 | + |
| 13 | +The package is registered in `METADATA.jl` and so can be installed with `Pkg.add`. |
| 14 | + |
13 | 15 | ```julia
|
14 |
| -Pkg.add("MySQL") |
| 16 | +julia> Pkg.add("MySQL") |
15 | 17 | ```
|
16 | 18 |
|
17 |
| -# Examples |
| 19 | +## Project Status |
18 | 20 |
|
19 |
| -The following example connects to a database, creates a table, inserts values, |
20 |
| - retrieves the results and disconnects: |
| 21 | +The package is tested against the current Julia `0.6` release and nightly on Linux and OS X. |
21 | 22 |
|
22 |
| -```julia |
23 |
| -using MySQL |
24 |
| -con = mysql_connect("192.168.23.24", "username", "password", "db_name") |
25 |
| -command = """CREATE TABLE Employee |
26 |
| - ( |
27 |
| - ID INT NOT NULL AUTO_INCREMENT, |
28 |
| - Name VARCHAR(255), |
29 |
| - Salary FLOAT, |
30 |
| - JoinDate DATE, |
31 |
| - PRIMARY KEY (ID) |
32 |
| - );""" |
33 |
| -mysql_execute(con, command) |
34 |
| - |
35 |
| -# Insert some values |
36 |
| -mysql_execute(con, "INSERT INTO Employee (Name, Salary, JoinDate) values ('John', 25000.00, '2015-12-12'), ('Sam', 35000.00, '2012-8-17'), ('Tom', 50000.00, '2013-12-14');") |
37 |
| - |
38 |
| -# Get SELECT results |
39 |
| -command = "SELECT * FROM Employee;" |
40 |
| -dframe = mysql_execute(con, command) |
41 |
| - |
42 |
| -# Close connection |
43 |
| -mysql_disconnect(con) |
44 |
| -``` |
| 23 | +## Contributing and Questions |
45 | 24 |
|
46 |
| -## Getting the result set |
| 25 | +Contributions are very welcome, as are feature requests and suggestions. Please open an |
| 26 | +[issue][issues-url] if you encounter any problems or would just like to ask a question. |
47 | 27 |
|
48 |
| -By default, `mysql_execute` returns a DataFrame. To obtain each row as a tuple use `mysql_execute(con, command; opformat=MYSQL_TUPLES)`. The same can also be done with the `MySQLRowIterator`, example: |
49 | 28 |
|
50 |
| -```julia |
51 |
| -for row in MySQLRowIterator(con, command) |
52 |
| - # do stuff with row |
53 |
| -end |
54 |
| -``` |
| 29 | +<!-- [docs-latest-img]: https://img.shields.io/badge/docs-latest-blue.svg |
| 30 | +[docs-latest-url]: https://JuliaData.github.io/MySQL.jl/latest --> |
55 | 31 |
|
56 |
| -# Extended example: Prepared Statements |
| 32 | +[docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg |
| 33 | +[docs-stable-url]: https://JuliaData.github.io/MySQL.jl/stable |
57 | 34 |
|
58 |
| -Prepared statements are used to optimize queries. Queries that are run repeatedly can be |
59 |
| - prepared once and then executed many times. The query can take parameters, these are |
60 |
| - indicated by '?'s. Using the `mysql_stmt_bind_param` the values can be bound to the query. |
61 |
| - An Example: |
| 35 | +[travis-img]: https://travis-ci.org/JuliaData/MySQL.jl.svg?branch=master |
| 36 | +[travis-url]: https://travis-ci.org/JuliaData/MySQL.jl |
62 | 37 |
|
63 |
| -```julia |
64 |
| -mysql_stmt_prepare(conn, "INSERT INTO Employee (Name, Salary, JoinDate) values (?, ?, ?);") |
| 38 | +[codecov-img]: https://codecov.io/gh/JuliaData/MySQL.jl/branch/master/graph/badge.svg |
| 39 | +[codecov-url]: https://codecov.io/gh/JuliaData/MySQL.jl |
65 | 40 |
|
66 |
| -values = [("John", 10000.50, "2015-8-3"), |
67 |
| - ("Tom", 20000.25, "2015-8-4"), |
68 |
| - ("Jim", 30000.00, "2015-6-2")] |
| 41 | +[issues-url]: https://github.com/JuliaData/MySQL.jl/issues |
69 | 42 |
|
70 |
| -for val in values |
71 |
| - mysql_execute(conn, [MYSQL_TYPE_VARCHAR, MYSQL_TYPE_FLOAT, MYSQL_TYPE_DATE], val) |
72 |
| -end |
| 43 | +[pkg-0.6-img]: http://pkg.julialang.org/badges/MySQL_0.6.svg |
| 44 | +[pkg-0.6-url]: http://pkg.julialang.org/?pkg=MySQL |
73 | 45 |
|
74 |
| -mysql_stmt_prepare(conn, "SELECT * from Employee WHERE ID = ? AND Salary > ?") |
75 |
| -dframe = mysql_execute(conn, [MYSQL_TYPE_LONG, MYSQL_TYPE_FLOAT], [5, 35000.00]) |
| 46 | +## Documentation |
76 | 47 |
|
77 |
| -# To iterate over the result and get each row as a tuple |
78 |
| -for row in MySQLRowIterator(conn, [MYSQL_TYPE_LONG, MYSQL_TYPE_FLOAT], [5, 35000.00]) |
79 |
| - # do stuff with row |
80 |
| -end |
| 48 | +```julia |
| 49 | +MySQL.connect(host::String, user::String, passwd::String; db::String = "", port = "3306", socket::String = MySQL.API.MYSQL_DEFAULT_SOCKET, opts = Dict()) |
81 | 50 | ```
|
82 |
| - |
83 |
| -# Metadata |
| 51 | +Connect to a mysql database, returns a `MySQL.Connection` object to be passed to other API functions |
84 | 52 |
|
85 | 53 | ```julia
|
86 |
| -mysql_query(con, "SELECT * FROM some_table;") |
87 |
| -result = mysql_store_result(con) # result set can be used later to retrieve values. |
88 |
| -meta = mysql_metadata(result) |
89 |
| -for i in 1:meta.nfields |
90 |
| - println("Field name is: ", meta.names[i]) |
91 |
| - println("Field length is: ", meta.lens[i]) |
92 |
| - println("MySQL type is: ", meta.mtypes[i]) |
93 |
| - println("Julia type is: ", meta.jtypes[i]) |
94 |
| - println("Is nullable: ", meta.is_nullables[i]) |
95 |
| -end |
| 54 | +MySQL.disconnect(conn::MySQL.Connection) |
96 | 55 | ```
|
| 56 | +Disconnect a `MySQL.Connection` object from the remote database: |
97 | 57 |
|
98 |
| -The same function `mysql_metadata` can be called for prepared statements with the statement |
99 |
| - handle as the argument after preparing the query. |
| 58 | +```julia |
| 59 | +MYSQL.insertid(conn::Connection) |
| 60 | +``` |
| 61 | +Get the insert id of the most recently executed SQL statement: |
100 | 62 |
|
101 |
| -# Multi-Query |
| 63 | +```julia |
| 64 | +MySQL.escape(conn::MySQL.Connection, str::String) -> String |
| 65 | +``` |
| 66 | +Escape an SQL statement |
102 | 67 |
|
103 |
| -`mysql_execute` handles multi-query. It returns an array of DataFrames and integers. |
104 |
| - The DataFrames correspond to the SELECT queries and the integers respresent the number of |
105 |
| - affected rows corresponding to non-SELECT queries in the multi statement. |
| 68 | +```julia |
| 69 | +MySQL.execute!(conn, sql) => # of affected rows |
| 70 | +``` |
| 71 | +Execute an SQL statement without returning results (useful for DDL statements, update, delete, etc.) |
106 | 72 |
|
107 |
| -If `MYSQL_TUPLES` are passed as the last argument, then tuples will be returned instead |
108 |
| - of DataFrames. |
| 73 | +```julia |
| 74 | +MySQL.query(conn, sql, sink=Data.Table; append::Bool=false) => sink |
| 75 | +``` |
| 76 | +Execute an SQL statement and return the results in `sink`, which can be any valid `Data.Sink` (interface from DataStreams.jl). By default, a NamedTuple of Vectors are returned. |
109 | 77 |
|
110 |
| -# Error types |
| 78 | +Passing `append=true` as a keyword argument will cause the resultset to be _appended_ to the sink instead of replacing. |
111 | 79 |
|
112 |
| -* `MySQLInterfaceError`: This error is thrown for exceptions that occur in the MySQL julia interface, such as when calling functions with a null connection. |
113 |
| -* `MySQLInternalError`: This error is thrown for exceptions that occur in the underlying C library. |
114 |
| -* `MySQLStatementError`: This error is thrown for exceptions that occur in the underlying C library when using prepared statements. |
| 80 | +```julia |
| 81 | +MySQL.Query(conn, sql, sink=Data.Table; append::Bool=false) => MySQL.Query |
| 82 | +``` |
| 83 | +execute an sql statement and return a `MySQL.Query` object. Result rows can be iterated as NamedTuples via `Data.rows(query)` where `query` is the `MySQL.Query` object. Results can also be streamed to any valid `Data.Sink` via `Data.stream!(query, sink)`. |
115 | 84 |
|
116 |
| -# How to solve MySQL library not found error |
| 85 | +```julia |
| 86 | +MySQL.Stmt(conn, sql) => MySQL.Stmt |
| 87 | +``` |
| 88 | +Prepare an SQL statement that may contain `?` parameter placeholders. |
117 | 89 |
|
118 |
| -This error may occur during `using MySQL`. To resolve this- |
119 |
| -* **Ubuntu**: Just add the MariaDB/MySQL `.so` file to the `lib_choices` array in `src/config.jl` (the system file is at `~/.julia/v0.7/MySQL/src/config.jl`). If it is already there make sure `LD_LIBRARY_PATH` contains the MariaDB/MySQL `.so` file directory path. Usually this is something like `/usr/local/lib/mariadb/`. |
120 |
| -* **OSX**: Same as above. In this case the file will be something like `libmysqlclient.dylib`. Homebrew users should look in `/usr/local/Cellar/mysql`. |
121 |
| -* **Windows**: The file will be picked up automatically if MySQL is installed correctly. If you still get the error add the location of `libmysql.dll` to PATH. |
| 90 | +A `MySQL.Stmt` may then be executed by calling `MySQL.execute!(stmt, params)` where `params` are the values to be bound to the `?` placeholders in the original SQL statement. Params must be provided for every `?` and will be matched in the same order they appeared in the original SQL statement. |
122 | 91 |
|
123 |
| -# Tests |
| 92 | +Bulk statement execution can be accomplished by "streaming" a param source like: |
124 | 93 |
|
125 |
| -To run the tests you must have MySQL server running on the host. Set the constants HOST and ROOTPASS |
126 |
| -in `test/runtests.jl` to the host and root password on your test setup. Run the tests using: |
127 |
| -``` |
128 |
| -Pkg.test("MySQL") |
| 94 | +```julia |
| 95 | +Data.stream!(source, stmt) |
129 | 96 | ```
|
130 | 97 |
|
131 |
| -# Acknowledgement |
132 |
| - |
133 |
| -We acknowledge the contributions of [JustDial](http://www.justdial.com) towards this work. |
| 98 | +where `source` is any valid `Data.Source` (from DataStreams.jl). As with `MySQL.execute!`, the `source` must provide enough params and will be matched in the same order. |
0 commit comments