forked from livecode/livecode
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdbdrivercommon.h
More file actions
263 lines (215 loc) · 5.6 KB
/
dbdrivercommon.h
File metadata and controls
263 lines (215 loc) · 5.6 KB
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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
/* Copyright (C) 2003-2015 LiveCode Ltd.
This file is part of LiveCode.
LiveCode is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License v3 as published by the Free
Software Foundation.
LiveCode 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 General Public License
for more details.
You should have received a copy of the GNU General Public License
along with LiveCode. If not see <http://www.gnu.org/licenses/>. */
// Common exports for drivers, containing default implementations of abstract classes exported by revDB
#include "dbdriver.h"
#include <stdlib.h>
enum
{
STATE_NONE,
STATE_INTEGER,
STATE_MARKER,
STATE_QUOTED_STRING,
STATE_QUOTED_STRING_ESCAPE
};
//class for a database field in a row
class DBField
{
public:
DBField();
virtual ~DBField();
char fieldName[F_NAMESIZE];
unsigned int fieldNum;
unsigned long int maxlength;
signed long int dataSize;
char *data;
DBFieldType fieldType;
Bool freeBuffer;
Bool isAutoIncrement;
Bool isPrimaryKey;
Bool isUnique;
Bool isNotNull;
Bool isNull;
};
struct PlaceholderMap
{
int length;
int *elements;
};
struct QueryMetadata
{
DBString *arguments;
int argument_count;
void *connection;
};
enum cursor_type_t
{
kCursorTypeStatic,
kCursorTypeEmulated,
kCursorTypeForward
};
///////////////////////////////////////////////////////////////////////////////
// Simple extensible buffer class.
// To use:
// DBBuffer t_buffer;
//
// // I want to append 100 bytes so:
// if (!t_buffer . ensure(100))
// .. error ..
// // Buffer now has 100 bytes available beyond the frontier so:
// do_processing_requiring_100_bytes(t_buffer . getFrontier());
// t_buffer . advance(100);
//
// // I need to pass the pointer to somewhere else so I 'grab' it:
// pass_to_thing_that_adopts_pointer(t_buffer . grab());
class DBBuffer
{
public:
DBBuffer(void);
DBBuffer(int p_capacity);
~DBBuffer(void);
// Ensure that there is at least p_amount bytes beyond the frontier.
bool ensure(int p_amount);
// Take ownership of the buffer's backing-store.
char *grab(void);
// Borrow the buffer's backing-store
const char *borrow(void);
// Advance the frontier by count bytes
void advance(int p_count);
// Append the given bytes to the buffer
bool append(const char *p_bytes, int p_length);
// Get a pointer to next position
char *getFrontier(void);
int getSize(void);
private:
char *m_base, *m_frontier, *m_limit;
};
inline DBBuffer::DBBuffer(void)
: m_base(NULL), m_frontier(NULL), m_limit(NULL)
{
}
inline DBBuffer::DBBuffer(int p_capacity)
: m_base(NULL), m_frontier(NULL), m_limit(NULL)
{
ensure(p_capacity);
}
inline DBBuffer::~DBBuffer(void)
{
if (m_base != NULL)
free(m_base);
}
inline bool DBBuffer::ensure(int p_amount)
{
if (m_limit - m_frontier < p_amount)
{
char *t_new_base;
t_new_base = (char *)realloc(m_base, ((m_frontier - m_base) + p_amount + 255) & ~255);
if (t_new_base == NULL)
return false;
m_limit += t_new_base - m_base;
m_frontier += t_new_base - m_base;
m_base = t_new_base;
}
return true;
}
inline char *DBBuffer::grab(void)
{
char *t_store;
t_store = (char *)realloc(m_base, m_frontier - m_base);
m_base = NULL;
m_frontier = NULL;
m_limit = NULL;
return t_store;
}
inline const char *DBBuffer::borrow(void)
{
return m_base;
}
inline int DBBuffer::getSize(void)
{
return m_frontier - m_base;
}
inline char *DBBuffer::getFrontier(void)
{
return m_frontier;
}
inline void DBBuffer::advance(int p_count)
{
m_frontier += p_count;
}
inline bool DBBuffer::append(const char *p_bytes, int p_count)
{
if (!ensure(p_count))
return false;
memcpy(m_frontier, p_bytes, p_count);
advance(p_count);
return true;
}
///////////////////////////////////////////////////////////////////////////////
class CDBConnection: public DBConnection2
{
public:
CDBConnection();
virtual ~CDBConnection();
DBList *getCursorList();
int getConnectionType();
Bool getIsConnected();
void deleteCursor(int p_id);
DBCursor *findCursor(int fid);
int countCursors();
DBCursor *findCursorIndex(int fid);
typedef bool (*ProcessQueryCallback)(void *p_context, int p_placeholder, DBBuffer& p_output);
static bool processQuery(const char *p_input, DBBuffer& p_output, ProcessQueryCallback p_callback, void *p_callback_context);
bool isLegacy(void);
protected:
void addCursor(DBCursor *newcursor);
void closeCursors();
void errorMessageSet(const char *p_message);
Bool isConnected;
int connectionType;
DBList cursorlist;
char *m_error;
};
// Base Class for database cursor of mySQL, Oracle, ...
class CDBCursor: public DBCursor3
{
public:
CDBCursor();
virtual Bool getIsOpen();
virtual Bool IsError();
virtual char* getErrorMessage();
virtual int getFieldCount();
virtual int getRecordCount();
virtual int getRecordNumber();
virtual Bool getEOF();
virtual Bool getBOF();
virtual DBFieldType getFieldType(unsigned int fieldnum);
virtual unsigned int getFieldLength(unsigned int fieldnum);
virtual char* getFieldName(unsigned int fieldnum);
virtual char* getFieldDataBinary(unsigned int fieldnum, unsigned int &fdlength);
virtual char* getFieldDataString(unsigned int fieldnum);
virtual Bool getFieldIsNull(unsigned int fieldnum);
virtual DBConnection* getConnection();
int getVersion(void) { return 3;}
virtual int move(int p_record_index);
protected:
virtual void FreeFields();
Bool isBOF;
Bool isEOF;
Bool isTransaction;
int recordNum;
int recordCount;
int fieldCount;
DBField **fields;
DBConnection *connection;
int maxrows;
Bool cacherows;
};