diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c359b56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +composer.lock +vendor/* +koharness_bootstrap.php + diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..1313e37 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,18 @@ +language: php + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - hhvm + +before_script: + - composer install --prefer-dist + - vendor/bin/koharness + +script: + - cd /tmp/koharness && ./vendor/bin/phpunit --bootstrap=modules/unittest/bootstrap.php modules/unittest/tests.php + +notifications: + email: false diff --git a/README.md b/README.md new file mode 100644 index 0000000..6a40ee8 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Kohana - database access module + +| ver | Stable | Develop | +|-------|--------------------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------| +| 3.3.x | [![Build Status - 3.3/master](https://travis-ci.org/kohana/database.svg?branch=3.3%2Fmaster)](https://travis-ci.org/kohana/database) | [![Build Status - 3.3/develop](https://travis-ci.org/kohana/database.svg?branch=3.3%2Fdevelop)](https://travis-ci.org/kohana/database) | +| 3.4.x | [![Build Status - 3.4/master](https://travis-ci.org/kohana/database.svg?branch=3.4%2Fmaster)](https://travis-ci.org/kohana/database) | [![Build Status - 3.4/develop](https://travis-ci.org/kohana/database.svg?branch=3.4%2Fdevelop)](https://travis-ci.org/kohana/database) | diff --git a/classes/Kohana/Config/Database.php b/classes/Kohana/Config/Database.php index f03a201..e344761 100644 --- a/classes/Kohana/Config/Database.php +++ b/classes/Kohana/Config/Database.php @@ -9,7 +9,7 @@ * @copyright (c) 2012 Kohana Team * @license http://kohanaframework.org/license */ -class Kohana_Config_Database extends Kohana_Config_Database_Writer +class Kohana_Config_Database extends Config_Database_Writer { } diff --git a/classes/Kohana/Config/Database/Writer.php b/classes/Kohana/Config/Database/Writer.php index f6b6738..3b77851 100644 --- a/classes/Kohana/Config/Database/Writer.php +++ b/classes/Kohana/Config/Database/Writer.php @@ -3,6 +3,15 @@ /** * Database writer for the config system * + * Schema for configuration table: + * + * CREATE TABLE IF NOT EXISTS `config` ( + * `group_name` varchar(128) NOT NULL, + * `config_key` varchar(128) NOT NULL, + * `config_value` text, + * PRIMARY KEY (`group_name`,`config_key`) + * ) ENGINE=InnoDB; + * * @package Kohana * @category Configuration * @author Kohana Team diff --git a/classes/Kohana/Database/MySQL/Result.php b/classes/Kohana/Database/MySQL/Result.php index 22a5d14..8c84765 100644 --- a/classes/Kohana/Database/MySQL/Result.php +++ b/classes/Kohana/Database/MySQL/Result.php @@ -51,6 +51,9 @@ public function current() // Increment internal row for optimization assuming rows are fetched in order $this->_internal_row++; + // FIXME mysql_fetch_object has been deprecated as of php 5.5! + // Please use mysqli_fetch_object or PDOStatement::fetch(PDO::FETCH_OBJ) instead. + if ($this->_as_object === TRUE) { // Return an stdClass @@ -58,8 +61,32 @@ public function current() } elseif (is_string($this->_as_object)) { - // Return an object of given class name - return mysql_fetch_object($this->_result, $this->_as_object, $this->_object_params); + /* The second and third argument for mysql_fetch_object are optional, but do + * not have default values defined. Passing _object_params with a non-array value results + * in undefined behavior that varies by PHP version. For example, if NULL is supplied on + * PHP 5.3, the resulting behavior is identical to calling with array(), which results in the + * classes __construct function being called with no arguments. This is only an issue when + * the _as_object class does not have an explicit __construct method resulting in the + * cryptic error "Class %s does not have a constructor hence you cannot use ctor_params." + * In contrast, the same function call on PHP 5.5 will 'functionally' interpret + * _object_params == NULL as an omission of the third argument, resulting in the original + * intended functionally. + * + * Because the backing code for the mysql_fetch_object has not changed between 5.3 and 5.5, + * I suspect this discrepancy is due to the way the classes are instantiated on a boarder + * level. Additionally, mysql_fetch_object has been deprecated in 5.5 and should probably be + * replaced by mysqli_fetch_object or PDOStatement::fetch(PDO::FETCH_OBJ) in Kohana 3.4. + */ + if ($this->_object_params !== NULL) + { + // Return an object of given class name with constructor params + return mysql_fetch_object($this->_result, $this->_as_object, $this->_object_params); + } + else + { + // Return an object of given class name without constructor params + return mysql_fetch_object($this->_result, $this->_as_object); + } } else { diff --git a/classes/Kohana/Database/PDO.php b/classes/Kohana/Database/PDO.php index 573f8d3..ba6de22 100644 --- a/classes/Kohana/Database/PDO.php +++ b/classes/Kohana/Database/PDO.php @@ -60,6 +60,12 @@ public function connect() array(':error' => $e->getMessage()), $e->getCode()); } + + if ( ! empty($this->_config['charset'])) + { + // Set the character set + $this->set_charset($this->_config['charset']); + } } /** diff --git a/classes/Kohana/Database/Query/Builder.php b/classes/Kohana/Database/Query/Builder.php index 3e1bdb5..c0915dc 100644 --- a/classes/Kohana/Database/Query/Builder.php +++ b/classes/Kohana/Database/Query/Builder.php @@ -80,7 +80,7 @@ protected function _compile_conditions(Database $db, array $conditions) // Convert "val = NULL" to "val IS NULL" $op = 'IS'; } - elseif ($op === '!=') + elseif ($op === '!=' OR $op === '<>') { // Convert "val != NULL" to "valu IS NOT NULL" $op = 'IS NOT'; diff --git a/classes/Kohana/Database/Query/Builder/Insert.php b/classes/Kohana/Database/Query/Builder/Insert.php index aa3c807..8d116da 100644 --- a/classes/Kohana/Database/Query/Builder/Insert.php +++ b/classes/Kohana/Database/Query/Builder/Insert.php @@ -31,7 +31,7 @@ public function __construct($table = NULL, array $columns = NULL) if ($table) { // Set the inital table name - $this->_table = $table; + $this->table($table); } if ($columns) @@ -47,11 +47,14 @@ public function __construct($table = NULL, array $columns = NULL) /** * Sets the table to insert into. * - * @param mixed $table table name or array($table, $alias) or object + * @param string $table table name * @return $this */ public function table($table) { + if ( ! is_string($table)) + throw new Kohana_Exception('INSERT INTO syntax does not allow table aliasing'); + $this->_table = $table; return $this; diff --git a/classes/Kohana/Database/Query/Builder/Select.php b/classes/Kohana/Database/Query/Builder/Select.php index 3492a71..21da70a 100644 --- a/classes/Kohana/Database/Query/Builder/Select.php +++ b/classes/Kohana/Database/Query/Builder/Select.php @@ -309,7 +309,7 @@ public function union($select, $all = TRUE) */ public function offset($number) { - $this->_offset = $number; + $this->_offset = ($number === NULL) ? NULL : (int) $number; return $this; } @@ -404,13 +404,14 @@ public function compile($db = NULL) if ( ! empty($this->_union)) { + $query = '('.$query.')'; foreach ($this->_union as $u) { $query .= ' UNION '; if ($u['all'] === TRUE) { $query .= 'ALL '; } - $query .= $u['select']->compile($db); + $query .= '('.$u['select']->compile($db).')'; } } diff --git a/classes/Kohana/Database/Query/Builder/Where.php b/classes/Kohana/Database/Query/Builder/Where.php index 58f6b5d..a6589e4 100644 --- a/classes/Kohana/Database/Query/Builder/Where.php +++ b/classes/Kohana/Database/Query/Builder/Where.php @@ -172,7 +172,7 @@ public function order_by($column, $direction = NULL) */ public function limit($number) { - $this->_limit = $number; + $this->_limit = ($number === NULL) ? NULL : (int) $number; return $this; } diff --git a/composer.json b/composer.json index 33b1962..8a3ddd2 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,13 @@ "require": { "composer/installers": "~1.0", "kohana/core": ">=3.3", - "php": ">=5.3.3" + "php": ">=5.3.6" }, + "require-dev": { + "kohana/core": "3.3.*@dev", + "kohana/unittest": "3.3.*@dev", + "kohana/koharness": "*@dev" + }, "suggest": { "ext-mysql": "*", "ext-pdo": "*" @@ -32,6 +37,9 @@ "branch-alias": { "dev-3.3/develop": "3.3.x-dev", "dev-3.4/develop": "3.4.x-dev" - } + }, + "installer-paths": { + "vendor/{$vendor}/{$name}": ["type:kohana-module"] + } } } diff --git a/guide/database/config.md b/guide/database/config.md index 27ae9b4..0d9ecf9 100644 --- a/guide/database/config.md +++ b/guide/database/config.md @@ -10,6 +10,7 @@ The database configuration file contains an array of configuration groups. The s 'table_prefix' => string TABLE_PREFIX, 'charset' => string CHARACTER_SET, ), + Understanding each of these settings is important. @@ -17,7 +18,7 @@ INSTANCE_NAME : Connections can be named anything you want, but you should always have at least one connection called "default". DATABASE_TYPE -: One of the installed database drivers. Kohana comes with "mysql" and "pdo" drivers. Drivers must extend the Database class. +: One of the installed database drivers. Kohana comes with "MySQL" and "PDO" drivers. Drivers must extend the Database class. This parameter is case sensitive. CONNECTION_ARRAY : Specific driver options for connecting to your database. (Driver options are explained [below](#connection-settings).) @@ -49,7 +50,7 @@ The example file below shows 2 MySQL connections, one local and one remote. ( 'default' => array ( - 'type' => 'mysql', + 'type' => 'MySQL', 'connection' => array( 'hostname' => 'localhost', 'username' => 'dbuser', @@ -61,7 +62,7 @@ The example file below shows 2 MySQL connections, one local and one remote. 'charset' => 'utf8', ), 'remote' => array( - 'type' => 'mysql', + 'type' => 'MySQL', 'connection' => array( 'hostname' => '55.55.55.55', 'username' => 'remote_user', @@ -74,6 +75,8 @@ The example file below shows 2 MySQL connections, one local and one remote. ), ); +[!!] Note that the 'type' parameter is case sensitive (eg 'MySQL', 'PDO'). + ## Connections and Instances Each configuration group is referred to as a database instance. Each instance can be accessed by calling [Database::instance]. If you don't provide a parameter, the default instance is used. @@ -128,4 +131,4 @@ Type | Option | Description | Default value The connection character set should be configured using the DSN string or `options` array. -[!!] If you are using PDO and are not sure what to use for the `dsn` option, review [PDO::__construct](http://php.net/pdo.construct). \ No newline at end of file +[!!] If you are using PDO and are not sure what to use for the `dsn` option, review [PDO::__construct](http://php.net/pdo.construct). diff --git a/guide/database/examples.md b/guide/database/examples.md index 6a9d1b5..ff14ec5 100644 --- a/guide/database/examples.md +++ b/guide/database/examples.md @@ -25,7 +25,7 @@ In this example, we loop through an array of whitelisted input fields and for ea //copy the query & execute it $pagination_query = clone $query; - $count = $pagination_query->select(DB::expr('COUNT(*)) AS mycount')->execute()->get('mycount'); + $count = $pagination_query->select(DB::expr('COUNT(*) AS mycount'))->execute()->get('mycount'); //pass the total item count to Pagination $config = Kohana::$config->load('pagination'); @@ -49,4 +49,4 @@ In this example, we loop through an array of whitelisted input fields and for ea TODO: example goes here -[!!] We could use more examples on this page. \ No newline at end of file +[!!] We could use more examples on this page. diff --git a/guide/database/query/builder.md b/guide/database/query/builder.md index d2fd893..2b03b19 100644 --- a/guide/database/query/builder.md +++ b/guide/database/query/builder.md @@ -76,7 +76,7 @@ This query would generate the following SQL: Often you will want the results in a particular order and rather than sorting the results, it's better to have the results returned to you in the correct order. You can do this by using the order_by() method. It takes the column name and an optional direction string as the parameters. Multiple `order_by()` methods can be used to add additional sorting capability. - $query = DB::select()->from(`posts`)->order_by(`published`, `DESC`); + $query = DB::select()->from('posts')->order_by('published', 'DESC'); This query would generate the following SQL: @@ -248,4 +248,4 @@ Once you are done building, you can execute the query using `execute()` and use To use a different database [config group](config) pass either the name or the config object to `execute()`. - $result = $query->execute('config_name') \ No newline at end of file + $result = $query->execute('config_name') diff --git a/koharness.php b/koharness.php new file mode 100644 index 0000000..fd2366d --- /dev/null +++ b/koharness.php @@ -0,0 +1,8 @@ + array( + 'database' => __DIR__, + 'unittest' => __DIR__ . '/vendor/kohana/unittest' + ), +);