rugged-mysql 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +22 -0
- data/LICENSE +22 -0
- data/README.md +40 -0
- data/Rakefile +8 -0
- data/ext/rugged/mysql/extconf.rb +24 -0
- data/ext/rugged/mysql/mysql_odb_backend.c +478 -0
- data/ext/rugged/mysql/mysql_refdb_backend.c +735 -0
- data/ext/rugged/mysql/rugged_mysql.c +13 -0
- data/ext/rugged/mysql/rugged_mysql.h +4 -0
- data/ext/rugged/mysql/rugged_mysql_backend.c +161 -0
- data/lib/rugged-mysql.rb +1 -0
- data/lib/rugged/mysql.rb +9 -0
- data/lib/rugged/mysql/version.rb +5 -0
- data/rugged-mysql.gemspec +28 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ce274abfec7be172fce34784845f6965c7d24abb
|
4
|
+
data.tar.gz: 0d23e7f09c4c85d512e1431273b2215fa517e5e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d6acfd623e6b3dfcee07240a44d9baeb8e4bd08a121e3d5803510c66559fe87ff4d4c7da0d402a46b710334b88b1e89283717314c48f790a1b35bbfdf29defe9
|
7
|
+
data.tar.gz: 65fb60e0dbfc890f0c9dbe4aa04582452e200b47d993963cda2c6b4555d5f81235b90b93a8a0d30ee8cfa03355917994b10e82331769ccea0e816b50cde93b93
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.4
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rugged-mysql (0.0.1)
|
5
|
+
rugged (~> 0.21.2)
|
6
|
+
|
7
|
+
GEM
|
8
|
+
remote: https://rubygems.org/
|
9
|
+
specs:
|
10
|
+
rake (10.3.2)
|
11
|
+
rake-compiler (0.9.3)
|
12
|
+
rake
|
13
|
+
rugged (0.21.2)
|
14
|
+
|
15
|
+
PLATFORMS
|
16
|
+
ruby
|
17
|
+
|
18
|
+
DEPENDENCIES
|
19
|
+
bundler (~> 1.7)
|
20
|
+
rake (~> 10.0)
|
21
|
+
rake-compiler
|
22
|
+
rugged-mysql!
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 重楼
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
rugged-mysql
|
2
|
+
============
|
3
|
+
|
4
|
+
Enables rugged to store git objects and references into MySQL.
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to you application's Gemfile:
|
11
|
+
|
12
|
+
gem 'rugged-mysql'
|
13
|
+
Or:
|
14
|
+
|
15
|
+
gem 'rugged-mysql', chonglou/rugged-mysql
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
bundle install
|
20
|
+
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
Create the backend:
|
25
|
+
|
26
|
+
require 'rugged-mysql'
|
27
|
+
mysql_backend = Rugged::MySql::Backend.new(host:'localhost', port:3306, username:'git', password:'tig', database:'git')
|
28
|
+
|
29
|
+
And pass it to rugged:
|
30
|
+
|
31
|
+
repo = Rugged::Repository.bare('repo-name', backend:mysql_backend)
|
32
|
+
|
33
|
+
Or
|
34
|
+
|
35
|
+
repo = Rugged::Repository.init_at('repo-name', :bare, backend:mysql_backend)
|
36
|
+
|
37
|
+
|
38
|
+
Each instance of the backend consumes a single MySql connection.
|
39
|
+
|
40
|
+
Enjoy it!
|
data/Rakefile
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
|
4
|
+
$CFLAGS << " #{ENV['CFLAGS']}"
|
5
|
+
$CFLAGS << ' -I/usr/include/mysql'
|
6
|
+
|
7
|
+
RUGGED_EXT_DIR = Gem::Specification.find_by_name('rugged').gem_dir
|
8
|
+
puts "Using rugged headers from #{RUGGED_EXT_DIR}\n"
|
9
|
+
$CFLAGS << " -I#{RUGGED_EXT_DIR}/ext/rugged"
|
10
|
+
$CFLAGS << " -I#{RUGGED_EXT_DIR}/vendor/libgit2/include"
|
11
|
+
$CFLAGS << " -I#{RUGGED_EXT_DIR}/vendor/libgit2/src"
|
12
|
+
|
13
|
+
$CFLAGS << ' -g'
|
14
|
+
$CFLAGS << ' -O3' unless $CFLAGS[/-O\d/]
|
15
|
+
$CFLAGS << ' -Wall -Wno-comment -Wno-sizeof-pointer-memaccess'
|
16
|
+
|
17
|
+
|
18
|
+
MAKE = find_executable('gmake') || find_executable('make')
|
19
|
+
unless MAKE
|
20
|
+
abort 'ERROR: GNU make is required to build Rugged.'
|
21
|
+
end
|
22
|
+
|
23
|
+
create_makefile('rugged/mysql/rugged-mysql')
|
24
|
+
|
@@ -0,0 +1,478 @@
|
|
1
|
+
/*
|
2
|
+
* source: https://github.com/libgit2/libgit2-backends/blob/master/mysql/mysql.c
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include <assert.h>
|
6
|
+
#include <string.h>
|
7
|
+
#include <git2.h>
|
8
|
+
#include <git2/sys/odb_backend.h>
|
9
|
+
#include <mysql.h>
|
10
|
+
|
11
|
+
#define GIT2_ODB_TABLE_NAME "git2_odb"
|
12
|
+
#define GIT2_STORAGE_ENGINE "InnoDB"
|
13
|
+
|
14
|
+
typedef struct {
|
15
|
+
git_odb_backend parent;
|
16
|
+
MYSQL *db;
|
17
|
+
MYSQL_STMT *st_read;
|
18
|
+
MYSQL_STMT *st_write;
|
19
|
+
MYSQL_STMT *st_read_header;
|
20
|
+
} mysql_odb_backend;
|
21
|
+
|
22
|
+
int
|
23
|
+
mysql_odb_backend__read_header(size_t * len_p, git_otype * type_p,
|
24
|
+
git_odb_backend * _backend, const git_oid * oid)
|
25
|
+
{
|
26
|
+
mysql_odb_backend *backend;
|
27
|
+
int error;
|
28
|
+
MYSQL_BIND bind_buffers[1];
|
29
|
+
MYSQL_BIND result_buffers[2];
|
30
|
+
|
31
|
+
assert(len_p && type_p && _backend && oid);
|
32
|
+
|
33
|
+
backend = (mysql_odb_backend *) _backend;
|
34
|
+
error = GIT_ERROR;
|
35
|
+
|
36
|
+
memset(bind_buffers, 0, sizeof(bind_buffers));
|
37
|
+
memset(result_buffers, 0, sizeof(result_buffers));
|
38
|
+
|
39
|
+
// bind the oid passed to the statement
|
40
|
+
bind_buffers[0].buffer = (void *)oid->id;
|
41
|
+
bind_buffers[0].buffer_length = 20;
|
42
|
+
bind_buffers[0].length = &bind_buffers[0].buffer_length;
|
43
|
+
bind_buffers[0].buffer_type = MYSQL_TYPE_BLOB;
|
44
|
+
if (mysql_stmt_bind_param(backend->st_read_header, bind_buffers) != 0) {
|
45
|
+
return 0;
|
46
|
+
}
|
47
|
+
// execute the statement
|
48
|
+
if (mysql_stmt_execute(backend->st_read_header) != 0) {
|
49
|
+
return 0;
|
50
|
+
}
|
51
|
+
if (mysql_stmt_store_result(backend->st_read_header) != 0) {
|
52
|
+
return 0;
|
53
|
+
}
|
54
|
+
// this should either be 0 or 1
|
55
|
+
// if it's > 1 MySQL's unique index failed and we should all fear for our lives
|
56
|
+
if (mysql_stmt_num_rows(backend->st_read_header) == 1) {
|
57
|
+
result_buffers[0].buffer_type = MYSQL_TYPE_TINY;
|
58
|
+
result_buffers[0].buffer = type_p;
|
59
|
+
result_buffers[0].buffer_length = sizeof(type_p);
|
60
|
+
memset(type_p, 0, sizeof(type_p));
|
61
|
+
|
62
|
+
result_buffers[1].buffer_type = MYSQL_TYPE_LONGLONG;
|
63
|
+
result_buffers[1].buffer = len_p;
|
64
|
+
result_buffers[1].buffer_length = sizeof(len_p);
|
65
|
+
memset(len_p, 0, sizeof(len_p));
|
66
|
+
|
67
|
+
if (mysql_stmt_bind_result
|
68
|
+
(backend->st_read_header, result_buffers) != 0) {
|
69
|
+
return GIT_ERROR;
|
70
|
+
}
|
71
|
+
// this should populate the buffers at *type_p and *len_p
|
72
|
+
if (mysql_stmt_fetch(backend->st_read_header) != 0) {
|
73
|
+
return GIT_ERROR;
|
74
|
+
}
|
75
|
+
|
76
|
+
error = GIT_OK;
|
77
|
+
} else {
|
78
|
+
error = GIT_ENOTFOUND;
|
79
|
+
}
|
80
|
+
|
81
|
+
// reset the statement for further use
|
82
|
+
if (mysql_stmt_reset(backend->st_read_header) != 0) {
|
83
|
+
return 0;
|
84
|
+
}
|
85
|
+
|
86
|
+
return error;
|
87
|
+
}
|
88
|
+
|
89
|
+
int
|
90
|
+
mysql_odb_backend__read(void **data_p, size_t * len_p, git_otype * type_p,
|
91
|
+
git_odb_backend * _backend, const git_oid * oid)
|
92
|
+
{
|
93
|
+
mysql_odb_backend *backend;
|
94
|
+
int error;
|
95
|
+
MYSQL_BIND bind_buffers[1];
|
96
|
+
MYSQL_BIND result_buffers[3];
|
97
|
+
unsigned long data_len;
|
98
|
+
|
99
|
+
assert(len_p && type_p && _backend && oid);
|
100
|
+
|
101
|
+
backend = (mysql_odb_backend *) _backend;
|
102
|
+
error = GIT_ERROR;
|
103
|
+
|
104
|
+
memset(bind_buffers, 0, sizeof(bind_buffers));
|
105
|
+
memset(result_buffers, 0, sizeof(result_buffers));
|
106
|
+
|
107
|
+
// bind the oid passed to the statement
|
108
|
+
bind_buffers[0].buffer = (void *)oid->id;
|
109
|
+
bind_buffers[0].buffer_length = 20;
|
110
|
+
bind_buffers[0].length = &bind_buffers[0].buffer_length;
|
111
|
+
bind_buffers[0].buffer_type = MYSQL_TYPE_BLOB;
|
112
|
+
if (mysql_stmt_bind_param(backend->st_read, bind_buffers) != 0) {
|
113
|
+
return 0;
|
114
|
+
}
|
115
|
+
// execute the statement
|
116
|
+
if (mysql_stmt_execute(backend->st_read) != 0) {
|
117
|
+
return 0;
|
118
|
+
}
|
119
|
+
|
120
|
+
if (mysql_stmt_store_result(backend->st_read) != 0) {
|
121
|
+
return 0;
|
122
|
+
}
|
123
|
+
// this should either be 0 or 1
|
124
|
+
// if it's > 1 MySQL's unique index failed and we should all fear for our lives
|
125
|
+
if (mysql_stmt_num_rows(backend->st_read) == 1) {
|
126
|
+
result_buffers[0].buffer_type = MYSQL_TYPE_TINY;
|
127
|
+
result_buffers[0].buffer = type_p;
|
128
|
+
result_buffers[0].buffer_length = sizeof(type_p);
|
129
|
+
memset(type_p, 0, sizeof(type_p));
|
130
|
+
|
131
|
+
result_buffers[1].buffer_type = MYSQL_TYPE_LONGLONG;
|
132
|
+
result_buffers[1].buffer = len_p;
|
133
|
+
result_buffers[1].buffer_length = sizeof(len_p);
|
134
|
+
memset(len_p, 0, sizeof(len_p));
|
135
|
+
|
136
|
+
// by setting buffer and buffer_length to 0, this tells libmysql
|
137
|
+
// we want it to set data_len to the *actual* length of that field
|
138
|
+
// this way we can malloc exactly as much memory as we need for the buffer
|
139
|
+
//
|
140
|
+
// come to think of it, we can probably just use the length set in *len_p
|
141
|
+
// once we fetch the result?
|
142
|
+
result_buffers[2].buffer_type = MYSQL_TYPE_LONG_BLOB;
|
143
|
+
result_buffers[2].buffer = 0;
|
144
|
+
result_buffers[2].buffer_length = 0;
|
145
|
+
result_buffers[2].length = &data_len;
|
146
|
+
|
147
|
+
if (mysql_stmt_bind_result(backend->st_read, result_buffers) !=
|
148
|
+
0) {
|
149
|
+
return GIT_ERROR;
|
150
|
+
}
|
151
|
+
// this should populate the buffers at *type_p, *len_p and &data_len
|
152
|
+
error = mysql_stmt_fetch(backend->st_read);
|
153
|
+
// if(error != 0 || error != MYSQL_DATA_TRUNCATED)
|
154
|
+
// return GIT_ERROR;
|
155
|
+
|
156
|
+
if (data_len > 0) {
|
157
|
+
*data_p = malloc(data_len);
|
158
|
+
result_buffers[2].buffer = *data_p;
|
159
|
+
result_buffers[2].buffer_length = data_len;
|
160
|
+
|
161
|
+
if (mysql_stmt_fetch_column
|
162
|
+
(backend->st_read, &result_buffers[2], 2, 0) != 0) {
|
163
|
+
return GIT_ERROR;
|
164
|
+
}
|
165
|
+
}
|
166
|
+
|
167
|
+
error = GIT_OK;
|
168
|
+
} else {
|
169
|
+
error = GIT_ENOTFOUND;
|
170
|
+
}
|
171
|
+
|
172
|
+
// reset the statement for further use
|
173
|
+
if (mysql_stmt_reset(backend->st_read) != 0) {
|
174
|
+
return 0;
|
175
|
+
}
|
176
|
+
|
177
|
+
return error;
|
178
|
+
}
|
179
|
+
|
180
|
+
int mysql_odb_backend__exists(git_odb_backend * _backend, const git_oid * oid)
|
181
|
+
{
|
182
|
+
mysql_odb_backend *backend;
|
183
|
+
int found;
|
184
|
+
MYSQL_BIND bind_buffers[1];
|
185
|
+
|
186
|
+
assert(_backend && oid);
|
187
|
+
|
188
|
+
backend = (mysql_odb_backend *) _backend;
|
189
|
+
found = 0;
|
190
|
+
|
191
|
+
memset(bind_buffers, 0, sizeof(bind_buffers));
|
192
|
+
|
193
|
+
// bind the oid passed to the statement
|
194
|
+
bind_buffers[0].buffer = (void *)oid->id;
|
195
|
+
bind_buffers[0].buffer_length = 20;
|
196
|
+
bind_buffers[0].length = &bind_buffers[0].buffer_length;
|
197
|
+
bind_buffers[0].buffer_type = MYSQL_TYPE_BLOB;
|
198
|
+
if (mysql_stmt_bind_param(backend->st_read_header, bind_buffers) != 0) {
|
199
|
+
return 0;
|
200
|
+
}
|
201
|
+
// execute the statement
|
202
|
+
if (mysql_stmt_execute(backend->st_read_header) != 0) {
|
203
|
+
return 0;
|
204
|
+
}
|
205
|
+
|
206
|
+
if (mysql_stmt_store_result(backend->st_read_header) != 0) {
|
207
|
+
return 0;
|
208
|
+
}
|
209
|
+
// now lets see if any rows matched our query
|
210
|
+
// this should either be 0 or 1
|
211
|
+
// if it's > 1 MySQL's unique index failed and we should all fear for our lives
|
212
|
+
if (mysql_stmt_num_rows(backend->st_read_header) == 1) {
|
213
|
+
found = 1;
|
214
|
+
}
|
215
|
+
// reset the statement for further use
|
216
|
+
if (mysql_stmt_reset(backend->st_read_header) != 0) {
|
217
|
+
return 0;
|
218
|
+
}
|
219
|
+
|
220
|
+
return found;
|
221
|
+
}
|
222
|
+
|
223
|
+
int
|
224
|
+
mysql_odb_backend__write(git_odb_backend * _backend, const git_oid * oid,
|
225
|
+
const void *data, size_t len, git_otype type)
|
226
|
+
{
|
227
|
+
int error;
|
228
|
+
mysql_odb_backend *backend;
|
229
|
+
MYSQL_BIND bind_buffers[4];
|
230
|
+
my_ulonglong affected_rows;
|
231
|
+
|
232
|
+
assert(oid && _backend && data);
|
233
|
+
|
234
|
+
backend = (mysql_odb_backend *) _backend;
|
235
|
+
|
236
|
+
if ((error = git_odb_hash(oid, data, len, type)) < 0) {
|
237
|
+
return error;
|
238
|
+
}
|
239
|
+
|
240
|
+
memset(bind_buffers, 0, sizeof(bind_buffers));
|
241
|
+
|
242
|
+
// bind the oid
|
243
|
+
bind_buffers[0].buffer = (void *)oid->id;
|
244
|
+
bind_buffers[0].buffer_length = 20;
|
245
|
+
bind_buffers[0].length = &bind_buffers[0].buffer_length;
|
246
|
+
bind_buffers[0].buffer_type = MYSQL_TYPE_BLOB;
|
247
|
+
|
248
|
+
// bind the type
|
249
|
+
bind_buffers[1].buffer = &type;
|
250
|
+
bind_buffers[1].buffer_type = MYSQL_TYPE_TINY;
|
251
|
+
|
252
|
+
// bind the size of the data
|
253
|
+
bind_buffers[2].buffer = &len;
|
254
|
+
bind_buffers[2].buffer_type = MYSQL_TYPE_LONG;
|
255
|
+
|
256
|
+
// bind the data
|
257
|
+
bind_buffers[3].buffer = (void *)data;
|
258
|
+
bind_buffers[3].buffer_length = len;
|
259
|
+
bind_buffers[3].length = &bind_buffers[3].buffer_length;
|
260
|
+
bind_buffers[3].buffer_type = MYSQL_TYPE_BLOB;
|
261
|
+
|
262
|
+
if (mysql_stmt_bind_param(backend->st_write, bind_buffers) != 0) {
|
263
|
+
return GIT_ERROR;
|
264
|
+
}
|
265
|
+
// TODO: use the streaming backend API so this actually makes sense to use :P
|
266
|
+
// once we want to use this we should comment out
|
267
|
+
// if (mysql_stmt_send_long_data(backend->st_write, 2, data, len) != 0)
|
268
|
+
// return GIT_ERROR;
|
269
|
+
|
270
|
+
// execute the statement
|
271
|
+
if (mysql_stmt_execute(backend->st_write) != 0) {
|
272
|
+
return GIT_ERROR;
|
273
|
+
}
|
274
|
+
// now lets see if the insert worked
|
275
|
+
affected_rows = mysql_stmt_affected_rows(backend->st_write);
|
276
|
+
if (affected_rows != 1) {
|
277
|
+
return GIT_ERROR;
|
278
|
+
}
|
279
|
+
// reset the statement for further use
|
280
|
+
if (mysql_stmt_reset(backend->st_read_header) != 0) {
|
281
|
+
return GIT_ERROR;
|
282
|
+
}
|
283
|
+
|
284
|
+
return GIT_OK;
|
285
|
+
}
|
286
|
+
|
287
|
+
void mysql_odb_backend__free(git_odb_backend * _backend)
|
288
|
+
{
|
289
|
+
mysql_odb_backend *backend;
|
290
|
+
assert(_backend);
|
291
|
+
backend = (mysql_odb_backend *) _backend;
|
292
|
+
|
293
|
+
if (backend->st_read) {
|
294
|
+
mysql_stmt_close(backend->st_read);
|
295
|
+
}
|
296
|
+
if (backend->st_read_header) {
|
297
|
+
mysql_stmt_close(backend->st_read_header);
|
298
|
+
}
|
299
|
+
if (backend->st_write) {
|
300
|
+
mysql_stmt_close(backend->st_write);
|
301
|
+
}
|
302
|
+
|
303
|
+
mysql_close(backend->db);
|
304
|
+
|
305
|
+
free(backend);
|
306
|
+
}
|
307
|
+
|
308
|
+
static int create_table(MYSQL * db)
|
309
|
+
{
|
310
|
+
static const char *sql_create =
|
311
|
+
"CREATE TABLE `" GIT2_ODB_TABLE_NAME "` ("
|
312
|
+
" `oid` binary(20) NOT NULL DEFAULT '',"
|
313
|
+
" `type` tinyint(1) unsigned NOT NULL,"
|
314
|
+
" `size` bigint(20) unsigned NOT NULL,"
|
315
|
+
" `data` longblob NOT NULL,"
|
316
|
+
" PRIMARY KEY (`oid`),"
|
317
|
+
" KEY `type` (`type`),"
|
318
|
+
" KEY `size` (`size`)"
|
319
|
+
") ENGINE=" GIT2_STORAGE_ENGINE
|
320
|
+
" DEFAULT CHARSET=utf8 COLLATE=utf8_bin;";
|
321
|
+
|
322
|
+
if (mysql_real_query(db, sql_create, strlen(sql_create)) != 0) {
|
323
|
+
return GIT_ERROR;
|
324
|
+
}
|
325
|
+
|
326
|
+
return GIT_OK;
|
327
|
+
}
|
328
|
+
|
329
|
+
static int init_db(MYSQL * db)
|
330
|
+
{
|
331
|
+
static const char *sql_check =
|
332
|
+
"SHOW TABLES LIKE '" GIT2_ODB_TABLE_NAME "';";
|
333
|
+
|
334
|
+
MYSQL_RES *res;
|
335
|
+
int error;
|
336
|
+
my_ulonglong num_rows;
|
337
|
+
|
338
|
+
if (mysql_real_query(db, sql_check, strlen(sql_check)) != 0)
|
339
|
+
return GIT_ERROR;
|
340
|
+
|
341
|
+
res = mysql_store_result(db);
|
342
|
+
if (res == NULL)
|
343
|
+
return GIT_ERROR;
|
344
|
+
|
345
|
+
num_rows = mysql_num_rows(res);
|
346
|
+
if (num_rows == 0) {
|
347
|
+
/* the table was not found */
|
348
|
+
error = create_table(db);
|
349
|
+
} else if (num_rows > 0) {
|
350
|
+
/* the table was found */
|
351
|
+
error = GIT_OK;
|
352
|
+
} else {
|
353
|
+
error = GIT_ERROR;
|
354
|
+
}
|
355
|
+
|
356
|
+
mysql_free_result(res);
|
357
|
+
return error;
|
358
|
+
}
|
359
|
+
|
360
|
+
static int init_statements(mysql_odb_backend * backend)
|
361
|
+
{
|
362
|
+
my_bool truth = 1;
|
363
|
+
|
364
|
+
static const char *sql_read =
|
365
|
+
"SELECT `type`, `size`, UNCOMPRESS(`data`) FROM `"
|
366
|
+
GIT2_ODB_TABLE_NAME "` WHERE `oid` = ?;";
|
367
|
+
|
368
|
+
static const char *sql_read_header =
|
369
|
+
"SELECT `type`, `size` FROM `" GIT2_ODB_TABLE_NAME
|
370
|
+
"` WHERE `oid` = ?;";
|
371
|
+
|
372
|
+
static const char *sql_write =
|
373
|
+
"INSERT IGNORE INTO `" GIT2_ODB_TABLE_NAME
|
374
|
+
"` VALUES (?, ?, ?, COMPRESS(?));";
|
375
|
+
|
376
|
+
backend->st_read = mysql_stmt_init(backend->db);
|
377
|
+
if (backend->st_read == NULL) {
|
378
|
+
return GIT_ERROR;
|
379
|
+
}
|
380
|
+
|
381
|
+
if (mysql_stmt_attr_set
|
382
|
+
(backend->st_read, STMT_ATTR_UPDATE_MAX_LENGTH, &truth) != 0) {
|
383
|
+
return GIT_ERROR;
|
384
|
+
}
|
385
|
+
|
386
|
+
if (mysql_stmt_prepare(backend->st_read, sql_read, strlen(sql_read)) !=
|
387
|
+
0) {
|
388
|
+
return GIT_ERROR;
|
389
|
+
}
|
390
|
+
|
391
|
+
backend->st_read_header = mysql_stmt_init(backend->db);
|
392
|
+
if (backend->st_read_header == NULL) {
|
393
|
+
return GIT_ERROR;
|
394
|
+
}
|
395
|
+
|
396
|
+
if (mysql_stmt_attr_set
|
397
|
+
(backend->st_read_header, STMT_ATTR_UPDATE_MAX_LENGTH, &truth) != 0)
|
398
|
+
{
|
399
|
+
return GIT_ERROR;
|
400
|
+
}
|
401
|
+
|
402
|
+
if (mysql_stmt_prepare
|
403
|
+
(backend->st_read_header, sql_read_header, strlen(sql_read)) != 0) {
|
404
|
+
return GIT_ERROR;
|
405
|
+
}
|
406
|
+
|
407
|
+
backend->st_write = mysql_stmt_init(backend->db);
|
408
|
+
if (backend->st_write == NULL) {
|
409
|
+
return GIT_ERROR;
|
410
|
+
}
|
411
|
+
|
412
|
+
if (mysql_stmt_attr_set
|
413
|
+
(backend->st_write, STMT_ATTR_UPDATE_MAX_LENGTH, &truth) != 0) {
|
414
|
+
return GIT_ERROR;
|
415
|
+
}
|
416
|
+
|
417
|
+
if (mysql_stmt_prepare(backend->st_write, sql_write, strlen(sql_read))
|
418
|
+
!= 0) {
|
419
|
+
return GIT_ERROR;
|
420
|
+
}
|
421
|
+
|
422
|
+
return GIT_OK;
|
423
|
+
}
|
424
|
+
|
425
|
+
int
|
426
|
+
git_odb_backend_mysql(git_odb_backend ** backend_out, const char *mysql_host,
|
427
|
+
unsigned int mysql_port,
|
428
|
+
const char *mysql_unix_socket,
|
429
|
+
const char *mysql_db,
|
430
|
+
const char *mysql_user, const char *mysql_passwd,
|
431
|
+
unsigned long mysql_client_flag)
|
432
|
+
{
|
433
|
+
mysql_odb_backend *backend;
|
434
|
+
int error;
|
435
|
+
my_bool reconnect;
|
436
|
+
|
437
|
+
backend = calloc(1, sizeof(mysql_odb_backend));
|
438
|
+
if (backend == NULL) {
|
439
|
+
return GITERR_NOMEMORY;
|
440
|
+
}
|
441
|
+
|
442
|
+
backend->db = mysql_init(backend->db);
|
443
|
+
|
444
|
+
reconnect = 1;
|
445
|
+
// allow libmysql to reconnect gracefully
|
446
|
+
if (mysql_options(backend->db, MYSQL_OPT_RECONNECT, &reconnect) != 0) {
|
447
|
+
goto cleanup;
|
448
|
+
}
|
449
|
+
// make the connection
|
450
|
+
if (mysql_real_connect
|
451
|
+
(backend->db, mysql_host, mysql_user, mysql_passwd, mysql_db,
|
452
|
+
mysql_port, mysql_unix_socket, mysql_client_flag) != backend->db) {
|
453
|
+
goto cleanup;
|
454
|
+
}
|
455
|
+
// check for and possibly create the database
|
456
|
+
error = init_db(backend->db);
|
457
|
+
if (error < 0) {
|
458
|
+
goto cleanup;
|
459
|
+
}
|
460
|
+
|
461
|
+
error = init_statements(backend);
|
462
|
+
if (error < 0) {
|
463
|
+
goto cleanup;
|
464
|
+
}
|
465
|
+
|
466
|
+
backend->parent.read = &mysql_odb_backend__read;
|
467
|
+
backend->parent.read_header = &mysql_odb_backend__read_header;
|
468
|
+
backend->parent.write = &mysql_odb_backend__write;
|
469
|
+
backend->parent.exists = &mysql_odb_backend__exists;
|
470
|
+
backend->parent.free = &mysql_odb_backend__free;
|
471
|
+
|
472
|
+
*backend_out = (git_odb_backend *) backend;
|
473
|
+
return GIT_OK;
|
474
|
+
|
475
|
+
cleanup:
|
476
|
+
mysql_odb_backend__free((git_odb_backend *) backend);
|
477
|
+
return GIT_ERROR;
|
478
|
+
}
|