-
Notifications
You must be signed in to change notification settings - Fork 2
/
ma_fake_request.c
181 lines (164 loc) · 6.24 KB
/
ma_fake_request.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*************************************************************************************
Copyright (c) 2021 SingleStore, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not see <http://www.gnu.org/licenses>
or write to the Free Software Foundation, Inc.,
51 Franklin St., Fifth Floor, Boston, MA 02110, USA
*************************************************************************************/
#include "ma_global.h"
#include "ma_sys.h"
#include "ma_odbc.h"
#define DEFAULT_CATALOG "def"
#define DEFAULT_TABLE "SUB"
SQLRETURN constructField(MA_MEM_ROOT *alloc, MYSQL_FIELD* dest, const char* fieldName, enum enum_field_types type, unsigned long length)
{
dest->name_length = dest->org_name_length = strlen(fieldName);
if (!(dest->name = ma_strdup_root(alloc, fieldName))) { return SQL_ERROR; }
dest->org_name = dest->name;
dest->catalog_length = strlen(DEFAULT_CATALOG);
dest->catalog = DEFAULT_CATALOG;
dest->table_length = strlen(DEFAULT_TABLE);
dest->table = DEFAULT_TABLE;
dest->db_length = dest->org_table_length = dest->def_length = 0;
dest->db = "";
dest->org_table = "";
dest->def = NULL;
dest->decimals = 0;
dest->flags = 0;
dest->type = type;
switch (type) {
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_TINY_BLOB:
dest->flags |= BLOB_FLAG;
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
dest->charsetnr = UTF8_CHARSETNR;
length += 1; // Terminal symbol
break;
default:
dest->charsetnr = BINARY_CHARSETNR;
}
MARIADB_CHARSET_INFO *fieldCs = mariadb_get_charset_by_nr(dest->charsetnr);
dest->length = dest->max_length = length * fieldCs->char_maxlen;
return SQL_SUCCESS;
}
SQLRETURN constructData(MYSQL_DATA *dest, const char * const * const *data, unsigned long nRows, unsigned long nCols, unsigned long *max_lengths)
{
dest->rows = nRows;
dest->fields = nCols;
dest->type = MYSQL_FAKE_RESULT;
if(!nRows)
{
dest->data = NULL;
return SQL_SUCCESS;
}
MYSQL_ROWS *cur = dest->data = (MYSQL_ROWS*) ma_alloc_root(&dest->alloc, nRows * sizeof(MYSQL_ROWS));
if (!cur) return SQL_ERROR;
int i;
unsigned long j;
for (i = 0; i < nRows; i++)
{
if (!(cur->data = (char**)ma_alloc_root(&dest->alloc, sizeof(char*) * nCols)))
{
return SQL_ERROR;
}
cur->length = 0;
for (j = 0; j < nCols; j++)
{
if (data[i][j] != NULL) {
cur->length += strlen(data[i][j]);
max_lengths[j] = MAX(max_lengths[j], strlen(data[i][j]));
if (!(cur->data[j] = ma_strdup_root(&dest->alloc, data[i][j]))) {
return SQL_ERROR;
}
}
else
{
cur->data[j] = NULL;
}
}
if (i < nRows - 1)
{
cur = cur->next = cur + 1;
} else
{
cur->next = NULL;
}
}
return SQL_SUCCESS;
}
/**
Prepare data as if it comes as a result of an SQL query
@param[in] Stmt Handle to the statement
@param[in] fields Column names
@param[in] fieldTypes Column types
@param[in] fieldsLength Number of columns
@param[in] data Values to be written as a response to the request
@param[in] dataLength Number of rows
@return SQL_SUCCESS if no memory allocation errors occurred
*/
SQLRETURN MADB_FakeRequest(MADB_Stmt *Stmt, const char * const *fields, const enum enum_field_types *fieldTypes, unsigned long fieldsLength,
char ***data, unsigned long dataLength)
{
if (!fieldsLength)
return MADB_SetError(&Stmt->Error, MADB_ERR_HY090, "fieldsLength must be non-zero", 0);
if (!fields)
return MADB_SetError(&Stmt->Error, MADB_ERR_HY009, "fields value required", 0);
if (!fieldTypes)
return MADB_SetError(&Stmt->Error, MADB_ERR_HY009, "fieldTypes value required", 0);
if (!data)
return MADB_SetError(&Stmt->Error, MADB_ERR_HY009, "data value required", 0);
LOCK_MARIADB(Stmt->Connection);
MADB_StmtReset(Stmt);
UNLOCK_MARIADB(Stmt->Connection);
MA_MEM_ROOT *alloc_root = &(Stmt->stmt->mem_root);
MA_MEM_ROOT *fields_ma_alloc_root= &((MADB_STMT_EXTENSION *)Stmt->stmt->extension)->fields_ma_alloc_root;
Stmt->stmt->field_count = fieldsLength;
// Check if allocation didn't fail
if (!(Stmt->stmt->fields = (MYSQL_FIELD*)ma_alloc_root(fields_ma_alloc_root, sizeof(MYSQL_FIELD) * fieldsLength)) ||
!(Stmt->stmt->bind= (MYSQL_BIND*)ma_alloc_root(alloc_root, fieldsLength * sizeof(MYSQL_BIND))))
{
ma_free_root(fields_ma_alloc_root, MYF(0));
ma_free_root(alloc_root, MYF(0));
char *errMsg = "Failed to allocate memory for fields";
if (Stmt->stmt->fields) errMsg = "Failed to allocate memory for bind";
return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, errMsg, 0);
}
int i, rc;
unsigned long *max_lengts = calloc(1, sizeof(unsigned long) * fieldsLength);
if (constructData(&(Stmt->stmt->result), data, dataLength, fieldsLength, max_lengts))
{
ma_free_root(fields_ma_alloc_root, MYF(0));
ma_free_root(alloc_root, MYF(0));
free(max_lengts);
return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, "Failed to allocate memory for data", 0);
}
for(i = 0; i < fieldsLength; i++)
{
if (constructField(fields_ma_alloc_root, &Stmt->stmt->fields[i], fields[i], fieldTypes[i], max_lengts[i]))
{
ma_free_root(fields_ma_alloc_root, MYF(0));
ma_free_root(alloc_root, MYF(0));
free(max_lengts);
return MADB_SetError(&Stmt->Error, MADB_ERR_HY001, "Failed to allocate memory for fields", 0);
}
}
free(max_lengts);
Stmt->stmt->state = MYSQL_STMT_USE_OR_STORE_CALLED;
Stmt->stmt->result_cursor = Stmt->stmt->result.data;
Stmt->State = MADB_SS_PREPARED;
MADB_InstallStmt(Stmt, Stmt->stmt);
Stmt->AffectedRows = -1;
return SQL_SUCCESS;
}