Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 8 commits
  • 19 files changed
  • 0 commit comments
  • 2 contributors
View
2  Makefile
@@ -35,7 +35,7 @@ test:
test-cover:
rm -rf tmp/test coverage
- TEST_COVERAGE=1 $(PROVE) test
+ TEST_COVERAGE=1 $(PROVE) -v test
phpcov --merge --html coverage tmp/test/coverage
rm -rf tmp/test
View
50 Modyllic/AutoLoader.php
@@ -12,30 +12,62 @@
*/
class Modyllic_AutoLoader {
- static function install() {
+ /**
+ * This calculates a new include path that includes this file's install location.
+ * If the include path already has that then it is unchanged.
+ * @returns string An include path, suitable for setting with set_include_path
+ */
+ static function get_new_include_path() {
$path = realpath( dirname(__FILE__) . DIRECTORY_SEPARATOR . ".." );
$include_path = explode(PATH_SEPARATOR,get_include_path());
- $matched = false;
if ( ! in_array($path,array_map('realpath',$include_path)) ) {
array_unshift( $include_path, $path );
- set_include_path( implode(PATH_SEPARATOR,$include_path) );
}
+ return implode(PATH_SEPARATOR,$include_path);
+ }
+
+ /**
+ * Configures the include path and installs self::autoload as an autoloader.
+ */
+ static function install() {
+ set_include_path( self::get_new_include_path() );
spl_autoload_register( array(__CLASS__,'autoload') );
}
- static function autoload($classname) {
+ /**
+ * @param string $classname
+ * @returns string Where, relative to the include paths, to find $classname on disk
+ */
+ static function class_to_filename($classname) {
$namespace = explode('\\',ltrim($classname,'\\'));
$filename = str_replace('_', DIRECTORY_SEPARATOR, array_pop($namespace)) . ".php";
- $filename = implode(DIRECTORY_SEPARATOR, array_merge($namespace,array($filename)) );
- foreach (explode(PATH_SEPARATOR,get_include_path()) as $path) {
- if ( file_exists( realpath("$path/$filename") ) ) {
- $fullpath = realpath("$path/$filename");
- break;
+ return implode(DIRECTORY_SEPARATOR, array_merge($namespace,array($filename)) );
+ }
+
+ /**
+ * @param string $filename
+ * @returns null|string The full path to $filename, or null if none exists
+ */
+ static function find_in_path($filename) {
+ foreach ( explode(PATH_SEPARATOR,get_include_path() ) as $path) {
+ $fullpath = realpath("$path/$filename");
+ if ( file_exists( $fullpath ) ) {
+ return $fullpath;
}
}
+ }
+
+ /**
+ * @param string $classname The name of the class to try to autoload
+ */
+ static function autoload($classname) {
+ $filename = self::class_to_filename($classname);
+ $fullpath = self::find_in_path($filename);
+
if ( isset($fullpath) ) {
require_once $fullpath;
}
+
return;
}
}
View
15 Modyllic/Token.php
@@ -12,16 +12,19 @@
class Modyllic_Token {
public $pos;
protected $value;
+
function __construct($pos,$value=null) {
$this->pos = $pos;
$this->value = $value;
}
+
/**
* This is exactly the string that was matched by the tokenizer
*/
function literal() {
return $this->value;
}
+
/**
* The value of the token. This differs from literal for things like
* comments, which don't include the comment markers and quoted
@@ -30,19 +33,29 @@ function literal() {
function value() {
return $this->value;
}
+
/**
* The "token" value, for any kind of identifier this is all caps.
*/
function token() {
return $this->value;
}
+
+ /**
+ * If this is a string type, this would be the unquoted value. For
+ * other types this is just the value.
+ */
+ function unquote() {
+ return $this->value;
+ }
+
/**
* The token value and class, used in debugging
*/
function debug() {
return get_class($this).":'".$this->value."'";
}
-
+
/**
* We stringify int our debug value
*/
View
6 Modyllic/Token/Num.php
@@ -9,4 +9,8 @@
/**
* Things that look like numbers
*/
-class Modyllic_Token_Num extends Modyllic_Token {}
+class Modyllic_Token_Num extends Modyllic_Token {
+ function debug() {
+ return get_class($this).":".$this->value();
+ }
+}
View
3  Modyllic/Token/String.php
@@ -56,7 +56,4 @@ function unquote() {
}
return $unquoted;
}
- function debug() {
- return get_class($this).":".$this->value();
- }
}
View
12 Modyllic/Type/Datetime.php
@@ -8,13 +8,19 @@
class Modyllic_Type_Datetime extends Modyllic_Type {
function normalize($date) {
+ assert( '! is_object($date) or $date instanceOf Modyllic_Token' );
$is_object = is_object($date);
- $value = $is_object ? $date->value() : $date;
- $unquoted = $is_object ? $date->unquote() : $date;
+ if ($is_object) {
+ $value = $date->value();
+ $unquoted = $date->unquote();
+ }
+ else {
+ $value = $unquoted = $date;
+ }
if ( $date instanceOf Modyllic_Token_Reserved or (!$is_object and Modyllic_SQL::is_reserved($value) ) ) {
return $value;
}
- if ( $value == 0 ) {
+ if ( is_numeric($value) and $value == 0 ) {
return "'0000-00-00 00:00:00'";
}
if ( $is_object and ! $date instanceOf Modyllic_Token_String ) {
View
25 test/General_Functional.t
@@ -7,9 +7,10 @@
* @author bturner@online-buddies.com
*/
-require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . "test_environment.php";
+require_once implode(DIRECTORY_SEPARATOR, array(
+ dirname(__FILE__), "test_environment.php" ));
-plan(28);
+plan(33);
$parser = new Modyllic_Parser();
@@ -86,7 +87,25 @@ if ( is_dir(dirname(__FILE__)."/test_schema") ) {
is( $loader, "Modyllic_Loader_DB", "DSN schema are loaded with DB" );
list( $source, $loader ) = Modyllic_Loader::determine_loader( dirname(__FILE__)."/test_schema/invalid" );
is( $loader, null, "Invalid schema result in no loader" );
+
+ $schema = Modyllic_Loader::load( array( dirname(__FILE__)."/test_schema/test1.sql" ) );
+ is( get_class($schema), "Modyllic_Schema", "File loaded a plain file" );
+ $schema = Modyllic_Loader::load( array( dirname(__FILE__)."/test_schema/test2.sql" ) );
+ is( get_class($schema), "Modyllic_Schema", "File loaded a symlink");
+ $schema = Modyllic_Loader::load( array( dirname(__FILE__)."/test_schema/test3/" ) );
+ is( get_class($schema), "Modyllic_Schema", "Dir loaded a directory");
+ $schema = Modyllic_Loader::load( array( dirname(__FILE__)."/test_schema/test4" ) );
+ is( get_class($schema), "Modyllic_Schema", "Dir loaded a symlink to a directory");
+ $msg = "Invalid schema throw an error";
+ try {
+ $schema = Modyllic_Loader::load( array( dirname(__FILE__)."/test_schema/invalid" ) );
+ fail($msg);
+ }
+ catch (Modyllic_Loader_Exception $e) {
+ pass($msg);
+ }
}
else {
skip("Test schema not found, not doing loader tests",6);
-}
+}
+
View
43 test/Quote.t
@@ -1,43 +0,0 @@
-#!/usr/bin/env php
-<?php
-/**
- * Copyright © 2011 Online Buddies, Inc. - All Rights Reserved
- *
- * @package Modyllic
- * @author bturner@online-buddies.com
- */
-
-require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . "test_environment.php";
-
-$ident_tests = array(
- 'abc123' => 'abc123',
- '$foo' => '$foo',
- '_bar' => '_bar',
- '0abc27' => '0abc27',
- '123' => '`123`',
- 'ABC' => 'ABC',
- 'TIME' => '`TIME`',
-);
-$str_tests = array(
- "abc" => "'abc'",
- "abc'123" => "'abc''123'",
- "ab\\%" => "'ab\\%'",
- "ab\\_" => "'ab\\_'",
- "ab\\$" => "'ab\\\\$'",
- "null".chr(0) => "'null\\0'",
- "bs".chr(8) => "'bs\\b'",
- "nl".chr(10) => "'nl\\n'",
- "cr".chr(13) => "'cr\\r'",
- "tab".chr(9) => "'tab\\t'",
- "eot".chr(26) => "'eot\\Z'",
-);
-
-plan( count($ident_tests) + count($str_tests) );
-
-foreach ($ident_tests as $plain=>$quoted) {
- is( Modyllic_SQL::quote_ident($plain), $quoted, "Identifier $plain");
-}
-
-foreach ($str_tests as $plain=>$quoted) {
- is( Modyllic_SQL::quote_str($plain), $quoted, "String $plain");
-}
View
35 test/diff/DatabaseCharset.t
@@ -0,0 +1,35 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+require_once implode( DIRECTORY_SEPARATOR, array(dirname(__FILE__), "..", "test_environment.php") );
+
+plan( 3 );
+
+$parser = new Modyllic_Parser();
+
+$schema1_sql = <<< EOSQL
+CREATE DATABASE test1 CHARSET utf8 COLLATE utf8_general_ci ;
+EOSQL;
+
+$schema2_sql = <<< EOSQL
+CREATE DATABASE test1 CHARSET latin1 COLLATE latin1_general_ci ;
+EOSQL;
+
+$schema1 = $parser->parse($schema1_sql);
+$schema2 = $parser->parse($schema2_sql);
+
+$diff = new Modyllic_Diff($schema1,$schema2);
+
+$changes = $diff->changeset();
+
+is($changes->has_changes(), true, "Changing charset and collation changes schema" );
+
+is($changes->schema->charset, 'latin1', "Changed charset to latin1");
+
+is($changes->schema->collate, 'latin1_general_ci', "And changed the collation as well");
View
36 test/diff/NewTables.t
@@ -0,0 +1,36 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+require_once implode( DIRECTORY_SEPARATOR, array(dirname(__FILE__), "..", "test_environment.php") );
+
+plan( 3 );
+
+$parser = new Modyllic_Parser();
+
+$schema1_sql = <<< EOSQL
+CREATE DATABASE test1;
+EOSQL;
+
+$schema2_sql = <<< EOSQL
+CREATE DATABASE test1;
+CREATE TABLE table1 ( id int PRIMARY KEY );
+EOSQL;
+
+$schema1 = $parser->parse($schema1_sql);
+$schema2 = $parser->parse($schema2_sql);
+
+$diff = new Modyllic_Diff($schema1,$schema2);
+
+$changes = $diff->changeset();
+
+is($changes->has_changes(), true, "Adding a table changes the schema" );
+
+is(count($changes->add['tables']), 1, "One new table found in the changeset");
+
+is(current($changes->add['tables'])->name, 'table1', "The new table is our new table");
View
53 test/diff/Routines.t
@@ -0,0 +1,53 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+require_once implode( DIRECTORY_SEPARATOR, array(dirname(__FILE__), "..", "test_environment.php") );
+
+plan( 5 );
+
+$parser = new Modyllic_Parser();
+
+$schema1_sql = <<< EOSQL
+DELIMITER ;;
+CREATE DATABASE test1 ;;
+CREATE PROCEDURE foo()
+BEGIN
+ SELECT 1;
+END ;;
+EOSQL;
+
+$schema2_sql = <<< EOSQL
+DELIMITER ;;
+CREATE DATABASE test1 ;;
+CREATE PROCEDURE foo(id INT)
+BEGIN
+ SELECT 1;
+END ;;
+CREATE PROCEDURE bar()
+BEGIN
+ SELECT 2;
+END ;;
+EOSQL;
+
+$schema1 = $parser->parse($schema1_sql);
+$schema2 = $parser->parse($schema2_sql);
+
+$diff = new Modyllic_Diff($schema1,$schema2);
+
+$changes = $diff->changeset();
+
+is($changes->has_changes(), true, "Our changeset contains changes" );
+
+is(count($changes->add['routines']), 1, "One new routine found in the changeset");
+
+is(current($changes->add['routines'])->name, 'bar', "The new routine is bar");
+
+is(count($changes->update['routines']), 1, "One updated routine found in the changeset");
+
+is(current($changes->update['routines'])->name, 'foo', "The updated routine is foo");
View
77 test/parser/Drop.t
@@ -0,0 +1,77 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+require_once implode( DIRECTORY_SEPARATOR, array(dirname(__FILE__), "..", "test_environment.php") );
+
+plan( 16 );
+
+$parser = new Modyllic_Parser();
+
+$drop1_sql = <<< EOSQL
+DELIMITER ;;
+
+CREATE DATABASE db1;;
+
+CREATE TABLE table1 (
+ col1 INT PRIMARY KEY,
+ col2 CHAR(30),
+ KEY col2 (col2)) ;;
+
+CREATE EVENT event1 ON SCHEDULE EVERY 1 YEAR DO
+BEGIN
+ SELECT 1;
+END ;;
+
+CREATE TRIGGER trigger1 BEFORE INSERT ON table1 FOR EACH ROW SET col2=col1 ;;
+
+CREATE FUNCTION routine1()
+RETURNS INT
+BEGIN
+ RETURN 1;
+END ;;
+
+CREATE PROCEDURE routine2()
+COMMENT 'routine1 comment'
+CALL routine1();;
+
+CREATE VIEW view1 AS SELECT * from table1;;
+
+EOSQL;
+
+$schema = $parser->parse($drop1_sql);
+
+ok( isset($schema->views['view1']), "We created a view" );
+$parser->partial($schema,"DROP VIEW view1");
+is( count($schema->views), 0, "We dropped a view" );
+
+ok( isset($schema->routines['routine1']), "We created a routine" );
+ok( isset($schema->routines['routine2']), "We created routine without a begin block" );
+$parser->partial($schema,"DROP PROCEDURE routine1");
+ok( ! isset($schema->routines['routine1']), "We dropped a routine" );
+
+ok( isset($schema->triggers['trigger1']), "We created a trigger" );
+$parser->partial($schema,"DROP TRIGGER trigger1");
+is( count($schema->triggers), 0, "We dropped a trigger" );
+
+ok( isset($schema->events['event1']), "We created a event" );
+$parser->partial($schema,"DROP EVENT event1");
+is( count($schema->events), 0, "We dropped a event" );
+
+ok( isset($schema->tables['table1']), "We created a table" );
+ok( isset($schema->tables['table1']->indexes["col2"]), "We created an index" );
+$parser->partial($schema,"DROP INDEX col2 ON table1");
+ok( ! isset($schema->tables['table1']->indexes["col2"]), "We dropped an index" );
+
+$parser->partial($schema,"DROP TABLE table1");
+is( count($schema->tables), 0, "We dropped a table" );
+
+is( $schema->name, 'db1', "Our database is named" );
+$parser->partial($schema,"DROP DATABASE db1" );
+is( $schema->name, 'database', "Dropping the database reset its name");
+is( count($schema->routines), 0, "Dropping the database dropped the last routine");
View
53 test/parser/Errors.t
@@ -0,0 +1,53 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+require_once implode( DIRECTORY_SEPARATOR, array(dirname(__FILE__), "..", "test_environment.php") );
+
+plan( 3 );
+
+$parser = new Modyllic_Parser();
+
+$error1_sql = <<< EOSQL
+INTEGER;
+EOSQL;
+
+$msg = "A non-command reserved word throws an exception";
+try {
+ $schema = $parser->parse($error1_sql);
+ fail($msg);
+}
+catch (Modyllic_Exception $e) {
+ like($e->getMessage(),"/Unsupported SQL command/", $msg);
+}
+
+$error2_sql = <<< EOSQL
+INVALIDXYZZY COMMAND;
+EOSQL;
+
+$msg = "A nonsense word throws an exception";
+try {
+ $schema = $parser->parse($error2_sql);
+ fail($msg);
+}
+catch (Modyllic_Exception $e) {
+ like($e->getMessage(),"/Expected reserved word, got/", $msg);
+}
+
+$error3_sql = <<< EOSQL
+CREATE DATABASE test1;
+USE test2;
+EOSQL;
+$msg = "Can't USE a different database then you CREATE";
+try {
+ $schema = $parser->parse($error3_sql);
+ fail($msg);
+}
+catch (Modyllic_Exception $e) {
+ like($e->getMessage(),"/Can't USE test2 when creating test1/", $msg);
+}
View
28 test/parser/Views.t
@@ -0,0 +1,28 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+require_once implode( DIRECTORY_SEPARATOR, array(dirname(__FILE__), "..", "test_environment.php") );
+
+plan( 3 );
+
+$parser = new Modyllic_Parser();
+
+$view1_sql = <<< EOSQL
+CREATE ALGORITHM=UNDEFINED
+ DEFINER=`abc`@`def` SQL SECURITY DEFINER
+ VIEW test AS SELECT * from foo;
+EOSQL;
+
+$schema = $parser->parse($view1_sql);
+
+ok( isset($schema->views['test']), "View created" );
+
+is( $schema->views['test']->name, 'test', "View name" );
+
+is ( $schema->views['test']->def, ' AS SELECT * from foo', "View defined" );
View
24 test/test_environment.php
@@ -24,15 +24,33 @@ function test_error_handler($code=0, $message="", $file="", $line=-1) {
// Install our auto loader
require_once implode(DIRECTORY_SEPARATOR,array(dirname(__FILE__),"..","Modyllic", "AutoLoader.php"));
-Modyllic_AutoLoader::install();
-if (getenv("TEST_COVERAGE")) {
+if ( ! defined("AUTO_SETUP_ENV") or AUTO_SETUP_ENV ) {
+ __setup_env();
+}
+
+function __setup_env() {
+ Modyllic_AutoLoader::install();
+ __begin_coverage();
+}
+
+function __begin_coverage() {
+ global $__coverage;
+ if ( isset($__coverage) ) { return; }
+ if ( ! getenv("TEST_COVERAGE") ) { return; }
+ require_once "PHP/CodeCoverage.php";
+ require_once "PHP/CodeCoverage/Driver.php";
+ require_once "PHP/CodeCoverage/Driver/Xdebug.php";
+ require_once "PHP/CodeCoverage/Filter.php";
+ require_once "PHP/CodeCoverage/Util.php";
+ require_once "File/Iterator/Facade.php";
+ require_once "File/Iterator/Factory.php";
+ require_once "File/Iterator.php";
$__coverage = new PHP_CodeCoverage;
$__coverage->start('test');
$__coverage->filter()->addDirectoryToWhitelist(realpath(dirname(__FILE__)."/../Modyllic"));
register_shutdown_function('__end_coverage');
}
-
function __end_coverage() {
global $__coverage;
$__coverage->stop();
View
66 test/unit/AutoLoader.t
@@ -0,0 +1,66 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+
+define('AUTO_SETUP_ENV', false);
+
+require_once implode(DIRECTORY_SEPARATOR, array(
+ dirname(__FILE__), '..', 'test_environment.php' ));
+
+// We have to be a little weird here in order to get coverage loaded earlier
+// without the autoloader installed.
+if (getenv("TEST_COVERAGE")) {
+ __begin_coverage();
+}
+
+plan(19);
+
+$old_include = get_include_path();
+set_include_path( dirname(__FILE__) );
+
+$new_include_path = Modyllic_AutoLoader::get_new_include_path();
+isnt( $new_include_path, get_include_path(), 'We know how to add ourselves to the include path' );
+
+is( Modyllic_AutoLoader::class_to_filename('Example'), 'Example.php', 'Simple classes' );
+is( Modyllic_AutoLoader::class_to_filename('AutoLoader_Example'), 'AutoLoader/Example.php', '<= 5.2 "namespaces"');
+is( Modyllic_AutoLoader::class_to_filename('AutoLoader_Example_Test'), 'AutoLoader/Example/Test.php', '<= 5.2 "namespaces" more then one level');
+is( Modyllic_AutoLoader::class_to_filename('\main\Example'), 'main/Example.php', '>= 5.3 namespaces');
+is( Modyllic_AutoLoader::class_to_filename('\main\test\Example'), 'main/test/Example.php', '>= 5.3 namespaces, more then one level');
+is( Modyllic_AutoLoader::class_to_filename('\main_test\Example'), 'main_test/Example.php', '>= 5.3 namespaces with underscores');
+is( Modyllic_AutoLoader::class_to_filename('\main_test\Example_Test'), 'main_test/Example/Test.php', '>= 5.3 namespaces with underscores and 5.2 style class name');
+
+
+$example_path = Modyllic_AutoLoader::find_in_path('AutoLoader/Example.php');
+ok( isset($example_path), 'We can find Example.php in our path' );
+$nosuchfile_path = Modyllic_AutoLoader::find_in_path('AutoLoader/NoSuchFile.php');
+ok( ! isset($nosuchfile_path), 'But not NoSuchFile.php' );
+
+ok( !class_exists('AutoLoader_Example',false), 'Our AutoLoader example class does not yet exist');
+Modyllic_AutoLoader::autoload('AutoLoader_Example');
+ok( class_exists('AutoLoader_Example',false), 'Our AutoLoader example class has been loaded');
+
+ok( !class_exists('AutoLoader_NoSuchFile',false), 'Our non-existant AutoLoader class does not exist');
+Modyllic_AutoLoader::autoload('AutoLoader_NoSuchFile');
+ok( !class_exists('AutoLoader_NoSuchFile',false), 'Our non-existant AutoLoader class still does not exist');
+
+set_include_path($old_include);
+
+$autoloaders = spl_autoload_functions();
+
+ok( ! $autoloaders, 'No autoloaders have yet been configured' );
+
+__setup_env();
+
+$autoloaders = spl_autoload_functions();
+
+ok( $autoloaders, 'Autoloaders exist and have been configured' );
+is( count($autoloaders), 1, 'We have exactly one autoloader' );
+
+ok( !class_exists('Modyllic_SQL',false), 'We\'ve not yet loaded Modyllic_SQL' );
+ok( class_exists('Modyllic_SQL'), 'But we can do so via our autoloader' );
View
12 test/unit/AutoLoader/Example.php
@@ -0,0 +1,12 @@
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+/**
+ * This is an example class, for testing the autoloader.
+ */
+class AutoLoader_Example {}
View
70 test/unit/SQL.t
@@ -0,0 +1,70 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+require_once implode(DIRECTORY_SEPARATOR, array(
+ dirname(__FILE__), '..', 'test_environment.php' ));
+
+$ident_tests = array(
+ 'abc123' => 'abc123',
+ '$foo' => '$foo',
+ '_bar' => '_bar',
+ '0abc27' => '0abc27',
+ '123' => '`123`',
+ 'ABC' => 'ABC',
+ 'TIME' => '`TIME`',
+);
+$str_tests = array(
+ "abc" => "'abc'",
+ "abc'123" => "'abc''123'",
+ "ab\\%" => "'ab\\%'",
+ "ab\\_" => "'ab\\_'",
+ "ab\\$" => "'ab\\\\$'",
+ "null".chr(0) => "'null\\0'",
+ "bs".chr(8) => "'bs\\b'",
+ "nl".chr(10) => "'nl\\n'",
+ "cr".chr(13) => "'cr\\r'",
+ "tab".chr(9) => "'tab\\t'",
+ "eot".chr(26) => "'eot\\Z'",
+);
+$reserved = array( "CREATE" );
+$not_reserved = array( "WIBBLE" );
+
+
+ // Unquoted identifiers are either: http://dev.mysql.com/doc/refman/5.5/en/identifiers.html
+ // An alpha+dollar+underscore followed by any number of digit+alpha+dollar+underscore
+ // OR
+ // Some number of digits followed a alpha+dollar+underscore followed by any number of digit+alpha+dollar+underscore
+$valid_ident = array( "foo", '$', '_', '$$_', 'abc123', '_789', '23$', '15_27', '42a' );
+$not_valid_ident = array( "23", '@', '!@$', 'ab&' );
+
+plan( count($ident_tests) + count($str_tests) + count($reserved) + count($not_reserved) + count($valid_ident) + count($not_valid_ident) );
+
+foreach ($ident_tests as $plain=>$quoted) {
+ is( Modyllic_SQL::quote_ident($plain), $quoted, "Identifier $plain");
+}
+
+foreach ($str_tests as $plain=>$quoted) {
+ is( Modyllic_SQL::quote_str($plain), $quoted, "String $plain");
+}
+
+foreach ($reserved as $word ) {
+ ok( Modyllic_SQL::is_reserved($word), "$word is a reserved word" );
+}
+
+foreach ($not_reserved as $word ) {
+ ok( ! Modyllic_SQL::is_reserved($word), "$word is not a reserved word" );
+}
+
+foreach ($valid_ident as $ident) {
+ ok( Modyllic_SQL::valid_ident($ident), "$ident is a valid identifier name" );
+}
+
+foreach ($not_valid_ident as $ident) {
+ ok( ! Modyllic_SQL::valid_ident($ident), "$ident is not a valid identifier name" );
+}
View
76 test/unit/Type/DateTime.t
@@ -0,0 +1,76 @@
+#!/usr/bin/env php
+<?php
+/**
+ * Copyright © 2012 Online Buddies, Inc. - All Rights Reserved
+ *
+ * @package Modyllic
+ * @author bturner@online-buddies.com
+ */
+
+require_once implode(DIRECTORY_SEPARATOR, array(
+ dirname(__FILE__), '..', '..', 'test_environment.php' ));
+
+$normalization_tests = array(
+ array( "CURRENT_TIME", new Modyllic_Token_Reserved(0,"CURRENT_TIME"), "CURRENT_TIME" ),
+ array( 0, new Modyllic_Token_Num(0,0), "'0000-00-00 00:00:00'" ),
+ array( "0", null, "'0000-00-00 00:00:00'" ),
+ array( "2012-01-01", new Modyllic_Token_String(0,"'2012-01-01'"), "'2012-01-01 00:00:00'" ),
+ array( "2012-1-1", new Modyllic_Token_String(0,"'2012-1-1'"), "'2012-01-01 00:00:00'" ),
+ array( "5-1-1", new Modyllic_Token_String(0,"'5-1-1'"), "'0005-01-01 00:00:00'" ),
+ array( "2012-01-01 7", new Modyllic_Token_String(0,"'2012-01-01 7'"), "'2012-01-01 07:00:00'" ),
+ array( "2012-01-01 7:1", new Modyllic_Token_String(0,"'2012-01-01 7:1'"), "'2012-01-01 07:01:00'" ),
+ array( "2012-01-01 7:1:8", new Modyllic_Token_String(0,"'2012-01-01 7:1:8'"), "'2012-01-01 07:01:08'" ),
+ array( "2012-01-01 07:01:08", new Modyllic_Token_String(0,"'2012-01-01 07:01:08'"), "'2012-01-01 07:01:08'" ),
+ );
+
+$invalid_date_tests = array(
+ new Modyllic_Token_String(0,"'0'"),
+ new Modyllic_Token_Num(0,"1.0"),
+ 5,
+ "7",
+ new Modyllic_Token_String(0,"'0.1'"),
+ "2012-01-01T07:01:08",
+ new Modyllic_Token_String(0,"'2012-01-01T07:01:08'"),
+ "2012-01",
+ new Modyllic_Token_String(0,"'2012-01'"),
+ "asdlkjfd",
+ new Modyllic_Token_Ident(0, "abc"),
+ );
+
+plan( count($invalid_date_tests) + (2*count($normalization_tests)) + 6 );
+
+$datetype1 = Modyllic_Type::create("DATETIME");
+$datetype2 = Modyllic_Type::create("DATETIME");
+$strtype = Modyllic_Type::create("CHAR");
+$strtype->length = 17;
+
+is( $datetype1->to_sql(), "DATETIME", "to_sql" );
+ok( $datetype2->equal_to($datetype2), "equal_to" );
+ok( ! $datetype2->equal_to($strtype), "! equal_to" );
+ok( $datetype1->isa_equivalent($datetype2), "isa_equivalent" );
+ok( ! $datetype1->isa_equivalent($strtype), "! isa_equivalent" );
+ok( $datetype1->is_valid(), "is_valid" );
+
+foreach ($normalization_tests as $test) {
+ list($value, $token, $expected) = $test;
+ is($datetype1->normalize($value), $expected, "Normalize a literal $value");
+ if ( isset($token) ) {
+ is($datetype1->normalize($token), $expected, "Normalize a $token");
+ }
+ else {
+ ok(true, "#");
+ }
+
+}
+
+foreach ($invalid_date_tests as $test) {
+ $msg = "Trying to normalize a ". (is_object($test)?"$test":"literal $test"). " should fail";
+ try {
+ $normalized = $datetype1->normalize($test);
+ fail($msg);
+ }
+ catch (Exception $e) {
+ pass($msg);
+ }
+}
+

No commit comments for this range

Something went wrong with that request. Please try again.