trilogy_w_prepared_statements 2.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +80 -0
- data/Rakefile +22 -0
- data/ext/trilogy-ruby/cast.c +277 -0
- data/ext/trilogy-ruby/cext.c +1048 -0
- data/ext/trilogy-ruby/extconf.rb +17 -0
- data/ext/trilogy-ruby/inc/trilogy/blocking.h +281 -0
- data/ext/trilogy-ruby/inc/trilogy/buffer.h +64 -0
- data/ext/trilogy-ruby/inc/trilogy/builder.h +165 -0
- data/ext/trilogy-ruby/inc/trilogy/charset.h +277 -0
- data/ext/trilogy-ruby/inc/trilogy/client.h +760 -0
- data/ext/trilogy-ruby/inc/trilogy/error.h +44 -0
- data/ext/trilogy-ruby/inc/trilogy/packet_parser.h +34 -0
- data/ext/trilogy-ruby/inc/trilogy/protocol.h +1014 -0
- data/ext/trilogy-ruby/inc/trilogy/reader.h +216 -0
- data/ext/trilogy-ruby/inc/trilogy/socket.h +111 -0
- data/ext/trilogy-ruby/inc/trilogy/vendor/curl_hostcheck.h +29 -0
- data/ext/trilogy-ruby/inc/trilogy/vendor/openssl_hostname_validation.h +51 -0
- data/ext/trilogy-ruby/inc/trilogy.h +8 -0
- data/ext/trilogy-ruby/src/blocking.c +358 -0
- data/ext/trilogy-ruby/src/buffer.c +60 -0
- data/ext/trilogy-ruby/src/builder.c +236 -0
- data/ext/trilogy-ruby/src/charset.c +212 -0
- data/ext/trilogy-ruby/src/client.c +903 -0
- data/ext/trilogy-ruby/src/error.c +17 -0
- data/ext/trilogy-ruby/src/packet_parser.c +140 -0
- data/ext/trilogy-ruby/src/protocol.c +1175 -0
- data/ext/trilogy-ruby/src/reader.c +282 -0
- data/ext/trilogy-ruby/src/socket.c +623 -0
- data/ext/trilogy-ruby/src/vendor/curl_hostcheck.c +206 -0
- data/ext/trilogy-ruby/src/vendor/openssl_hostname_validation.c +175 -0
- data/ext/trilogy-ruby/trilogy-ruby.h +37 -0
- data/lib/trilogy/version.rb +3 -0
- data/lib/trilogy.rb +61 -0
- data/trilogy.gemspec +27 -0
- metadata +107 -0
@@ -0,0 +1,206 @@
|
|
1
|
+
/***************************************************************************
|
2
|
+
* _ _ ____ _
|
3
|
+
* Project ___| | | | _ \| |
|
4
|
+
* / __| | | | |_) | |
|
5
|
+
* | (__| |_| | _ <| |___
|
6
|
+
* \___|\___/|_| \_\_____|
|
7
|
+
*
|
8
|
+
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
9
|
+
*
|
10
|
+
* This software is licensed as described in the file COPYING, which
|
11
|
+
* you should have received as part of this distribution. The terms
|
12
|
+
* are also available at http://curl.haxx.se/docs/copyright.html.
|
13
|
+
*
|
14
|
+
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
15
|
+
* copies of the Software, and permit persons to whom the Software is
|
16
|
+
* furnished to do so, under the terms of the COPYING file.
|
17
|
+
*
|
18
|
+
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
19
|
+
* KIND, either express or implied.
|
20
|
+
*
|
21
|
+
***************************************************************************/
|
22
|
+
|
23
|
+
/* This file is an amalgamation of hostcheck.c and most of rawstr.c
|
24
|
+
from cURL. The contents of the COPYING file mentioned above are:
|
25
|
+
COPYRIGHT AND PERMISSION NOTICE
|
26
|
+
Copyright (c) 1996 - 2013, Daniel Stenberg, <daniel@haxx.se>.
|
27
|
+
All rights reserved.
|
28
|
+
Permission to use, copy, modify, and distribute this software for any purpose
|
29
|
+
with or without fee is hereby granted, provided that the above copyright
|
30
|
+
notice and this permission notice appear in all copies.
|
31
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
32
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
33
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
|
34
|
+
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
35
|
+
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
36
|
+
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
37
|
+
OR OTHER DEALINGS IN THE SOFTWARE.
|
38
|
+
Except as contained in this notice, the name of a copyright holder shall not
|
39
|
+
be used in advertising or otherwise to promote the sale, use or other dealings
|
40
|
+
in this Software without prior written authorization of the copyright holder.
|
41
|
+
*/
|
42
|
+
|
43
|
+
#include "trilogy/vendor/curl_hostcheck.h"
|
44
|
+
#include <string.h>
|
45
|
+
|
46
|
+
/* Portable, consistent toupper (remember EBCDIC). Do not use toupper() because
|
47
|
+
its behavior is altered by the current locale. */
|
48
|
+
static char Curl_raw_toupper(char in)
|
49
|
+
{
|
50
|
+
switch (in) {
|
51
|
+
case 'a':
|
52
|
+
return 'A';
|
53
|
+
case 'b':
|
54
|
+
return 'B';
|
55
|
+
case 'c':
|
56
|
+
return 'C';
|
57
|
+
case 'd':
|
58
|
+
return 'D';
|
59
|
+
case 'e':
|
60
|
+
return 'E';
|
61
|
+
case 'f':
|
62
|
+
return 'F';
|
63
|
+
case 'g':
|
64
|
+
return 'G';
|
65
|
+
case 'h':
|
66
|
+
return 'H';
|
67
|
+
case 'i':
|
68
|
+
return 'I';
|
69
|
+
case 'j':
|
70
|
+
return 'J';
|
71
|
+
case 'k':
|
72
|
+
return 'K';
|
73
|
+
case 'l':
|
74
|
+
return 'L';
|
75
|
+
case 'm':
|
76
|
+
return 'M';
|
77
|
+
case 'n':
|
78
|
+
return 'N';
|
79
|
+
case 'o':
|
80
|
+
return 'O';
|
81
|
+
case 'p':
|
82
|
+
return 'P';
|
83
|
+
case 'q':
|
84
|
+
return 'Q';
|
85
|
+
case 'r':
|
86
|
+
return 'R';
|
87
|
+
case 's':
|
88
|
+
return 'S';
|
89
|
+
case 't':
|
90
|
+
return 'T';
|
91
|
+
case 'u':
|
92
|
+
return 'U';
|
93
|
+
case 'v':
|
94
|
+
return 'V';
|
95
|
+
case 'w':
|
96
|
+
return 'W';
|
97
|
+
case 'x':
|
98
|
+
return 'X';
|
99
|
+
case 'y':
|
100
|
+
return 'Y';
|
101
|
+
case 'z':
|
102
|
+
return 'Z';
|
103
|
+
}
|
104
|
+
return in;
|
105
|
+
}
|
106
|
+
|
107
|
+
/*
|
108
|
+
* Curl_raw_equal() is for doing "raw" case insensitive strings. This is meant
|
109
|
+
* to be locale independent and only compare strings we know are safe for
|
110
|
+
* this. See http://daniel.haxx.se/blog/2008/10/15/strcasecmp-in-turkish/ for
|
111
|
+
* some further explanation to why this function is necessary.
|
112
|
+
*
|
113
|
+
* The function is capable of comparing a-z case insensitively even for
|
114
|
+
* non-ascii.
|
115
|
+
*/
|
116
|
+
|
117
|
+
static int Curl_raw_equal(const char *first, const char *second)
|
118
|
+
{
|
119
|
+
while (*first && *second) {
|
120
|
+
if (Curl_raw_toupper(*first) != Curl_raw_toupper(*second))
|
121
|
+
/* get out of the loop as soon as they don't match */
|
122
|
+
break;
|
123
|
+
first++;
|
124
|
+
second++;
|
125
|
+
}
|
126
|
+
/* we do the comparison here (possibly again), just to make sure that if the
|
127
|
+
loop above is skipped because one of the strings reached zero, we must
|
128
|
+
not return this as a successful match */
|
129
|
+
return (Curl_raw_toupper(*first) == Curl_raw_toupper(*second));
|
130
|
+
}
|
131
|
+
|
132
|
+
static int Curl_raw_nequal(const char *first, const char *second, size_t max)
|
133
|
+
{
|
134
|
+
while (*first && *second && max) {
|
135
|
+
if (Curl_raw_toupper(*first) != Curl_raw_toupper(*second)) {
|
136
|
+
break;
|
137
|
+
}
|
138
|
+
max--;
|
139
|
+
first++;
|
140
|
+
second++;
|
141
|
+
}
|
142
|
+
if (0 == max)
|
143
|
+
return 1; /* they are equal this far */
|
144
|
+
|
145
|
+
return Curl_raw_toupper(*first) == Curl_raw_toupper(*second);
|
146
|
+
}
|
147
|
+
|
148
|
+
/*
|
149
|
+
* Match a hostname against a wildcard pattern.
|
150
|
+
* E.g.
|
151
|
+
* "foo.host.com" matches "*.host.com".
|
152
|
+
*
|
153
|
+
* We use the matching rule described in RFC6125, section 6.4.3.
|
154
|
+
* http://tools.ietf.org/html/rfc6125#section-6.4.3
|
155
|
+
*/
|
156
|
+
|
157
|
+
static int hostmatch(const char *hostname, const char *pattern)
|
158
|
+
{
|
159
|
+
const char *pattern_label_end, *pattern_wildcard, *hostname_label_end;
|
160
|
+
int wildcard_enabled;
|
161
|
+
size_t prefixlen, suffixlen;
|
162
|
+
pattern_wildcard = strchr(pattern, '*');
|
163
|
+
if (pattern_wildcard == NULL)
|
164
|
+
return Curl_raw_equal(pattern, hostname) ? CURL_HOST_MATCH : CURL_HOST_NOMATCH;
|
165
|
+
|
166
|
+
/* We require at least 2 dots in pattern to avoid too wide wildcard
|
167
|
+
match. */
|
168
|
+
wildcard_enabled = 1;
|
169
|
+
pattern_label_end = strchr(pattern, '.');
|
170
|
+
if (pattern_label_end == NULL || strchr(pattern_label_end + 1, '.') == NULL ||
|
171
|
+
pattern_wildcard > pattern_label_end || Curl_raw_nequal(pattern, "xn--", 4)) {
|
172
|
+
wildcard_enabled = 0;
|
173
|
+
}
|
174
|
+
if (!wildcard_enabled)
|
175
|
+
return Curl_raw_equal(pattern, hostname) ? CURL_HOST_MATCH : CURL_HOST_NOMATCH;
|
176
|
+
|
177
|
+
hostname_label_end = strchr(hostname, '.');
|
178
|
+
if (hostname_label_end == NULL || !Curl_raw_equal(pattern_label_end, hostname_label_end))
|
179
|
+
return CURL_HOST_NOMATCH;
|
180
|
+
|
181
|
+
/* The wildcard must match at least one character, so the left-most
|
182
|
+
label of the hostname is at least as large as the left-most label
|
183
|
+
of the pattern. */
|
184
|
+
if (hostname_label_end - hostname < pattern_label_end - pattern)
|
185
|
+
return CURL_HOST_NOMATCH;
|
186
|
+
|
187
|
+
prefixlen = (size_t)(pattern_wildcard - pattern);
|
188
|
+
suffixlen = (size_t)(pattern_label_end - (pattern_wildcard + 1));
|
189
|
+
return Curl_raw_nequal(pattern, hostname, prefixlen) &&
|
190
|
+
Curl_raw_nequal(pattern_wildcard + 1, hostname_label_end - suffixlen, suffixlen)
|
191
|
+
? CURL_HOST_MATCH
|
192
|
+
: CURL_HOST_NOMATCH;
|
193
|
+
}
|
194
|
+
|
195
|
+
int Curl_cert_hostcheck(const char *match_pattern, const char *hostname)
|
196
|
+
{
|
197
|
+
if (!match_pattern || !*match_pattern || !hostname || !*hostname) /* sanity check */
|
198
|
+
return 0;
|
199
|
+
|
200
|
+
if (Curl_raw_equal(hostname, match_pattern)) /* trivial case */
|
201
|
+
return 1;
|
202
|
+
|
203
|
+
if (hostmatch(hostname, match_pattern) == CURL_HOST_MATCH)
|
204
|
+
return 1;
|
205
|
+
return 0;
|
206
|
+
}
|
@@ -0,0 +1,175 @@
|
|
1
|
+
/* Obtained from: https://github.com/iSECPartners/ssl-conservatory */
|
2
|
+
|
3
|
+
/*
|
4
|
+
Copyright (C) 2012, iSEC Partners.
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
10
|
+
so, subject to the following conditions:
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
12
|
+
copies or substantial portions of the Software.
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
SOFTWARE.
|
20
|
+
*/
|
21
|
+
|
22
|
+
/*
|
23
|
+
* Helper functions to perform basic hostname validation using OpenSSL.
|
24
|
+
*
|
25
|
+
* Please read "everything-you-wanted-to-know-about-openssl.pdf" before
|
26
|
+
* attempting to use this code. This whitepaper describes how the code works,
|
27
|
+
* how it should be used, and what its limitations are.
|
28
|
+
*
|
29
|
+
* Author: Alban Diquet
|
30
|
+
* License: See LICENSE
|
31
|
+
*
|
32
|
+
*/
|
33
|
+
|
34
|
+
// Get rid of OSX 10.7 and greater deprecation warnings.
|
35
|
+
#if defined(__APPLE__) && defined(__clang__)
|
36
|
+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
37
|
+
#endif
|
38
|
+
|
39
|
+
#include <openssl/ssl.h>
|
40
|
+
#include <openssl/x509v3.h>
|
41
|
+
#include <string.h>
|
42
|
+
|
43
|
+
#include "trilogy/vendor/curl_hostcheck.h"
|
44
|
+
#include "trilogy/vendor/openssl_hostname_validation.h"
|
45
|
+
|
46
|
+
#define HOSTNAME_MAX_SIZE 255
|
47
|
+
|
48
|
+
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || \
|
49
|
+
(defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L)
|
50
|
+
#define ASN1_STRING_get0_data ASN1_STRING_data
|
51
|
+
#endif
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Tries to find a match for hostname in the certificate's Common Name field.
|
55
|
+
*
|
56
|
+
* Returns MatchFound if a match was found.
|
57
|
+
* Returns MatchNotFound if no matches were found.
|
58
|
+
* Returns MalformedCertificate if the Common Name had a NUL character embedded
|
59
|
+
* in it. Returns Error if the Common Name could not be extracted.
|
60
|
+
*/
|
61
|
+
static HostnameValidationResult matches_common_name(const char *hostname, const X509 *server_cert)
|
62
|
+
{
|
63
|
+
int common_name_loc = -1;
|
64
|
+
X509_NAME_ENTRY *common_name_entry = NULL;
|
65
|
+
ASN1_STRING *common_name_asn1 = NULL;
|
66
|
+
const char *common_name_str = NULL;
|
67
|
+
|
68
|
+
// Find the position of the CN field in the Subject field of the certificate
|
69
|
+
common_name_loc = X509_NAME_get_index_by_NID(X509_get_subject_name((X509 *)server_cert), NID_commonName, -1);
|
70
|
+
if (common_name_loc < 0) {
|
71
|
+
return Error;
|
72
|
+
}
|
73
|
+
|
74
|
+
// Extract the CN field
|
75
|
+
common_name_entry = X509_NAME_get_entry(X509_get_subject_name((X509 *)server_cert), common_name_loc);
|
76
|
+
if (common_name_entry == NULL) {
|
77
|
+
return Error;
|
78
|
+
}
|
79
|
+
|
80
|
+
// Convert the CN field to a C string
|
81
|
+
common_name_asn1 = X509_NAME_ENTRY_get_data(common_name_entry);
|
82
|
+
if (common_name_asn1 == NULL) {
|
83
|
+
return Error;
|
84
|
+
}
|
85
|
+
common_name_str = (char *)ASN1_STRING_get0_data(common_name_asn1);
|
86
|
+
|
87
|
+
// Make sure there isn't an embedded NUL character in the CN
|
88
|
+
if ((size_t)ASN1_STRING_length(common_name_asn1) != strlen(common_name_str)) {
|
89
|
+
return MalformedCertificate;
|
90
|
+
}
|
91
|
+
|
92
|
+
// Compare expected hostname with the CN
|
93
|
+
if (Curl_cert_hostcheck(common_name_str, hostname) == CURL_HOST_MATCH) {
|
94
|
+
return MatchFound;
|
95
|
+
} else {
|
96
|
+
return MatchNotFound;
|
97
|
+
}
|
98
|
+
}
|
99
|
+
|
100
|
+
/**
|
101
|
+
* Tries to find a match for hostname in the certificate's Subject Alternative
|
102
|
+
* Name extension.
|
103
|
+
*
|
104
|
+
* Returns MatchFound if a match was found.
|
105
|
+
* Returns MatchNotFound if no matches were found.
|
106
|
+
* Returns MalformedCertificate if any of the hostnames had a NUL character
|
107
|
+
* embedded in it. Returns NoSANPresent if the SAN extension was not present in
|
108
|
+
* the certificate.
|
109
|
+
*/
|
110
|
+
static HostnameValidationResult matches_subject_alternative_name(const char *hostname, const X509 *server_cert)
|
111
|
+
{
|
112
|
+
HostnameValidationResult result = MatchNotFound;
|
113
|
+
int i;
|
114
|
+
int san_names_nb = -1;
|
115
|
+
STACK_OF(GENERAL_NAME) *san_names = NULL;
|
116
|
+
|
117
|
+
// Try to extract the names within the SAN extension from the certificate
|
118
|
+
san_names = X509_get_ext_d2i((X509 *)server_cert, NID_subject_alt_name, NULL, NULL);
|
119
|
+
if (san_names == NULL) {
|
120
|
+
return NoSANPresent;
|
121
|
+
}
|
122
|
+
san_names_nb = sk_GENERAL_NAME_num(san_names);
|
123
|
+
|
124
|
+
// Check each name within the extension
|
125
|
+
for (i = 0; i < san_names_nb; i++) {
|
126
|
+
const GENERAL_NAME *current_name = sk_GENERAL_NAME_value(san_names, i);
|
127
|
+
|
128
|
+
if (current_name->type == GEN_DNS) {
|
129
|
+
// Current name is a DNS name, let's check it
|
130
|
+
const char *dns_name = (char *)ASN1_STRING_get0_data(current_name->d.dNSName);
|
131
|
+
|
132
|
+
// Make sure there isn't an embedded NUL character in the DNS name
|
133
|
+
if ((size_t)ASN1_STRING_length(current_name->d.dNSName) != strlen(dns_name)) {
|
134
|
+
result = MalformedCertificate;
|
135
|
+
break;
|
136
|
+
} else { // Compare expected hostname with the DNS name
|
137
|
+
if (Curl_cert_hostcheck(dns_name, hostname) == CURL_HOST_MATCH) {
|
138
|
+
result = MatchFound;
|
139
|
+
break;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
}
|
143
|
+
}
|
144
|
+
sk_GENERAL_NAME_pop_free(san_names, GENERAL_NAME_free);
|
145
|
+
|
146
|
+
return result;
|
147
|
+
}
|
148
|
+
|
149
|
+
/**
|
150
|
+
* Validates the server's identity by looking for the expected hostname in the
|
151
|
+
* server's certificate. As described in RFC 6125, it first tries to find a
|
152
|
+
* match in the Subject Alternative Name extension. If the extension is not
|
153
|
+
* present in the certificate, it checks the Common Name instead.
|
154
|
+
*
|
155
|
+
* Returns MatchFound if a match was found.
|
156
|
+
* Returns MatchNotFound if no matches were found.
|
157
|
+
* Returns MalformedCertificate if any of the hostnames had a NUL character
|
158
|
+
* embedded in it. Returns Error if there was an error.
|
159
|
+
*/
|
160
|
+
HostnameValidationResult validate_hostname(const char *hostname, const X509 *server_cert)
|
161
|
+
{
|
162
|
+
HostnameValidationResult result;
|
163
|
+
|
164
|
+
if ((hostname == NULL) || (server_cert == NULL))
|
165
|
+
return Error;
|
166
|
+
|
167
|
+
// First try the Subject Alternative Names extension
|
168
|
+
result = matches_subject_alternative_name(hostname, server_cert);
|
169
|
+
if (result == NoSANPresent) {
|
170
|
+
// Extension was not found: try the Common Name
|
171
|
+
result = matches_common_name(hostname, server_cert);
|
172
|
+
}
|
173
|
+
|
174
|
+
return result;
|
175
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#ifndef TRILOGY_RUBY_H
|
2
|
+
#define TRILOGY_RUBY_H
|
3
|
+
|
4
|
+
#include <stdbool.h>
|
5
|
+
|
6
|
+
#include <trilogy.h>
|
7
|
+
|
8
|
+
#define TRILOGY_FLAGS_CAST 1
|
9
|
+
#define TRILOGY_FLAGS_CAST_BOOLEANS 2
|
10
|
+
#define TRILOGY_FLAGS_LOCAL_TIMEZONE 4
|
11
|
+
#define TRILOGY_FLAGS_FLATTEN_ROWS 8
|
12
|
+
#define TRILOGY_FLAGS_DEFAULT (TRILOGY_FLAGS_CAST)
|
13
|
+
|
14
|
+
struct rb_trilogy_cast_options {
|
15
|
+
bool cast;
|
16
|
+
bool cast_booleans;
|
17
|
+
bool database_local_time;
|
18
|
+
bool flatten_rows;
|
19
|
+
};
|
20
|
+
|
21
|
+
struct column_info {
|
22
|
+
TRILOGY_TYPE_t type;
|
23
|
+
TRILOGY_CHARSET_t charset;
|
24
|
+
uint32_t len;
|
25
|
+
uint16_t flags;
|
26
|
+
uint8_t decimals;
|
27
|
+
};
|
28
|
+
|
29
|
+
extern VALUE rb_cTrilogyError;
|
30
|
+
|
31
|
+
VALUE
|
32
|
+
rb_trilogy_cast_value(const trilogy_value_t *value, const struct column_info *column,
|
33
|
+
const struct rb_trilogy_cast_options *options);
|
34
|
+
|
35
|
+
void rb_trilogy_cast_init(void);
|
36
|
+
|
37
|
+
#endif
|
data/lib/trilogy.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require "trilogy/cext"
|
2
|
+
require "trilogy/version"
|
3
|
+
|
4
|
+
class Trilogy
|
5
|
+
def in_transaction?
|
6
|
+
(server_status & SERVER_STATUS_IN_TRANS) != 0
|
7
|
+
end
|
8
|
+
|
9
|
+
def server_info
|
10
|
+
version_str = server_version
|
11
|
+
|
12
|
+
if /\A(\d+)\.(\d+)\.(\d+)/ =~ version_str
|
13
|
+
version_num = ($1.to_i * 10000) + ($2.to_i * 100) + $3.to_i
|
14
|
+
end
|
15
|
+
|
16
|
+
{ :version => version_str, :id => version_num }
|
17
|
+
end
|
18
|
+
|
19
|
+
def connected_host
|
20
|
+
@connected_host ||= query_with_flags("select @@hostname", query_flags | QUERY_FLAGS_FLATTEN_ROWS).rows.first
|
21
|
+
end
|
22
|
+
|
23
|
+
def query_with_flags(sql, flags)
|
24
|
+
old_flags = query_flags
|
25
|
+
self.query_flags = flags
|
26
|
+
|
27
|
+
query(sql)
|
28
|
+
ensure
|
29
|
+
self.query_flags = old_flags
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Trilogy::Result.class_eval do
|
34
|
+
def count
|
35
|
+
rows.count
|
36
|
+
end
|
37
|
+
|
38
|
+
def each_hash
|
39
|
+
return enum_for(:each_hash) unless block_given?
|
40
|
+
|
41
|
+
rows.each do |row|
|
42
|
+
this_row = {}
|
43
|
+
|
44
|
+
idx = 0
|
45
|
+
row.each do |col|
|
46
|
+
this_row[fields[idx]] = col
|
47
|
+
idx += 1
|
48
|
+
end
|
49
|
+
|
50
|
+
yield this_row
|
51
|
+
end
|
52
|
+
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def each(&bk)
|
57
|
+
rows.each(&bk)
|
58
|
+
end
|
59
|
+
|
60
|
+
include Enumerable
|
61
|
+
end
|
data/trilogy.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require File.expand_path("../lib/trilogy/version", __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'trilogy_w_prepared_statements'
|
5
|
+
s.version = Trilogy::VERSION
|
6
|
+
s.authors = ['GitHub Engineering', 'Brian Lopez']
|
7
|
+
s.email = "opensource+trilogy@github.com"
|
8
|
+
s.license = "MIT"
|
9
|
+
s.homepage = "https://github.com/lorint/trilogy_w_prepared_statements"
|
10
|
+
s.summary = "A friendly MySQL-compatible library for Ruby, binding to libtrilogy"
|
11
|
+
|
12
|
+
s.extensions = "ext/trilogy-ruby/extconf.rb"
|
13
|
+
|
14
|
+
gem_files = %w[LICENSE README.md Rakefile trilogy.gemspec]
|
15
|
+
gem_files += Dir.glob("lib/**/*.rb")
|
16
|
+
gem_files += Dir.glob("ext/trilogy-ruby/*.c")
|
17
|
+
gem_files += Dir.glob("ext/trilogy-ruby/*.h")
|
18
|
+
gem_files += Dir.glob("ext/trilogy-ruby/src/**/*.c")
|
19
|
+
gem_files += Dir.glob("ext/trilogy-ruby/inc/**/*.h")
|
20
|
+
|
21
|
+
s.files = gem_files
|
22
|
+
|
23
|
+
s.require_paths = ["lib"]
|
24
|
+
|
25
|
+
s.add_development_dependency "rake-compiler", "~> 1.0"
|
26
|
+
s.add_development_dependency "minitest", "~> 5.5"
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: trilogy_w_prepared_statements
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- GitHub Engineering
|
8
|
+
- Brian Lopez
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2022-12-18 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake-compiler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: minitest
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - "~>"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '5.5'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '5.5'
|
42
|
+
description:
|
43
|
+
email: opensource+trilogy@github.com
|
44
|
+
executables: []
|
45
|
+
extensions:
|
46
|
+
- ext/trilogy-ruby/extconf.rb
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- LICENSE
|
50
|
+
- README.md
|
51
|
+
- Rakefile
|
52
|
+
- ext/trilogy-ruby/cast.c
|
53
|
+
- ext/trilogy-ruby/cext.c
|
54
|
+
- ext/trilogy-ruby/extconf.rb
|
55
|
+
- ext/trilogy-ruby/inc/trilogy.h
|
56
|
+
- ext/trilogy-ruby/inc/trilogy/blocking.h
|
57
|
+
- ext/trilogy-ruby/inc/trilogy/buffer.h
|
58
|
+
- ext/trilogy-ruby/inc/trilogy/builder.h
|
59
|
+
- ext/trilogy-ruby/inc/trilogy/charset.h
|
60
|
+
- ext/trilogy-ruby/inc/trilogy/client.h
|
61
|
+
- ext/trilogy-ruby/inc/trilogy/error.h
|
62
|
+
- ext/trilogy-ruby/inc/trilogy/packet_parser.h
|
63
|
+
- ext/trilogy-ruby/inc/trilogy/protocol.h
|
64
|
+
- ext/trilogy-ruby/inc/trilogy/reader.h
|
65
|
+
- ext/trilogy-ruby/inc/trilogy/socket.h
|
66
|
+
- ext/trilogy-ruby/inc/trilogy/vendor/curl_hostcheck.h
|
67
|
+
- ext/trilogy-ruby/inc/trilogy/vendor/openssl_hostname_validation.h
|
68
|
+
- ext/trilogy-ruby/src/blocking.c
|
69
|
+
- ext/trilogy-ruby/src/buffer.c
|
70
|
+
- ext/trilogy-ruby/src/builder.c
|
71
|
+
- ext/trilogy-ruby/src/charset.c
|
72
|
+
- ext/trilogy-ruby/src/client.c
|
73
|
+
- ext/trilogy-ruby/src/error.c
|
74
|
+
- ext/trilogy-ruby/src/packet_parser.c
|
75
|
+
- ext/trilogy-ruby/src/protocol.c
|
76
|
+
- ext/trilogy-ruby/src/reader.c
|
77
|
+
- ext/trilogy-ruby/src/socket.c
|
78
|
+
- ext/trilogy-ruby/src/vendor/curl_hostcheck.c
|
79
|
+
- ext/trilogy-ruby/src/vendor/openssl_hostname_validation.c
|
80
|
+
- ext/trilogy-ruby/trilogy-ruby.h
|
81
|
+
- lib/trilogy.rb
|
82
|
+
- lib/trilogy/version.rb
|
83
|
+
- trilogy.gemspec
|
84
|
+
homepage: https://github.com/lorint/trilogy_w_prepared_statements
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
metadata: {}
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubygems_version: 3.0.8
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: A friendly MySQL-compatible library for Ruby, binding to libtrilogy
|
107
|
+
test_files: []
|