65 Commits
v1.5 ... v2.2.0

Author SHA1 Message Date
Sergey Tsalkov
3741291f44 add a few more fields to composer.json 2013-06-08 13:55:16 -07:00
Sergey Tsalkov
7e00296b32 add license to composer file 2013-06-08 13:38:26 -07:00
Sergey Tsalkov
e2e95adda2 composer fix 2013-06-08 13:32:01 -07:00
Sergey Tsalkov
34a3de3f84 add composer.json for composer support -- not yet tested 2013-06-08 13:28:27 -07:00
Sergey Tsalkov
cc8dbe47eb %i should allow big ints on 32 bit systems 2013-06-07 00:03:30 -07:00
SergeyTsalkov
8090f4e7dc Update README.md 2013-06-05 00:19:36 -07:00
SergeyTsalkov
58e564c3d5 Update README.md 2013-06-05 01:08:41 -06:00
Sergey Tsalkov
253e803160 WhereClause can't have a __toString() method anymore because of how it's handled in combinatino with preparseQueryParams() now 2013-06-05 00:01:10 -07:00
SergeyTsalkov
c05a575be0 Create README.md 2013-06-05 01:01:08 -06:00
Sergey Tsalkov
e61d66fdf8 new DateTime() can be used with insert-like commands, and with %? as well 2013-06-02 19:45:44 -07:00
Sergey Tsalkov
e9a55de0b4 DB::$usenull param can be used to decide whether insert()-like commands insert NULL or empty string for NULL 2013-06-02 19:22:14 -07:00
Sergey Tsalkov
9e4cbc28c1 %t and %lt variables can be used to hold a datetime, which will be formatted to mysql standards 2013-06-02 19:10:28 -07:00
Sergey Tsalkov
b6397a719c merge freeResult and checkError functions back into queryHelper() since they're only used once 2013-06-02 18:17:59 -07:00
Sergey Tsalkov
65ec35c591 modify WhereClause to hold off on evaluating parameters
preparseQueryParams will now receive full WhereClause object and evaluate there
2013-06-02 15:51:58 -07:00
Sergey Tsalkov
1d61a11098 add %? autodetection parameter, simplify functions such as insert() and update() to rely on it 2013-06-02 15:17:14 -07:00
Sergey Tsalkov
ecd5fe190f clean up query parsing code -- will be necessary for transition to prepared statement approach 2013-06-02 12:52:04 -07:00
Sergey Tsalkov
e94f75fe2a DB::disconnect() allows easy disconnecting from mysql 2013-03-19 12:02:47 -07:00
Sergey Tsalkov
ce11e65070 successful insert/replace/update/delete will return true 2013-03-19 11:31:50 -07:00
Sergey Tsalkov
6cb757797b minor fix for calculated columns with fullcolumns 2013-03-19 11:20:20 -07:00
Sergey Tsalkov
027e1529ba create DB::queryFullColumns() which will supply full column names in the format table.column 2013-02-22 22:11:27 -08:00
Sergey Tsalkov
e03ac71b45 more organization and simplification
add queryAllLists() and queryRawUnbuf() methods
2013-02-22 21:28:41 -08:00
Sergey Tsalkov
f89d70e49e bugfix: can use null value for named or numbered parameters 2013-02-22 16:32:15 -08:00
Sergey Tsalkov
6babe98b11 bugfix: free any extra results so CALL commands don't fail 2013-02-22 16:18:18 -08:00
Sergey Tsalkov
039468f3a3 more cleanups and remove old and unused code 2013-02-22 15:08:08 -08:00
Sergey Tsalkov
5e9507181f code cleanups 2013-02-22 12:37:11 -08:00
Sergey Tsalkov
7364df36cf include a formatting error if they pass an array where we're not expecting one 2013-02-22 11:52:18 -08:00
Sergey Tsalkov
7df5c9baa2 update copyright year 2012-09-20 21:05:19 -07:00
Sergey Tsalkov
ed347e841a verticalslice and reindex cleanups and tests 2012-09-20 20:50:05 -07:00
Sergey Tsalkov
2ffb770f8a bugfix: don't fail when inserting multiple rows at once, and one of the values is NULL 2012-09-19 14:58:09 -07:00
Sergey Tsalkov
ed9c29fe49 add DB::transactionDepth() for checking how many transactions are active
when not using nested transactions, will return 1 or 0
2012-09-18 21:08:28 -07:00
Sergey Tsalkov
9a41bf34a1 a few nested transaction cleanups
functionality for committing/rolling back all active transactions
2012-09-18 20:54:39 -07:00
Sergey Tsalkov
24c1b930df add DBHelper class with functions verticalSlice and reIndex 2012-09-18 20:13:43 -07:00
Sergey Tsalkov
d40bc57dde add nested transactions (mysql >= 5.5 only) 2012-09-18 19:08:37 -07:00
Sergey Tsalkov
c62fc187ee quick testing change 2012-09-09 17:31:57 -07:00
Sergey Tsalkov
6b324d1291 using $where is now equivalent to $where->text() 2012-09-09 14:49:43 -07:00
Sergey Tsalkov
5b4e5a959a fix named parameters 2012-07-22 17:43:34 -07:00
Sergey Tsalkov
7582961ee1 named parameters for queries 2012-07-22 17:29:59 -07:00
Sergey Tsalkov
2d49f4f350 remove backtrace from default error message -- it can leak private information 2012-07-08 13:04:57 -07:00
Sergey Tsalkov
9930fc073a restore %lb parameter to working, add unit test so it doesn't break again 2012-02-03 17:19:54 -08:00
Sergey Tsalkov
788c506f16 success handler gets "affected" var for affected rows 2012-01-25 13:59:42 -08:00
Sergey Tsalkov
bbf9534326 add execution time to tests 2011-12-24 17:27:53 -08:00
Sergey Tsalkov
1d5844bcc0 major redesign to enable multiple instances via "new MeekroDB()" while preserving full backwards
compatability

