This repository has been archived by the owner on Jun 12, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
parser3mssql.h
220 lines (191 loc) · 7.35 KB
/
parser3mssql.h
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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*!
* \brief The file contains Parser MSSQL driver interface
* \author \verbatim
Created by: Alexander Egorov
\endverbatim
* \date \verbatim
Creation date: 2010-04-11
\endverbatim
* Copyright 2008-2012 Alexander Egorov <[email protected]> (http://www.egoroff.spb.ru)
*/
#ifndef _MSC_VER
# error compile ISAPI module with MSVC [no urge for now to make it autoconf-ed (PAF)]
#endif
#include "stdafx.h"
#include "pa_sql_driver.h"
#include "Client.h"
#include "QueryDecorator.h"
struct Connection {
SQL_Driver_services* services;
Client* pClient;
};
const DBORDINAL kMaxColumnsCount = 500;
struct ColumnBind {
ColumnBind()
{
memset(this, 0, sizeof(this));
}
LPWSTR szValue;
DBLENGTH nSize;
DWORD dwStatus;
};
/**
* \brief MS SQL server native driver
*/
class SqlNativeDriver : public SQL_Driver {
public:
/**
* \brief Creates driver instance
*/
SqlNativeDriver();
/**
* \brief gets api version
*/
int api_version();
/**
* \brief SQL_Driver initialize implementation just returns zero and does nothing
*/
const char* initialize(char* p);
/**
* \brief creates SQL server connection
* @param pConnString the first string to compare
* format: @b server=<server>;database=<database>;Trusted_Connection=Yes (MSSQL connect string)
* WARNING: must be used only to connect, for buffer doesn't live long
* @param rServices SQL Driver helpers
* @param pConnection Connection object
*/
void connect(
__in char* pConnString,
SQL_Driver_services& rServices,
__deref_out void** pConnection);
/**
* \brief SQL_Driver initialize implementation just returns zero and does nothing
* @param pConnection Connection object that is destroyed in the method
*/
void disconnect(__in void* pConnection);
/**
* \brief Commits a transaction. Does nothing
*/
void commit(void* p);
/**
* \brief Rollbacks a transaction. Does nothing
*/
void rollback(void* p);
/**
* \brief Checks whether a connection is alive. Always returns true
*/
bool ping(void* p);
/**
* \brief Does special symbols escaping
* @param pConnection Connection object
* @param from Pointer to SQL query to escape
* @param length SQL query buffer length
*/
const char* quote(
__in void* pConnection,
__in const char* from,
unsigned int length);
/**
* \brief Runs SQL query
* @param pConnection Connection object
* @param nPlaceholders The number of bind variables. Not used so far
* @param pPlaceholders The pointer to bind variables data. Not used so far
* @param offset The number of records to offset
* @param limit The max number of records to return
* @param rHandlers Query results handler
*/
void query(__in void* pConnection,
__in const char* pStatement,
size_t nPlaceholders,
__in Placeholder* pPlaceholders,
unsigned long offset,
unsigned long limit,
SQL_Driver_query_event_handlers& rHandlers);
private:
void _throw(SQL_Driver_services&, const std::exception&) const;
void ThrowIfError(SQL_Driver_services&, bool isFailure) const;
void ValidateColumns(
ULONG* pColumnsCount, SQL_Driver_services& rServices) const;
void InsertColumn(
const CStringW& rUnicodeStr,
Connection& rConnection,
SQL_Driver_query_event_handlers& rHandlers,
SQL_Error& rSqlError
);
void InsertColumnValue(
const CStringA& rMultibyteStr,
Connection& rConnection,
SQL_Driver_query_event_handlers& rHandlers,
SQL_Error& rSqlError
);
void ExecuteReader(
const QueryDecorator& decorator,
Connection& rConnection,
SQL_Driver_query_event_handlers& rHandlers,
unsigned long offset,
unsigned long limit);
void ExecuteReader(
const QueryDecorator& decorator,
Connection& rConnection,
SQL_Driver_query_event_handlers& rHandlers,
unsigned long offset,
unsigned long limit,
size_t nPlaceholders,
__in Placeholder* pPlaceholders);
template<class TColumnSource, typename TAccessor>
void ReadResults(
CCommand<TAccessor>& cmd,
Connection& rConnection,
SQL_Driver_query_event_handlers& rHandlers,
unsigned long offset,
unsigned long limit,
ULONG nColumns,
TColumnSource src);
template<class TColumnSource>
LPWSTR ReadValue(int i, TColumnSource src);
UINT codePage_;
};
template<>
LPWSTR SqlNativeDriver::ReadValue(int i, ColumnBind* pBind)
{
return pBind[i - 1].szValue;
}
template<>
LPWSTR SqlNativeDriver::ReadValue(
int i,
CCommand<CDynamicStringAccessorW>* pCmd)
{
return pCmd->GetString(i);
}
template<class TColumnSource, typename TAccessor>
void SqlNativeDriver::ReadResults(
CCommand<TAccessor>& cmd,
Connection& rConnection,
SQL_Driver_query_event_handlers& rHandlers,
unsigned long offset,
unsigned long limit,
ULONG nColumns,
TColumnSource src)
{
SQL_Error sqlError;
HRESULT result = NULL;
SQL_Driver_services& rServices = *rConnection.services;
ThrowIfError(rServices, rHandlers.before_rows(sqlError));
if (offset > 0) {
result = cmd.MoveNext(offset - 1);
}
unsigned long row = 0;
while (SUCCEEDED(result) && result != DB_S_ENDOFROWSET && (IsNoLimit(limit) || row < limit)) {
ThrowIfError(rServices, rHandlers.add_row(sqlError));
for (DBORDINAL i = 1; i <= nColumns; ++i) {
const CStringA mbStr = CW2A(ReadValue(i, src), codePage_);
InsertColumnValue(mbStr, rConnection, rHandlers, sqlError);
}
result = cmd.MoveNext();
++row;
}
}
extern "C" SQL_Driver* SQL_DRIVER_CREATE()
{
return new SqlNativeDriver();
}