@@ -8,7 +8,8 @@ The database connection is necessary for today's enterprise development. WasmEdg
8
8
9
9
<!-- prettier-ignore -->
10
10
::: note
11
- Before we start, ensure [ you have Rust and WasmEdge installed] ( ../setup.md ) . If you are connecting to a remote MySQL database using TLS, you will need to [ install the TLS plugin] ( ../../../start/install.md#tls-plug-in ) for WasmEdge as well.
11
+ Before we start, [ you need to have Rust and WasmEdge installed] ( ../setup.md ) .
12
+ Make sure that you read the [ special notes on networking apps] ( ../setup#special-notes ) especially if you are compiling Rust programs on a Mac.
12
13
:::
13
14
14
15
## Run the example
@@ -20,28 +21,201 @@ git clone https://github.com/WasmEdge/wasmedge-db-examples
20
21
cd wasmedge-db-examples/mysql_async
21
22
22
23
# Compile the rust code into WASM
23
- cargo build --target wasm32-wasi --release
24
+ RUSTFLAGS= " --cfg wasmedge --cfg tokio_unstable " cargo build --target wasm32-wasi --release
24
25
25
26
# Execute MySQL statements against a MySQL database at mysql://user:passwd@127.0.0.1:3306
26
27
wasmedge --env " DATABASE_URL=mysql://user:passwd@127.0.0.1:3306/mysql" target/wasm32-wasi/release/crud.wasm
27
28
```
28
29
29
- To use TLS, you will need to turn on the ` default-rustls ` feature in ` Cargo.toml ` .
30
-
31
- ``` toml
32
- mysql_async_wasi = { version = " 0.31" , features = [ " default-rustls" ] }
33
- ```
30
+ <!-- prettier-ignore -->
31
+ ::: note
32
+ Since we have TLS enabled by default in this example, you will need the [ wasi-sdk version of clang] ( ../setup#tls-on-macos ) for compiling it on MacOS.
33
+ :::
34
34
35
+ To use TLS, you will need to turn on the ` default-rustls ` feature on the ` mysql_async ` crate in ` Cargo.toml ` .
35
36
Then, run the application as follows.
36
37
37
38
``` toml
38
39
# Execute MySQL statements against an AWS RDS database that requires TLS
39
40
wasmedge --env "DATABASE_SSL=1" --env "DATABASE_URL=mysql://user:passwd@mydb.123456789012.us-east-1.rds.amazonaws.com:3306/mysql" crud.wasm
40
41
```
41
42
42
- ## Code explanation
43
+ ## Configuration
44
+
45
+ In order to compile the ` mysql_async ` and ` tokio ` crates, we will need to apply two patches to add
46
+ WasmEdge-specific socket APIs to those crates. The following example shows that the TLS connection is enabled.
47
+
48
+ ```
49
+ [patch.crates-io]
50
+ tokio = { git = "https://github.com/second-state/wasi_tokio.git", branch = "v1.36.x" }
51
+ socket2 = { git = "https://github.com/second-state/socket2.git", branch = "v0.5.x" }
52
+
53
+ [dependencies]
54
+ mysql_async = { version = "0.34", default-features=false, features = [ "default-rustls" ], git="https://github.com/blackbeam/mysql_async.git" }
55
+ zstd-sys = "=2.0.9"
56
+ tokio = { version = "1", features = [ "io-util", "fs", "net", "time", "rt", "macros"] }
57
+ ```
58
+
59
+ ## Code example
60
+
61
+ The following code shows how to connect to a MySQL database server, and then insert, update, and delete records using SQL
62
+ statements.
63
+
64
+ Connect to a MySQL database.
65
+
66
+ ```
67
+ // Below we create a customized connection pool
68
+ let opts = Opts::from_url(&*get_url()).unwrap();
69
+ let mut builder = OptsBuilder::from_opts(opts);
70
+ if std::env::var("DATABASE_SSL").is_ok() {
71
+ builder = builder.ssl_opts(SslOpts::default());
72
+ }
73
+ // The connection pool will have a min of 5 and max of 10 connections.
74
+ let constraints = PoolConstraints::new(5, 10).unwrap();
75
+ let pool_opts = PoolOpts::default().with_constraints(constraints);
76
+
77
+ let pool = Pool::new(builder.pool_opts(pool_opts));
78
+ let mut conn = pool.get_conn().await.unwrap();
79
+ ```
80
+
81
+ Create a table on the connected database.
82
+
83
+ ```
84
+ // create table if no tables exist
85
+ let result = r"SHOW TABLES LIKE 'orders';"
86
+ .with(())
87
+ .map(&mut conn, |s: String| String::from(s))
88
+ .await?;
89
+
90
+ if result.len() == 0 {
91
+ // table doesn't exist, create a new one
92
+ r"CREATE TABLE orders (order_id INT, production_id INT, quantity INT, amount FLOAT, shipping FLOAT, tax FLOAT, shipping_address VARCHAR(20));".ignore(&mut conn).await?;
93
+ println!("create new table");
94
+ } else {
95
+ // delete all data from the table.
96
+ println!("delete all from orders");
97
+ r"DELETE FROM orders;".ignore(&mut conn).await?;
98
+ }
99
+ ```
100
+
101
+ Insert some records into the MySQL database using SQL.
102
+
103
+ ```
104
+ let orders = vec![
105
+ Order::new(1, 12, 2, 56.0, 15.0, 2.0, String::from("Mataderos 2312")),
106
+ Order::new(2, 15, 3, 256.0, 30.0, 16.0, String::from("1234 NW Bobcat")),
107
+ Order::new(3, 11, 5, 536.0, 50.0, 24.0, String::from("20 Havelock")),
108
+ Order::new(4, 8, 8, 126.0, 20.0, 12.0, String::from("224 Pandan Loop")),
109
+ Order::new(5, 24, 1, 46.0, 10.0, 2.0, String::from("No.10 Jalan Besar")),
110
+ ];
111
+
112
+ r"INSERT INTO orders (order_id, production_id, quantity, amount, shipping, tax, shipping_address)
113
+ VALUES (:order_id, :production_id, :quantity, :amount, :shipping, :tax, :shipping_address)"
114
+ .with(orders.iter().map(|order| {
115
+ params! {
116
+ "order_id" => order.order_id,
117
+ "production_id" => order.production_id,
118
+ "quantity" => order.quantity,
119
+ "amount" => order.amount,
120
+ "shipping" => order.shipping,
121
+ "tax" => order.tax,
122
+ "shipping_address" => &order.shipping_address,
123
+ }
124
+ }))
125
+ .batch(&mut conn)
126
+ .await?;
127
+ ```
128
+
129
+ Query the database.
130
+
131
+ ```
132
+ // query data
133
+ let loaded_orders = "SELECT * FROM orders"
134
+ .with(())
135
+ .map(
136
+ &mut conn,
137
+ |(order_id, production_id, quantity, amount, shipping, tax, shipping_address)| {
138
+ Order::new(
139
+ order_id,
140
+ production_id,
141
+ quantity,
142
+ amount,
143
+ shipping,
144
+ tax,
145
+ shipping_address,
146
+ )
147
+ },
148
+ )
149
+ .await?;
150
+ dbg!(loaded_orders.len());
151
+ dbg!(loaded_orders);
152
+ ```
153
+
154
+ Delete some records from the database.
155
+
156
+ ```
157
+ // // delete some data
158
+ r"DELETE FROM orders WHERE order_id=4;"
159
+ .ignore(&mut conn)
160
+ .await?;
161
+
162
+ // query data
163
+ let loaded_orders = "SELECT * FROM orders"
164
+ .with(())
165
+ .map(
166
+ &mut conn,
167
+ |(order_id, production_id, quantity, amount, shipping, tax, shipping_address)| {
168
+ Order::new(
169
+ order_id,
170
+ production_id,
171
+ quantity,
172
+ amount,
173
+ shipping,
174
+ tax,
175
+ shipping_address,
176
+ )
177
+ },
178
+ )
179
+ .await?;
180
+ dbg!(loaded_orders.len());
181
+ dbg!(loaded_orders);
182
+ ```
183
+
184
+ Update records in the MySQL database.
185
+
186
+ ```
187
+ // // update some data
188
+ r"UPDATE orders
189
+ SET shipping_address = '8366 Elizabeth St.'
190
+ WHERE order_id = 2;"
191
+ .ignore(&mut conn)
192
+ .await?;
193
+ // query data
194
+ let loaded_orders = "SELECT * FROM orders"
195
+ .with(())
196
+ .map(
197
+ &mut conn,
198
+ |(order_id, production_id, quantity, amount, shipping, tax, shipping_address)| {
199
+ Order::new(
200
+ order_id,
201
+ production_id,
202
+ quantity,
203
+ amount,
204
+ shipping,
205
+ tax,
206
+ shipping_address,
207
+ )
208
+ },
209
+ )
210
+ .await?;
211
+ dbg!(loaded_orders.len());
212
+ dbg!(loaded_orders);
213
+ ```
214
+
215
+ Close the database connection.
216
+
217
+ ```
218
+ drop(conn);
219
+ pool.disconnect().await.unwrap();
220
+ ```
43
221
44
- <!-- prettier-ignore -->
45
- ::: info
46
- Work in Progress
47
- :::
0 commit comments