static methods DB::whatever() will still be the recommended method of use, but the new object oriented
approach is now available to those who want it
2011-12-24 16:12:13 -08:00
Sergey Tsalkov
34c0f5e0a7 add E_STRICT to tests 2011-12-24 13:07:44 -08:00
Sergey Tsalkov
7825f90080 can now refer to a specific argument in a query
e.g. %s2 for the third argument, taken as a string
2011-12-17 19:54:55 -08:00
Sergey Tsalkov
a1f01a4f87 few more fixes and tests for WhereClause 2011-09-23 22:03:15 -07:00
Sergey Tsalkov
80cc78edcd insertUpdate() can now handle a second array for the update component, or nothing, so it'll
re-use the insert array for the update component
2011-09-23 21:29:40 -07:00
Sergey Tsalkov
5050205e58 add insertUpdate() function for "insert ... on duplicate key update" behavior 2011-09-23 19:15:41 -07:00
Sergey Tsalkov
9f3aa571dc add some simple tests for the WhereClause system, which will now be official and documented 2011-09-23 18:44:34 -07:00
Sergey Tsalkov
a2800ef04b add insertIgnore() function -- pretty self explanatory 2011-09-23 16:11:10 -07:00
Sergey Tsalkov
164c7157a6 queryRaw() will now be officially supported, returns mysqli_result instead of array of assoc
arrays
2011-09-23 15:57:36 -07:00
Sergey Tsalkov
f09308a3f7 re-organize test files, make it easy to test for both php 5.2 and 5.3 2011-09-23 15:51:35 -07:00
Sergey Tsalkov
69bfe15ebb add test case regarding BLOBs 2011-08-25 23:54:52 -07:00
Sergey Tsalkov
7621b50a02 handle non-sql errors (such as failure to connect to MySQL server) in a user-defined way
adds DB::$nonsql_error_handler and DB::$throw_exception_on_nonsql_error
2011-08-25 23:34:37 -07:00
Sergey Tsalkov
4122fe52c1 collapse some redundant code into a function 2011-06-02 18:57:46 -04:00
Sergey Tsalkov
8072f6ab07 use static class variable, not static function variable, to hold mysql connection 2011-06-01 17:30:28 -04:00
Sergey Tsalkov
860da8d18a insert(), replace(), and update() now handle the value NULL correctly 2011-05-31 21:50:24 -04:00
Sergey Tsalkov
0ed2837f3d on second thought, we won't have insertMany() and replaceMany(), but insert() and replace()
will figure out which one you mean

this means that a minor undocumented feature, being able to insert an array and have it
automatically serialized, can't exist anymore
2011-04-29 01:48:27 -04:00
Sergey Tsalkov
65cae974c5 remove unused variable 2011-04-28 18:51:53 -04:00
Sergey Tsalkov
96892fa6c2 DB::$param_char can now be used to change the char that needs to appear in front of params (% is the default) 2011-04-28 18:41:13 -04:00
Sergey Tsalkov
ad4889da09 revert last commit -- this is a bad way to do it, and I'll have to come up with something else
to let people use strings like %i in their SQL and bypass the parser
2011-04-28 18:14:59 -04:00
Sergey Tsalkov
12604d7854 bugfix: let people have literal %'s in their queries without confusing the parser
by using %% instead
2011-04-23 20:31:18 -04:00
Sergey Tsalkov
8c5299c2e2 * add insertMany() and replaceMany() to let you do multiple inserts in one SQL command
* error and success handlers can now be set to static and object methods
2011-04-23 00:46:51 -04:00
Sergey Tsalkov
964a36e4c2 sqleval() can now be used with %s, %i, and all that good stuff
there is probably no good reason to do this, as things like md5() can be done
from PHP, but people keep asking for it, so here it is :)
2011-04-22 23:29:09 -04:00
Sergey Tsalkov
68774532e1 add delete() function -- mostly for completeness with insert(), update(), etc 2011-04-22 23:15:14 -04:00
Sergey Tsalkov
2985815750 * add tests for tableList() and columnList() -- those are now supported functions
* remove some unused code, minor cleanup
2011-04-22 23:03:37 -04:00
15 changed files with 1809 additions and 462 deletions

1
.gitignore vendored
View File

@@ -0,0 +1 @@
simpletest/test_setup.php

118
README.md Normal file
View File

@@ -0,0 +1,118 @@
MeekroDB -- The Simple PHP MySQL Library
========
Learn more: http://www.meekro.com
MeekroDB is:
* A PHP MySQL library that lets you **get more done with fewer lines of code**, and **makes SQL injection 100% impossible**.
* Google's #1 search result for "php mysql library" for over 2 years, with **thousands of deployments worldwide**.
* A library with a **perfect security track record**. No bugs relating to security or SQL injection have ever been discovered.
Code Examples
========
### Grab some rows from the database and print out a field from each row.
$accounts = DB::query("SELECT * FROM accounts WHERE type = %s AND age > %i", $type, 15);
foreach ($accounts as $account) {
echo $account['username'] . "\n";
}
### Insert a new row.
DB::insert('mytable', array(
'name' => $name,
'rank' => $rank,
'location' => $location,
'age' => $age,
'intelligence' => $intelligence
));
### Grab one row or field
$account = DB::queryFirstRow("SELECT * FROM accounts WHERE username=%s", 'Joe');
$number_accounts = DB::queryFirstField("SELECT COUNT(*) FROM accounts");
### Use a list in a query
DB::query("SELECT * FROM tbl WHERE name IN %ls AND age NOT IN %li", array('John', 'Bob'), array(12, 15));
### Nested Transactions
DB::$nested_transactions = true;
DB::startTransaction(); // outer transaction
// .. some queries..
$depth = DB::startTransaction(); // inner transaction
echo $depth . 'transactions are currently active'; // 2
// .. some queries..
DB::commit(); // commit inner transaction
// .. some queries..
DB::commit(); // commit outer transaction
### Lots More - See: http://www.meekro.com/docs.php
How is MeekroDB better than PDO?
========
### Optional Static Class Mode
Most web apps will only ever talk to one database. This means that
passing $db objects to every function of your code just adds unnecessary clutter.
The simplest approach is to use static methods such as DB::query(), and that's how
MeekroDB works. Still, if you need database objects, MeekroDB can do that too.
### Do more with fewer lines of code
The code below escapes your parameters for safety, runs the query, and grabs
the first row of results. Try doing that in one line with PDO.
$account = DB::queryFirstRow("SELECT * FROM accounts WHERE username=%s", 'Joe');
### Work with list parameters easily
Using MySQL's IN keyword should not be hard. MeekroDB smooths out the syntax for you,
PDO does not.
$accounts = DB::query("SELECT * FROM accounts WHERE username IN %ls", array('Joe', 'Frank'));
### Simple inserts
Using MySQL's INSERT should not be more complicated than passing in an
associative array. MeekroDB also simplifies many related commands, including
the useful and bizarre INSERT .. ON DUPLICATE UPDATE command. PDO does none of this.
DB::insert('accounts', array('username' => 'John', 'password' => 'whatever'));
### Focus on the goal, not the task
Want to do INSERT yourself rather than relying on DB::insert()?
It's dead simple. I don't even want to think about how many lines
you'd need to pull this off in PDO.
// Insert 2 rows at once
DB::query("INSERT INTO %b %lb VALUES %?", 'accounts',
array('username', 'password', 'last_login_timestamp'),
array(
array('Joe', 'joes_password', new DateTime('yesterday')),
array('Frank', 'franks_password', new DateTime('last Monday'))
)
);
### Nested transactions
MySQL's SAVEPOINT commands lets you create nested transactions, but only
if you keep track of SAVEPOINT ids yourself. MeekroDB does this for you,
so you can have nested transactions with no complexity or learning curve.
DB::$nested_transactions = true;
DB::startTransaction(); // outer transaction
// .. some queries..
$depth = DB::startTransaction(); // inner transaction
echo $depth . 'transactions are currently active'; // 2
// .. some queries..
DB::commit(); // commit inner transaction
// .. some queries..
DB::commit(); // commit outer transaction
### Flexible error and success handlers
Set your own custom function run on errors, or on every query that succeeds.
You can easily have separate error handling behavior for the dev and live
versions of your application. Want to count up all your queries and their
runtime? Just add a new success handler.
### More about MeekroDB's design philosophy: http://www.meekro.com/beliefs.php

