-
Notifications
You must be signed in to change notification settings - Fork 50
/
README.txt
350 lines (251 loc) · 9.35 KB
/
README.txt
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
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
DbSimple: Simplest but powerful interface to work with various relational databases.
(C) Dmitry Koterov, http://en.dklab.ru/lib/DbSimple/
ABSTRACT
There are a lot of PHP libraries which bring us unified database access
interfaces: PEAR DB, ADOdb and PDO. Code written using these libraries is
known to be very verbalize and is excessive overloaded by useless details.
DbSimple introduces the interface much more simple and handy than above
(and many other popular) abstraction libraries.
MAIN FEATURES
* Supports PHP 4 and 5, DBMS: MySQL, PostgreSQL � InterBase/FireBird.
* Simple and laconic interface (see samples below).
* Conditional macro-blocks in SQL body ({}-blocks), which allow to
dynamically generate even very complex queries without detriment to
code readability.
* Caching of query results (if necessary).
* Supports various placeholder (query arguments) types: list-based,
associative, identifier-based etc.
* Supports operation "select + count total number of resulting rows"
(for data displayed page-by-page).
* Functions for direct fetching: all result rows, one row, one column,
one cell, associative array, multi-dimensional associative array,
linked tree etc.
* Very handy interface to watch and debug query errors.
* Supports enhanced query logging (including query results and caller
line number).
* Supports "native" database placeholders and automatic optimization
"single prepare, multiple execute".
* Object-based BLOB access interface (if necessary).
* Library code is quite compact: one file is the base class, one file -
specific database driver.
IDEOLOGY
* License LGPL (open-source).
* Library should not wrap differences in SQL language between different DBMS.
* Interface must be extremely laconic and handy for practical usage.
* "Query execution" and "result fetching" must be joined together into
single operation.
* If a query is built "piece by piece" (dynamically by PHP code), it must be
done without detriment to readability.
* Optimization "single prepare, multiple execute" must be performed transparently
and automatically.
WHY NOT TO USE OTHER LIBRARY?
* PEAR DB, ADOdb: these libraries do not simplify DBMS access, they
simply provide us single (and heavy overloaded) access interface; debug
functions are too poor.
* PDO: requires PHP 5; not quite handy work with placeholders and query
results provided.
* Standart PHP functions for DBMS access: poor code readability, large
debugging discomfort, amenability to SQL Injections.
LIBRARY INTERFACE (BRIEF)
mixed connect(string $dsn)
Static function to connect ANY database using DSN syntax.
mixed select(string $query [,$arg1...])
Executes the query and returns the result as 2D-array.
hash selectRow(string $query [,$arg1...])
Fetches the result of single-row query.
array selectCol(string $query [,$arg1...])
Fetches one column.
scalar selectCell(string $query [,$arg1...])
Fetches one query result cell.
mixed selectPage(int &$total, string $query [,$arg1...)
Fetches 2D-array with total number of found rows calculation.
mixed query(string $query [,$arg1...])
Executes non-SELECT query; for auto-increment fields and INSERT
queries - returns last inserted ID.
mixed transaction([mixed $parameters])
Starts the new transaction.
mixed commit() / mixed rollback()
Commits/rollbacks the current transaction.
In addition, to modify the format of result representation you may use
reserved column aliases (ARRAY_KEY* etc.) and attributed SQL comments
(e.g. for turning on caching). See usage synopsis below.
SYNOPSIS
Listing 1: Connect to DBMS
require_once "DbSimple/Generic.php";
$DB = DbSimple_Generic::connect("pgsql://login:password@host/database");
Listing 2: Fetch all resulting rows
$rows = $DB->select('SELECT * FROM ?_user LIMIT 10');
foreach ($rows as $numRow => $row) {
echo $row['user_name'];
}
Listing 3: Fetch one page
// Variable $totalNumberOfUsers will hold total number of found rows.
$rows = $DB->selectPage(
$totalNumberOfUsers,
'SELECT * FROM ?_user LIMIT ?d, ?d',
$pageOffset, $numUsersOnPage
);
Listing 4: Macro-substitutions in SQL queries
$rows = $DB->select('
SELECT *
FROM goods
WHERE
category_id = ?
{ AND activated_at > ? }
LIMIT ?d
',
$categoryId,
(empty($_POST['activated_at'])? DBSIMPLE_SKIP : $_POST['activated_at']),
$pageSize
);
Listing 5: Macro-substitutions in SQL queries #2
$rows = $DB->select('
SELECT *
FROM
goods g
{ JOIN category c ON c.id = g.category_id AND 1 = ? }
WHERE
1 = 1
{ AND c.name = ? }
LIMIT ?d
',
(empty($_POST['cat_name'])? DBSIMPLE_SKIP : 1),
(empty($_POST['cat_name'])? DBSIMPLE_SKIP : $_POST['cat_name']),
$pageSize
);
Listing 6: Macro-substitutions in SQL queries #3
$rows = $DB->select('
SELECT * FROM user
WHERE
1=0
{ OR user_id IN(?a) }
',
$listOfUserIdsMayBeEmpty
// If empty, resulted to 1=0 which means false.
);
Listing 7: Query result caching by time
$DB->setCacher('myCacher');
$row = $DB->select('
-- CACHE: 10h 20m 30s
SELECT * FROM table WHERE id=123
');
// Define caching function.
function myCacher($key, $value)
{
// If $value !== null then we must store it to the cache with key $key.
// If $value === null then we must return the value stored in the cache with key $key.
}
Listing 8: Query result caching with dependence on table modification
// Here forum.modified and topic.modified are TIMESTAMPs.
$row = $DB->select('
-- CACHE: 10h 20m 30s, forum.modified, topic.modified
SELECT *
FROM forum JOIN topic ON topic.forum_id=forum.id
WHERE id=123
');
Listing 9: Fetching of associative array
$rows = $DB->select('SELECT user_id AS ARRAY_KEY, ?_user.* FROM ?_user');
foreach ($rows as $userId => $userData) {
echo $userData['user_name'];
}
Listing 10: List-based placeholder
$ids = array(1, 101, 303);
$DB->select('SELECT name FROM tbl WHERE id IN(?a)', $ids);
// SELECT name FROM tbl WHERE id IN(1, 101, 303)
Listing 11: Associative placeholder
$row = array(
'id' => 10,
'date' => "2006-03-02"
);
$DB->query('UPDATE tbl SET ?a', $row);
// MySQL: UPDATE tbl SET `id`='10', `date`='2006-03-02'
Listing 12: Identifier-based placeholder
$DB->select('SELECT ?# FROM tbl', 'date');
// MySQL: SELECT `date` FROM tbl
// FireBird: SELECT "date" FROM tbl
Listing 13: Identifier-list-based placeholder
$user = array('user_id' => 101, 'user_name' => 'Rabbit', 'user_age' => 30);
$newUserId = $DB->query(
'INSERT INTO user(?#) VALUES(?a)',
array_keys($row),
array_values($row)
);
Listing 14: {Prefix-based placeholder}
$DB->setIdentPrefix('phpbb_');
$DB->select('SELECT * FROM ?_user');
// SELECT * FROM phpbb_users
Listing 15: One row fetching
$row = $DB->selectRow('SELECT * FROM ?_user WHERE user_id=?', $uid);
Listing 16: One cell fetching
$userName = $DB->selectCell(
'SELECT user_name FROM ?_user WHERE user_id=?',
$uid
);
Listing 17: One column fetching
$cities = $DB->selectCol('SELECT city_name FROM ?_cities');
$citiesById = $DB->selectCol(
'SELECT city_id AS ARRAY_KEY, city_name FROM ?_cities'
);
Listing 18: Multi-dimensional associative array fetching
$messagesByTopics = $DB->select('
SELECT
message_topic_id AS ARRAY_KEY_1,
message_id AS ARRAY_KEY_2,
message_subject, message_text
FROM
?_message
');
// $messagesByForumsAndTopics[topicId][messageId] = messageData
Listing 19: Linked tree fetching
$forest = $DB->select('
SELECT
person_id AS ARRAY_KEY,
person_father_id AS PARENT_KEY,
*
FROM ?_person
');
Listing 20: prepare ... execute optimization
foreach ($array as $item) {
// DbSimple underatands that it should execure "prepare" only once!
$DB->query('INSERT INTO tbl(field) VALUES(?)', $item);
}
Listing 21: Error handling
// File connect.php
$DB = DbSimple_Generic::connect('mysql://test:test@localhost1/non-existed-db');
$DB->setErrorHandler('databaseErrorHandler');
function databaseErrorHandler($message, $info)
{
if (!error_reporting()) return;
echo "SQL Error: $message<br><pre>"; print_r($info); echo "</pre>";
exit();
}
// As a result we will get:
SQL Error: Unknown MySQL Server Host 'localhost1' (11001) at .../connect.php line 17
Array
(
[code] => 2005
[message] => Unknown MySQL Server Host 'localhost1' (11001)
[query] => mysql_connect()
[context] => .../connect.php line 17
)
Listing 22: Temporary error disabling
// Please note the "@" operator usage!
// Also an unique index must be created for id field.
if (!@$DB->query('INSERT INTO tbl(id, field) VALUES(1, ?)', $field)) {
// Here goes the reaction on the query error.
// You may fetch error context using $DB->error property.
$DB->query('UPDATE tbl SET field=? WHERE id=1', $field);
}
Listing 23: Query logging
$DB->setLogger('myLogger');
$rows = $DB->select('SELECT * FROM U_GET_PARAM_LIST');
function myLogger($db, $sql)
{
$caller = $db->findLibraryCaller();
$tip = "at ".@$caller['file'].' line '.@$caller['line'];
// Print the query (of course it's better to use Debug_HackerConsole).
echo "<xmp title=\"$tip\">"; print_r($sql); echo "</xmp>";
}
// Will be printed something like:
SELECT * FROM U_GET_PARAM_LIST;
--- 13 ms = 4+3+6; returned 30 row(s);