29
composer.json Normal file
View File

@@ -0,0 +1,29 @@
{
"name": "SergeyTsalkov/meekrodb",
"description": "The Simple PHP/MySQL Library",
"homepage": "http://www.meekro.com",
"support": {
"email": "support@meekro.com"
},
"keywords": [
"mysql",
"database",
"mysqli",
"pdo"
],
"license": "LGPL-3.0",
"authors": [
{
"name": "Sergey Tsalkov",
"email": "stsalkov@gmail.com"
}
],
"require": {
"php": ">=5.2.0"
},
"autoload": {
"classmap": [
"db.class.php"
]
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,37 +1,32 @@
<?php
function new_error_callback($params) {
global $error_callback_worked;
if (substr_count($params['error'], 'You have an error in your SQL syntax')) $error_callback_worked = 1;
}
function my_debug_handler($params) {
global $debug_callback_worked;
if (substr_count($params['query'], 'SELECT')) $debug_callback_worked = 1;
}
class BasicTest extends SimpleTest {
function __construct() {
error_reporting(E_ALL);
require_once '../db.class.php';
DB::$user = 'libdb_user';
DB::$password = 'sdf235sklj';
DB::$dbName = 'libdb_test';
DB::query("DROP DATABASE libdb_test");
DB::query("CREATE DATABASE libdb_test");
DB::useDB('libdb_test');
foreach (DB::tableList() as $table) {
DB::query("DROP TABLE $table");
}
}
function test_1_create_table() {
DB::query("CREATE TABLE `accounts` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`profile_id` INT NOT NULL,
`username` VARCHAR( 255 ) NOT NULL ,
`password` VARCHAR( 255 ) NOT NULL ,
`password` VARCHAR( 255 ) NULL ,
`age` INT NOT NULL DEFAULT '10',
`height` DOUBLE NOT NULL DEFAULT '10.0'
`height` DOUBLE NOT NULL DEFAULT '10.0',
`favorite_word` VARCHAR( 255 ) NULL DEFAULT 'hi',
`birthday` TIMESTAMP NOT NULL
) ENGINE = InnoDB");
DB::query("CREATE TABLE `profile` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`signature` VARCHAR( 255 ) NULL DEFAULT 'donewriting'
) ENGINE = InnoDB");
$mysqli = DB::get();
DB::disconnect();
@$this->assert($mysqli->server_info === null);
}
function test_1_5_empty_table() {
@@ -55,11 +50,12 @@ class BasicTest extends SimpleTest {
}
function test_2_insert_row() {
DB::insert('accounts', array(
$true = DB::insert('accounts', array(
'username' => 'Abe',
'password' => 'hello'
));
$this->assert($true === true);
$this->assert(DB::affectedRows() === 1);
$counter = DB::queryFirstField("SELECT COUNT(*) FROM accounts");
@@ -73,22 +69,52 @@ class BasicTest extends SimpleTest {
'age' => 15,
'height' => 10.371
));
DB::insert('`libdb_test`.`accounts`', array(
$dbname = DB::$dbName;
DB::insert("`$dbname`.`accounts`", array(
'username' => 'Charlie\'s Friend',
'password' => 'goodbye',
'age' => 30,
'height' => 155.23
'height' => 155.23,
'favorite_word' => null,
));
$this->assert(DB::insertId() === 3);
$counter = DB::queryFirstField("SELECT COUNT(*) FROM accounts");
$this->assert($counter === strval(3));
$bart = DB::queryFirstRow("SELECT * FROM accounts WHERE age IN %li AND height IN %ld AND username IN %ls",
DB::insert('`accounts`', array(
'username' => 'Deer',
'password' => '',
'age' => 15,
'height' => 10.371
));
$username = DB::queryFirstField("SELECT username FROM accounts WHERE password=%s0", null);
$this->assert($username === 'Deer');
$password = DB::queryFirstField("SELECT password FROM accounts WHERE favorite_word IS NULL");
$this->assert($password === 'goodbye');
DB::$usenull = false;
DB::insertUpdate('accounts', array(
'id' => 3,
'favorite_word' => null,
));
$password = DB::queryFirstField("SELECT password FROM accounts WHERE favorite_word=%s AND favorite_word=%s", null, '');
$this->assert($password === 'goodbye');
DB::$usenull = true;
DB::insertUpdate('accounts', array(
'id' => 3,
'favorite_word' => null,
));
DB::$param_char = '###';
$bart = DB::queryFirstRow("SELECT * FROM accounts WHERE age IN ###li AND height IN ###ld AND username IN ###ls",
array(15, 25), array(10.371, 150.123), array('Bart', 'Barts'));
$this->assert($bart['username'] === 'Bart');
DB::$param_char = '%';
$charlie_password = DB::queryFirstField("SELECT password FROM accounts WHERE username IN %ls AND username = %s",
array('Charlie', 'Charlie\'s Friend'), 'Charlie\'s Friend');
@@ -107,84 +133,265 @@ class BasicTest extends SimpleTest {
$this->assert($username === 'Bart');
$this->assert($password === 'hello');
$this->assert($age == 15);
$mysqli_result = DB::queryRaw("SELECT * FROM accounts WHERE favorite_word IS NULL");
$this->assert($mysqli_result instanceof MySQLi_Result);
$row = $mysqli_result->fetch_assoc();
$this->assert($row['password'] === 'goodbye');
$this->assert($mysqli_result->fetch_assoc() === null);
}
function test_4_query() {
$results = DB::query("SELECT * FROM accounts WHERE username=%s", 'Charlie\'s Friend');
DB::update('accounts', array(
'birthday' => new DateTime('10 September 2000 13:13:13')
), 'username=%s', 'Charlie\'s Friend');
$results = DB::query("SELECT * FROM accounts WHERE username=%s AND birthday IN %lt", 'Charlie\'s Friend', array('September 10 2000 13:13:13'));
$this->assert(count($results) === 1);
$this->assert($results[0]['age'] == 30 && $results[0]['password'] == 'goodbye');
$this->assert($results[0]['age'] === '30' && $results[0]['password'] === 'goodbye');
$this->assert($results[0]['birthday'] == '2000-09-10 13:13:13');
$results = DB::query("SELECT * FROM accounts WHERE username!=%s", "Charlie's Friend");
$this->assert(count($results) === 2);
$this->assert(count($results) === 3);
$columnlist = DB::columnList('accounts');
$this->assert(count($columnlist) === 8);
$this->assert($columnlist[0] === 'id');
$this->assert($columnlist[5] === 'height');
$tablelist = DB::tableList();
$this->assert(count($tablelist) === 2);
$this->assert($tablelist[0] === 'accounts');
$tablelist = null;
$tablelist = DB::tableList(DB::$dbName);
$this->assert(count($tablelist) === 2);
$this->assert($tablelist[0] === 'accounts');
}
function test_4_1_query() {
DB::insert('accounts', array(
'username' => 'newguy',
'password' => DB::sqleval("REPEAT('blah', 3)"),
'age' => 172,
'password' => DB::sqleval("REPEAT('blah', %i)", '3'),
'age' => DB::sqleval('171+1'),
'height' => 111.15
));
$row = DB::queryOneRow("SELECT * FROM accounts WHERE password=%s", 'blahblahblah');
$this->assert($row['username'] === 'newguy');
$this->assert($row['age'] === '172');
DB::update('accounts', array(
'password' => DB::sqleval("REPEAT('blah', 4)"),
$true = DB::update('accounts', array(
'password' => DB::sqleval("REPEAT('blah', %i)", 4),
'favorite_word' => null,
), 'username=%s', 'newguy');
$row = null;
$row = DB::queryOneRow("SELECT * FROM accounts WHERE username=%s", 'newguy');
$this->assert($true === true);
$this->assert($row['password'] === 'blahblahblahblah');
$this->assert($row['favorite_word'] === null);
DB::query("DELETE FROM accounts WHERE password=%s", 'blahblahblahblah');
$row = DB::query("SELECT * FROM accounts WHERE password=%s_mypass AND (password=%s_mypass) AND username=%s_myuser",
array('myuser' => 'newguy', 'mypass' => 'blahblahblahblah')
);
$this->assert(count($row) === 1);
$this->assert($row[0]['username'] === 'newguy');
$this->assert($row[0]['age'] === '172');
$true = DB::query("DELETE FROM accounts WHERE password=%s", 'blahblahblahblah');
$this->assert($true === true);
$this->assert(DB::affectedRows() === 1);
}
function test_5_error_handler() {
global $error_callback_worked;
function test_4_2_delete() {
DB::insert('accounts', array(
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
));
DB::$error_handler = 'new_error_callback';
DB::query("SELET * FROM accounts");
$this->assert($error_callback_worked === 1);
$ct = DB::queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s AND height=%d", 'gonesoon', 199.194);
$this->assert(intval($ct) === 1);
$ct = DB::queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s1 AND height=%d0 AND height=%d", 199.194, 'gonesoon');
$this->assert(intval($ct) === 1);
DB::delete('accounts', 'username=%s AND age=%i AND height=%d', 'gonesoon', '61', '199.194');
$this->assert(DB::affectedRows() === 1);
$ct = DB::queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s AND height=%d", 'gonesoon', '199.194');
$this->assert(intval($ct) === 0);
}
function test_6_exception_catch() {
DB::$error_handler = '';
DB::$throw_exception_on_error = true;
try {
DB::query("SELET * FROM accounts");
} catch(MeekroDBException $e) {
$this->assert(substr_count($e->getMessage(), 'You have an error in your SQL syntax'));
$this->assert($e->getQuery() === 'SELET * FROM accounts');
$exception_was_caught = 1;
}
$this->assert($exception_was_caught === 1);
function test_4_3_insertmany() {
$ins[] = array(
'username' => '1ofmany',
'password' => 'something',
'age' => 23,
'height' => 190.194
);
$ins[] = array(
'password' => 'somethingelse',
'username' => '2ofmany',
'age' => 25,
'height' => 190.194
);
$ins[] = array(
'password' => NULL,
'username' => '3ofmany',
'age' => 15,
'height' => 111.951
);
try {
DB::insert('`libdb_test`.`accounts`', array(
'id' => 2,
'username' => 'Another Dude\'s \'Mom"',
'password' => 'asdfsdse',
'age' => 35,
'height' => 555.23
));
} catch(MeekroDBException $e) {
$this->assert(substr_count($e->getMessage(), 'Duplicate entry'));
$exception_was_caught = 2;
}
$this->assert($exception_was_caught === 2);
DB::insert('accounts', $ins);
$this->assert(DB::affectedRows() === 3);
$rows = DB::query("SELECT * FROM accounts WHERE height=%d ORDER BY age ASC", 190.194);
$this->assert(count($rows) === 2);
$this->assert($rows[0]['username'] === '1ofmany');
$this->assert($rows[0]['age'] === '23');
$this->assert($rows[1]['age'] === '25');
$this->assert($rows[1]['password'] === 'somethingelse');
$this->assert($rows[1]['username'] === '2ofmany');
$nullrow = DB::queryOneRow("SELECT * FROM accounts WHERE username=%s", '3ofmany');
$this->assert($nullrow['password'] === NULL);
$this->assert($nullrow['age'] === '15');
}
function test_7_debugmode_handler() {
global $debug_callback_worked;
function test_5_insert_blobs() {
DB::query("CREATE TABLE `storedata` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`picture` BLOB
) ENGINE = InnoDB");
DB::debugMode('my_debug_handler');
DB::query("SELECT * FROM accounts WHERE username!=%s", "Charlie's Friend");
$this->assert($debug_callback_worked === 1);
$smile = file_get_contents('smile1.jpg');
DB::insert('storedata', array(
'picture' => $smile,
));
DB::query("INSERT INTO storedata (picture) VALUES (%s)", $smile);
DB::debugMode(false);
$getsmile = DB::queryFirstField("SELECT picture FROM storedata WHERE id=1");
$getsmile2 = DB::queryFirstField("SELECT picture FROM storedata WHERE id=2");
$this->assert($smile === $getsmile);
$this->assert($smile === $getsmile2);
}
function test_6_insert_ignore() {
DB::insertIgnore('accounts', array(
'id' => 1, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
));
}
function test_7_insert_update() {
$true = DB::insertUpdate('accounts', array(
'id' => 2, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
), 'age = age + %i', 1);
$this->assert($true === true);
$this->assert(DB::affectedRows() === 2); // a quirk of MySQL, even though only 1 row was updated
$result = DB::query("SELECT * FROM accounts WHERE age = %i", 16);
$this->assert(count($result) === 1);
$this->assert($result[0]['height'] === '10.371');
DB::insertUpdate('accounts', array(
'id' => 2, //duplicate primary key
'username' => 'blahblahdude',
'age' => 233,
'height' => 199.194
));
$result = DB::query("SELECT * FROM accounts WHERE age = %i", 233);
$this->assert(count($result) === 1);
$this->assert($result[0]['height'] === '199.194');
$this->assert($result[0]['username'] === 'blahblahdude');
DB::insertUpdate('accounts', array(
'id' => 2, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
), array(
'age' => 74,
));
$result = DB::query("SELECT * FROM accounts WHERE age = %i", 74);
$this->assert(count($result) === 1);
$this->assert($result[0]['height'] === '199.194');
$this->assert($result[0]['username'] === 'blahblahdude');
$multiples[] = array(
'id' => 3, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
);
$multiples[] = array(
'id' => 1, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
);
DB::insertUpdate('accounts', $multiples, array('age' => 914));
$this->assert(DB::affectedRows() === 4);
$result = DB::query("SELECT * FROM accounts WHERE age=914 ORDER BY id ASC");
$this->assert(count($result) === 2);
$this->assert($result[0]['username'] === 'Abe');
$this->assert($result[1]['username'] === 'Charlie\'s Friend');
$true = DB::query("UPDATE accounts SET age=15, username='Bart' WHERE age=%i", 74);
$this->assert($true === true);
$this->assert(DB::affectedRows() === 1);
}
function test_8_lb() {
$data = array(
'username' => 'vookoo',
'password' => 'dookoo',
);
$true = DB::query("INSERT into accounts %lb VALUES %ls", array_keys($data), array_values($data));
$result = DB::query("SELECT * FROM accounts WHERE username=%s", 'vookoo');
$this->assert($true === true);
$this->assert(count($result) === 1);
$this->assert($result[0]['password'] === 'dookoo');
}
function test_9_fullcolumns() {
$true = DB::insert('profile', array(
'id' => 1,
'signature' => 'u_suck'
));
DB::query("UPDATE accounts SET profile_id=1 WHERE id=2");
$r = DB::queryFullColumns("SELECT accounts.*, profile.*, 1+1 FROM accounts
INNER JOIN profile ON accounts.profile_id=profile.id");
$this->assert($true === true);
$this->assert(count($r) === 1);
$this->assert($r[0]['accounts.id'] === '2');
$this->assert($r[0]['profile.id'] === '1');
$this->assert($r[0]['profile.signature'] === 'u_suck');
$this->assert($r[0]['1+1'] === '2');
}
}

17
simpletest/CallTest.php Normal file
View File

@@ -0,0 +1,17 @@
<?php
class CallTest extends SimpleTest {
function test_1_create_procedure() {
DB::query("DROP PROCEDURE IF EXISTS myProc");
DB::query("CREATE PROCEDURE myProc()
BEGIN
SELECT * FROM accounts;
END");
}
function test_2_run_procedure() {
$r = DB::query("CALL myProc()");
$this->assert($r[0]['username'] === 'Abe');
$this->assert($r[2]['age'] === '914');
}
}

83
simpletest/ErrorTest.php Normal file
View File

@@ -0,0 +1,83 @@
<?
function new_error_callback($params) {
global $error_callback_worked;
if (substr_count($params['error'], 'You have an error in your SQL syntax')) $error_callback_worked = 1;
}
function my_debug_handler($params) {
global $debug_callback_worked;
if (substr_count($params['query'], 'SELECT')) $debug_callback_worked = 1;
}
class ErrorTest extends SimpleTest {
function test_1_error_handler() {
global $error_callback_worked, $static_error_callback_worked, $nonstatic_error_callback_worked;
DB::$error_handler = 'new_error_callback';
DB::query("SELET * FROM accounts");
$this->assert($error_callback_worked === 1);
DB::$error_handler = array('ErrorTest', 'static_error_callback');
DB::query("SELET * FROM accounts");
$this->assert($static_error_callback_worked === 1);
DB::$error_handler = array($this, 'nonstatic_error_callback');
DB::query("SELET * FROM accounts");
$this->assert($nonstatic_error_callback_worked === 1);
}
public static function static_error_callback($params) {
global $static_error_callback_worked;
if (substr_count($params['error'], 'You have an error in your SQL syntax')) $static_error_callback_worked = 1;
}
public function nonstatic_error_callback($params) {
global $nonstatic_error_callback_worked;
if (substr_count($params['error'], 'You have an error in your SQL syntax')) $nonstatic_error_callback_worked = 1;
}
function test_2_exception_catch() {
$dbname = DB::$dbName;
DB::$error_handler = '';
DB::$throw_exception_on_error = true;
try {
DB::query("SELET * FROM accounts");
} catch(MeekroDBException $e) {
$this->assert(substr_count($e->getMessage(), 'You have an error in your SQL syntax'));
$this->assert($e->getQuery() === 'SELET * FROM accounts');
$exception_was_caught = 1;
}
$this->assert($exception_was_caught === 1);
try {
DB::insert("`$dbname`.`accounts`", array(
'id' => 2,
'username' => 'Another Dude\'s \'Mom"',
'password' => 'asdfsdse',
'age' => 35,
'height' => 555.23
));
} catch(MeekroDBException $e) {
$this->assert(substr_count($e->getMessage(), 'Duplicate entry'));
$exception_was_caught = 2;
}
$this->assert($exception_was_caught === 2);
}
function test_3_debugmode_handler() {
global $debug_callback_worked;
DB::debugMode('my_debug_handler');
DB::query("SELECT * FROM accounts WHERE username!=%s", "Charlie's Friend");
$this->assert($debug_callback_worked === 1);
DB::debugMode(false);
}
}
?>

View File

@@ -0,0 +1,19 @@
<?
class ErrorTest_53 extends SimpleTest {
function test_1_error_handler() {
global $anonymous_error_callback_worked;
DB::$throw_exception_on_error = false;
DB::$error_handler = function($params) {
global $anonymous_error_callback_worked;
if (substr_count($params['error'], 'You have an error in your SQL syntax')) $anonymous_error_callback_worked = 1;
};
DB::query("SELET * FROM accounts");
$this->assert($anonymous_error_callback_worked === 1);
}
}
?>

51
simpletest/HelperTest.php Normal file
View File

@@ -0,0 +1,51 @@
<?
class HelperTest extends SimpleTest {
function test_1_verticalslice() {
$all = DB::query("SELECT * FROM accounts ORDER BY id ASC");
$names = DBHelper::verticalSlice($all, 'username');
$this->assert(count($names) === 5);
$this->assert($names[0] === 'Abe');
$ages = DBHelper::verticalSlice($all, 'age', 'username');
$this->assert(count($ages) === 5);
$this->assert($ages['Abe'] === '700');
}
function test_2_reindex() {
$all = DB::query("SELECT * FROM accounts ORDER BY id ASC");
$names = DBHelper::reIndex($all, 'username');
$this->assert(count($names) === 5);
$this->assert($names['Bart']['username'] === 'Bart');
$this->assert($names['Bart']['age'] === '15');
$names = DBHelper::reIndex($all, 'username', 'age');
$this->assert($names['Bart']['15']['username'] === 'Bart');
$this->assert($names['Bart']['15']['age'] === '15');
}
function test_3_empty() {
$none = DB::query("SELECT * FROM accounts WHERE username=%s", 'doesnotexist');
$this->assert(is_array($none) && count($none) === 0);
$names = DBHelper::verticalSlice($none, 'username', 'age');
$this->assert(is_array($names) && count($names) === 0);
$names_other = DBHelper::reIndex($none, 'username', 'age');
$this->assert(is_array($names_other) && count($names_other) === 0);
}
function test_4_null() {
DB::query("UPDATE accounts SET password = NULL WHERE username=%s", 'Bart');
$all = DB::query("SELECT * FROM accounts ORDER BY id ASC");
$ages = DBHelper::verticalSlice($all, 'age', 'password');
$this->assert(count($ages) === 5);
$this->assert($ages[''] === '15');
$passwords = DBHelper::reIndex($all, 'password');
$this->assert(count($passwords) === 5);
$this->assert($passwords['']['username'] === 'Bart');
$this->assert($passwords['']['password'] === NULL);
}
}
?>

312
simpletest/ObjectTest.php Normal file
View File

@@ -0,0 +1,312 @@
<?php
class ObjectTest extends SimpleTest {
public $mdb;
function __construct() {
$this->mdb = new MeekroDB();
foreach ($this->mdb->tableList() as $table) {
$this->mdb->query("DROP TABLE $table");
}
}
function test_1_create_table() {
$this->mdb->query("CREATE TABLE `accounts` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 255 ) NOT NULL ,
`password` VARCHAR( 255 ) NULL ,
`age` INT NOT NULL DEFAULT '10',
`height` DOUBLE NOT NULL DEFAULT '10.0',
`favorite_word` VARCHAR( 255 ) NULL DEFAULT 'hi'
) ENGINE = InnoDB");
}
function test_1_5_empty_table() {
$counter = $this->mdb->queryFirstField("SELECT COUNT(*) FROM accounts");
$this->assert($counter === strval(0));
$row = $this->mdb->queryFirstRow("SELECT * FROM accounts");
$this->assert($row === null);
$field = $this->mdb->queryFirstField("SELECT * FROM accounts");
$this->assert($field === null);
$field = $this->mdb->queryOneField('nothere', "SELECT * FROM accounts");
$this->assert($field === null);
$column = $this->mdb->queryFirstColumn("SELECT * FROM accounts");
$this->assert(is_array($column) && count($column) === 0);
$column = $this->mdb->queryOneColumn('nothere', "SELECT * FROM accounts"); //TODO: is this what we want?
$this->assert(is_array($column) && count($column) === 0);
}
function test_2_insert_row() {
$this->mdb->insert('accounts', array(
'username' => 'Abe',
'password' => 'hello'
));
$this->assert($this->mdb->affectedRows() === 1);
$counter = $this->mdb->queryFirstField("SELECT COUNT(*) FROM accounts");
$this->assert($counter === strval(1));
}
function test_3_more_inserts() {
$this->mdb->insert('`accounts`', array(
'username' => 'Bart',
'password' => 'hello',
'age' => 15,
'height' => 10.371
));
$dbname = $this->mdb->dbName;
$this->mdb->insert("`$dbname`.`accounts`", array(
'username' => 'Charlie\'s Friend',
'password' => 'goodbye',
'age' => 30,
'height' => 155.23,
'favorite_word' => null,
));
$this->assert($this->mdb->insertId() === 3);
$counter = $this->mdb->queryFirstField("SELECT COUNT(*) FROM accounts");
$this->assert($counter === strval(3));
$password = $this->mdb->queryFirstField("SELECT password FROM accounts WHERE favorite_word IS NULL");
$this->assert($password === 'goodbye');
$this->mdb->param_char = '###';
$bart = $this->mdb->queryFirstRow("SELECT * FROM accounts WHERE age IN ###li AND height IN ###ld AND username IN ###ls",
array(15, 25), array(10.371, 150.123), array('Bart', 'Barts'));
$this->assert($bart['username'] === 'Bart');
$this->mdb->param_char = '%';
$charlie_password = $this->mdb->queryFirstField("SELECT password FROM accounts WHERE username IN %ls AND username = %s",
array('Charlie', 'Charlie\'s Friend'), 'Charlie\'s Friend');
$this->assert($charlie_password === 'goodbye');
$charlie_password = $this->mdb->queryOneField('password', "SELECT * FROM accounts WHERE username IN %ls AND username = %s",
array('Charlie', 'Charlie\'s Friend'), 'Charlie\'s Friend');
$this->assert($charlie_password === 'goodbye');
$passwords = $this->mdb->queryFirstColumn("SELECT password FROM accounts WHERE username=%s", 'Bart');
$this->assert(count($passwords) === 1);
$this->assert($passwords[0] === 'hello');
$username = $password = $age = null;
list($age, $username, $password) = $this->mdb->queryOneList("SELECT age,username,password FROM accounts WHERE username=%s", 'Bart');
$this->assert($username === 'Bart');
$this->assert($password === 'hello');
$this->assert($age == 15);
$mysqli_result = $this->mdb->queryRaw("SELECT * FROM accounts WHERE favorite_word IS NULL");
$this->assert($mysqli_result instanceof MySQLi_Result);
$row = $mysqli_result->fetch_assoc();
$this->assert($row['password'] === 'goodbye');
$this->assert($mysqli_result->fetch_assoc() === null);
}
function test_4_query() {
$results = $this->mdb->query("SELECT * FROM accounts WHERE username=%s", 'Charlie\'s Friend');
$this->assert(count($results) === 1);
$this->assert($results[0]['age'] == 30 && $results[0]['password'] == 'goodbye');
$results = $this->mdb->query("SELECT * FROM accounts WHERE username!=%s", "Charlie's Friend");
$this->assert(count($results) === 2);
$columnlist = $this->mdb->columnList('accounts');
$this->assert(count($columnlist) === 6);
$this->assert($columnlist[0] === 'id');
$this->assert($columnlist[4] === 'height');
$tablelist = $this->mdb->tableList();
$this->assert(count($tablelist) === 1);
$this->assert($tablelist[0] === 'accounts');
$tablelist = null;
$tablelist = $this->mdb->tableList($this->mdb->dbName);
$this->assert(count($tablelist) === 1);
$this->assert($tablelist[0] === 'accounts');
}
function test_4_1_query() {
$this->mdb->insert('accounts', array(
'username' => 'newguy',
'password' => $this->mdb->sqleval("REPEAT('blah', %i)", '3'),
'age' => $this->mdb->sqleval('171+1'),
'height' => 111.15
));
$row = $this->mdb->queryOneRow("SELECT * FROM accounts WHERE password=%s", 'blahblahblah');
$this->assert($row['username'] === 'newguy');
$this->assert($row['age'] === '172');
$this->mdb->update('accounts', array(
'password' => $this->mdb->sqleval("REPEAT('blah', %i)", 4),
'favorite_word' => null,
), 'username=%s', 'newguy');
$row = null;
$row = $this->mdb->queryOneRow("SELECT * FROM accounts WHERE username=%s", 'newguy');
$this->assert($row['password'] === 'blahblahblahblah');
$this->assert($row['favorite_word'] === null);
$this->mdb->query("DELETE FROM accounts WHERE password=%s", 'blahblahblahblah');
$this->assert($this->mdb->affectedRows() === 1);
}
function test_4_2_delete() {
$this->mdb->insert('accounts', array(
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
));
$ct = $this->mdb->queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s AND height=%d", 'gonesoon', 199.194);
$this->assert(intval($ct) === 1);
$ct = $this->mdb->queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s1 AND height=%d0 AND height=%d", 199.194, 'gonesoon');
$this->assert(intval($ct) === 1);
$this->mdb->delete('accounts', 'username=%s AND age=%i AND height=%d', 'gonesoon', '61', '199.194');
$this->assert($this->mdb->affectedRows() === 1);
$ct = $this->mdb->queryFirstField("SELECT COUNT(*) FROM accounts WHERE username=%s AND height=%d", 'gonesoon', '199.194');
$this->assert(intval($ct) === 0);
}
function test_4_3_insertmany() {
$ins[] = array(
'username' => '1ofmany',
'password' => 'something',
'age' => 23,
'height' => 190.194
);
$ins[] = array(
'password' => 'somethingelse',
'username' => '2ofmany',
'age' => 25,
'height' => 190.194
);
$this->mdb->insert('accounts', $ins);
$this->assert($this->mdb->affectedRows() === 2);
$rows = $this->mdb->query("SELECT * FROM accounts WHERE height=%d ORDER BY age ASC", 190.194);
$this->assert(count($rows) === 2);
$this->assert($rows[0]['username'] === '1ofmany');
$this->assert($rows[0]['age'] === '23');
$this->assert($rows[1]['age'] === '25');
$this->assert($rows[1]['password'] === 'somethingelse');
$this->assert($rows[1]['username'] === '2ofmany');
}
function test_5_insert_blobs() {
$this->mdb->query("CREATE TABLE `storedata` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`picture` BLOB
) ENGINE = InnoDB");
$smile = file_get_contents('smile1.jpg');
$this->mdb->insert('storedata', array(
'picture' => $smile,
));
$this->mdb->query("INSERT INTO storedata (picture) VALUES (%s)", $smile);
$getsmile = $this->mdb->queryFirstField("SELECT picture FROM storedata WHERE id=1");
$getsmile2 = $this->mdb->queryFirstField("SELECT picture FROM storedata WHERE id=2");
$this->assert($smile === $getsmile);
$this->assert($smile === $getsmile2);
}
function test_6_insert_ignore() {
$this->mdb->insertIgnore('accounts', array(
'id' => 1, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
));
}
function test_7_insert_update() {
$this->mdb->insertUpdate('accounts', array(
'id' => 2, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
), 'age = age + %i', 1);
$this->assert($this->mdb->affectedRows() === 2); // a quirk of MySQL, even though only 1 row was updated
$result = $this->mdb->query("SELECT * FROM accounts WHERE age = %i", 16);
$this->assert(count($result) === 1);
$this->assert($result[0]['height'] === '10.371');
$this->mdb->insertUpdate('accounts', array(
'id' => 2, //duplicate primary key
'username' => 'blahblahdude',
'age' => 233,
'height' => 199.194
));
$result = $this->mdb->query("SELECT * FROM accounts WHERE age = %i", 233);
$this->assert(count($result) === 1);
$this->assert($result[0]['height'] === '199.194');
$this->assert($result[0]['username'] === 'blahblahdude');
$this->mdb->insertUpdate('accounts', array(
'id' => 2, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
), array(
'age' => 74,
));
$result = $this->mdb->query("SELECT * FROM accounts WHERE age = %i", 74);
$this->assert(count($result) === 1);
$this->assert($result[0]['height'] === '199.194');
$this->assert($result[0]['username'] === 'blahblahdude');
$multiples[] = array(
'id' => 3, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
);
$multiples[] = array(
'id' => 1, //duplicate primary key
'username' => 'gonesoon',
'password' => 'something',
'age' => 61,
'height' => 199.194
);
$this->mdb->insertUpdate('accounts', $multiples, array('age' => 914));
$this->assert($this->mdb->affectedRows() === 4);
$result = $this->mdb->query("SELECT * FROM accounts WHERE age=914 ORDER BY id ASC");
$this->assert(count($result) === 2);
$this->assert($result[0]['username'] === 'Abe');
$this->assert($result[1]['username'] === 'Charlie\'s Friend');
$this->mdb->query("UPDATE accounts SET age=15, username='Bart' WHERE age=%i", 74);
$this->assert($this->mdb->affectedRows() === 1);
}
}
?>

View File

@@ -0,0 +1,30 @@
<?
class TransactionTest extends SimpleTest {
function test_1_transactions() {
DB::$nested_transactions = false;
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 600, 'Abe');
$depth = DB::startTransaction();
$this->assert($depth === 1);
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 700, 'Abe');
$depth = DB::startTransaction();
$this->assert($depth === 1);
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 800, 'Abe');
$depth = DB::rollback();
$this->assert($depth === 0);
$age = DB::queryFirstField("SELECT age FROM accounts WHERE username=%s", 'Abe');
$this->assert($age == 700);
$depth = DB::rollback();
$this->assert($depth === 0);
$age = DB::queryFirstField("SELECT age FROM accounts WHERE username=%s", 'Abe');
$this->assert($age == 700);
}
}
?>

View File

@@ -0,0 +1,85 @@
<?
class TransactionTest_55 extends SimpleTest {
function test_1_transactions() {
DB::$nested_transactions = true;
$depth = DB::startTransaction();
$this->assert($depth === 1);
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 700, 'Abe');
$depth = DB::startTransaction();
$this->assert($depth === 2);
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 800, 'Abe');
$depth = DB::startTransaction();
$this->assert($depth === 3);
$this->assert(DB::transactionDepth() === 3);
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 500, 'Abe');
$depth = DB::commit();
$this->assert($depth === 2);
$age = DB::queryFirstField("SELECT age FROM accounts WHERE username=%s", 'Abe');
$this->assert($age == 500);
$depth = DB::rollback();
$this->assert($depth === 1);
$age = DB::queryFirstField("SELECT age FROM accounts WHERE username=%s", 'Abe');
$this->assert($age == 700);
$depth = DB::commit();
$this->assert($depth === 0);
$age = DB::queryFirstField("SELECT age FROM accounts WHERE username=%s", 'Abe');
$this->assert($age == 700);
DB::$nested_transactions = false;
}
function test_2_transactions() {
DB::$nested_transactions = true;
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 600, 'Abe');
DB::startTransaction();
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 700, 'Abe');
DB::startTransaction();
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 800, 'Abe');
DB::rollback();
$age = DB::queryFirstField("SELECT age FROM accounts WHERE username=%s", 'Abe');
$this->assert($age == 700);
DB::rollback();
$age = DB::queryFirstField("SELECT age FROM accounts WHERE username=%s", 'Abe');
$this->assert($age == 600);
DB::$nested_transactions = false;
}
function test_3_transaction_rollback_all() {
DB::$nested_transactions = true;
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 200, 'Abe');
$depth = DB::startTransaction();
$this->assert($depth === 1);
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 300, 'Abe');
$depth = DB::startTransaction();
$this->assert($depth === 2);
DB::query("UPDATE accounts SET age=%i WHERE username=%s", 400, 'Abe');
$depth = DB::rollback(true);
$this->assert($depth === 0);
$age = DB::queryFirstField("SELECT age FROM accounts WHERE username=%s", 'Abe');
$this->assert($age == 200);
DB::$nested_transactions = false;
}
}
?>

View File

@@ -0,0 +1,64 @@
<?
class WhereClauseTest extends SimpleTest {
function test_1_basic_where() {
$where = new WhereClause('and');
$where->add('username=%s', 'Bart');
$where->add('password=%s', 'hello');
$result = DB::query("SELECT * FROM accounts WHERE %l", $where->text());
$this->assert(count($result) === 1);
$this->assert($result[0]['age'] === '15');
}
function test_2_simple_grouping() {
$where = new WhereClause('and');
$where->add('password=%s', 'hello');
$subclause = $where->addClause('or');
$subclause->add('age=%i', 15);
$subclause->add('age=%i', 14);
$result = DB::query("SELECT * FROM accounts WHERE %l", $where->text());
$this->assert(count($result) === 1);
$this->assert($result[0]['age'] === '15');
}
function test_3_negate_last() {
$where = new WhereClause('and');
$where->add('password=%s', 'hello');
$subclause = $where->addClause('or');
$subclause->add('username!=%s', 'Bart');
$subclause->negateLast();
$result = DB::query("SELECT * FROM accounts WHERE %l", $where->text());
$this->assert(count($result) === 1);
$this->assert($result[0]['age'] === '15');
}
function test_4_negate_last_query() {
$where = new WhereClause('and');
$where->add('password=%s', 'hello');
$subclause = $where->addClause('or');
$subclause->add('username!=%s', 'Bart');
$where->negateLast();
$result = DB::query("SELECT * FROM accounts WHERE %l", $where);
$this->assert(count($result) === 1);
$this->assert($result[0]['age'] === '15');
}
function test_5_negate() {
$where = new WhereClause('and');
$where->add('password=%s', 'hello');
$subclause = $where->addClause('or');
$subclause->add('username!=%s', 'Bart');
$subclause->negate();
$result = DB::query("SELECT * FROM accounts WHERE %l", $where);
$this->assert(count($result) === 1);
$this->assert($result[0]['age'] === '15');
}
}
?>

BIN
simpletest/smile1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -1,7 +1,7 @@
#!/usr/bin/php
<?php
class SimpleTest {
protected function assert($boolean) {
public function assert($boolean) {
if (! $boolean) $this->fail();
}
@@ -11,49 +11,76 @@ class SimpleTest {
die;
}
public static function __listfiles($dir, $regex, $type='files', $rec = false) {
$A = array();
if (! $dir_handler = @opendir($dir)) return $A;
while (false !== ($filename = @readdir($dir_handler))) {
if ($filename == '.' || $filename == '..') continue;
if ($rec && is_dir("$dir/$filename")) $A = array_merge($A, File::listfiles("$dir/$filename", $regex, $type, true));
if (! preg_match($regex, $filename)) continue;
if ($type == 'files' && ! is_file("$dir/$filename")) continue;
if ($type == 'dirs' && ! is_dir("$dir/$filename")) continue;
if ($type == 'symlinks' && ! is_link("$dir/$filename")) continue;
$A[] = $dir . DIRECTORY_SEPARATOR . $filename;
}
return $A;
}
}
$files = SimpleTest::__listfiles(dirname(__FILE__), '/^.*php$/i');
$classes_to_test = array();
foreach ($files as $fullpath) {
$filename = basename($fullpath);
if ($fullpath == __FILE__) continue;
require_once($fullpath);
$classes_to_test[] = str_replace('.php', '', $filename);
function microtime_float()
{
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
if (phpversion() >= '5.3') $is_php_53 = true;
else $is_php_53 = false;
ini_set('date.timezone', 'America/Los_Angeles');
error_reporting(E_ALL | E_STRICT);
require_once '../db.class.php';
include 'test_setup.php'; //test config values go here
DB::$user = $set_db_user;
DB::$password = $set_password;
DB::$dbName = $set_db;
DB::$host = $set_host;
DB::get(); //connect to mysql
require_once 'BasicTest.php';
require_once 'CallTest.php';
require_once 'ObjectTest.php';
require_once 'WhereClauseTest.php';
require_once 'ErrorTest.php';
require_once 'TransactionTest.php';
require_once 'HelperTest.php';
$classes_to_test = array(
'BasicTest',
'CallTest',
'WhereClauseTest',
'ObjectTest',
'ErrorTest',
'TransactionTest',
'HelperTest',
);
if ($is_php_53) {
require_once 'ErrorTest_53.php';
$classes_to_test[] = 'ErrorTest_53';
} else {
echo "PHP 5.3 not detected, skipping 5.3 tests..\n";
}
$mysql_version = DB::serverVersion();
if ($mysql_version >= '5.5') {
require_once 'TransactionTest_55.php';
$classes_to_test[] = 'TransactionTest_55';
} else {
echo "MySQL 5.5 not available (version is $mysql_version) -- skipping MySQL 5.5 tests\n";
}
$time_start = microtime_float();
foreach ($classes_to_test as $class) {
$object = new $class();
foreach (get_class_methods($object) as $method) {
if (substr($method, 0, 2) == '__') continue;
if (substr($method, 0, 4) != 'test') continue;
echo "Running $class::$method..\n";
$object->$method();
}
}
$time_end = microtime_float();
$time = round($time_end - $time_start, 2);
echo "Completed in $time seconds\n";
?>