/**
  * Perform migration
  *
  * @param string $base Absolute base path (parent of assets folder). Will default to BASE_PATH
  * @return int Number of files successfully migrated
  */
 public function run($base = null)
 {
     if (empty($base)) {
         $base = BASE_PATH;
     }
     // Check if the File dataobject has a "Filename" field.
     // If not, cannot migrate
     /** @skipUpgrade */
     if (!DB::get_schema()->hasField('File', 'Filename')) {
         return 0;
     }
     // Set max time and memory limit
     increase_time_limit_to();
     increase_memory_limit_to();
     // Loop over all files
     $count = 0;
     $originalState = Versioned::get_reading_mode();
     Versioned::set_stage(Versioned::DRAFT);
     $filenameMap = $this->getFilenameArray();
     foreach ($this->getFileQuery() as $file) {
         // Get the name of the file to import
         $filename = $filenameMap[$file->ID];
         $success = $this->migrateFile($base, $file, $filename);
         if ($success) {
             $count++;
         }
     }
     Versioned::set_reading_mode($originalState);
     return $count;
 }
 public function testFilter()
 {
     if (DB::get_conn() instanceof MySQLDatabase) {
         $baseQuery = FulltextFilterTest_DataObject::get();
         $this->assertEquals(3, $baseQuery->count(), "FulltextFilterTest_DataObject count does not match.");
         // First we'll text the 'SearchFields' which has been set using an array
         $search = $baseQuery->filter("SearchFields:fulltext", 'SilverStripe');
         $this->assertEquals(1, $search->count());
         $search = $baseQuery->exclude("SearchFields:fulltext", "SilverStripe");
         $this->assertEquals(2, $search->count());
         // Now we'll run the same tests on 'OtherSearchFields' which should yield the same resutls
         // but has been set using a string.
         $search = $baseQuery->filter("OtherSearchFields:fulltext", 'SilverStripe');
         $this->assertEquals(1, $search->count());
         $search = $baseQuery->exclude("OtherSearchFields:fulltext", "SilverStripe");
         $this->assertEquals(2, $search->count());
         // Search on a single field
         $search = $baseQuery->filter("ColumnE:fulltext", 'Dragons');
         $this->assertEquals(1, $search->count());
         $search = $baseQuery->exclude("ColumnE:fulltext", "Dragons");
         $this->assertEquals(2, $search->count());
     } else {
         $this->markTestSkipped("FulltextFilter only supports MySQL syntax.");
     }
 }
 public function testMultipleRowInsert()
 {
     $query = SQLInsert::create('"SQLInsertTestBase"');
     $query->addRow(array('"Title"' => 'First Object', '"Age"' => 10, '"Description"' => 'First the worst'));
     $query->addRow(array('"Title"' => 'Second object', '"Age"' => 12));
     $sql = $query->sql($parameters);
     // Only test this case if using the default query builder
     if (get_class(DB::get_conn()->getQueryBuilder()) === 'SilverStripe\\ORM\\Connect\\DBQueryBuilder') {
         $this->assertSQLEquals('INSERT INTO "SQLInsertTestBase" ("Title", "Age", "Description") VALUES (?, ?, ?), (?, ?, ?)', $sql);
     }
     $this->assertEquals(array('First Object', 10, 'First the worst', 'Second object', 12, null), $parameters);
     $query->execute();
     $this->assertEquals(2, DB::affected_rows());
     // Check inserted objects are correct
     $firstObject = DataObject::get_one('SQLInsertTestBase', array('"Title"' => 'First Object'), false);
     $this->assertNotEmpty($firstObject);
     $this->assertEquals($firstObject->Title, 'First Object');
     $this->assertEquals($firstObject->Age, 10);
     $this->assertEquals($firstObject->Description, 'First the worst');
     $secondObject = DataObject::get_one('SQLInsertTestBase', array('"Title"' => 'Second object'), false);
     $this->assertNotEmpty($secondObject);
     $this->assertEquals($secondObject->Title, 'Second object');
     $this->assertEquals($secondObject->Age, 12);
     $this->assertEmpty($secondObject->Description);
 }
 public function testCreateWithTransaction()
 {
     if (DB::get_conn()->supportsTransactions() == true) {
         DB::get_conn()->transactionStart();
         $obj = new TransactionTest_Object();
         $obj->Title = 'First page';
         $obj->write();
         $obj = new TransactionTest_Object();
         $obj->Title = 'Second page';
         $obj->write();
         //Create a savepoint here:
         DB::get_conn()->transactionSavepoint('rollback');
         $obj = new TransactionTest_Object();
         $obj->Title = 'Third page';
         $obj->write();
         $obj = new TransactionTest_Object();
         $obj->Title = 'Fourth page';
         $obj->write();
         //Revert to a savepoint:
         DB::get_conn()->transactionRollback('rollback');
         DB::get_conn()->transactionEnd();
         $first = DataObject::get('TransactionTest_Object', "\"Title\"='First page'");
         $second = DataObject::get('TransactionTest_Object', "\"Title\"='Second page'");
         $third = DataObject::get('TransactionTest_Object', "\"Title\"='Third page'");
         $fourth = DataObject::get('TransactionTest_Object', "\"Title\"='Fourth page'");
         //These pages should be in the system
         $this->assertTrue(is_object($first) && $first->exists());
         $this->assertTrue(is_object($second) && $second->exists());
         //These pages should NOT exist, we reverted to a savepoint:
         $this->assertFalse(is_object($third) && $third->exists());
         $this->assertFalse(is_object($fourth) && $fourth->exists());
     } else {
         $this->markTestSkipped('Current database does not support transactions');
     }
 }
 /**
  * (non-PHPdoc)
  * @see DBField::requireField()
  */
 public function requireField()
 {
     $charset = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'charset');
     $collation = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'collation');
     $parts = array('datatype' => 'varchar', 'precision' => $this->size, 'character set' => $charset, 'collate' => $collation, 'arrayValue' => $this->arrayValue);
     $values = array('type' => 'varchar', 'parts' => $parts);
     DB::require_field($this->tableName, $this->name, $values);
 }
 public function requireField()
 {
     // @todo: Remove mysql-centric logic from this
     $charset = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'charset');
     $collation = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'collation');
     $values = array('type' => 'set', 'parts' => array('enums' => $this->enum, 'character set' => $charset, 'collate' => $collation, 'default' => $this->default, 'table' => $this->tableName, 'arrayValue' => $this->arrayValue));
     DB::require_field($this->tableName, $this->name, $values);
 }
 /**
  * (non-PHPdoc)
  * @see DBField::requireField()
  */
 public function requireField()
 {
     $charset = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'charset');
     $collation = Config::inst()->get('SilverStripe\\ORM\\Connect\\MySQLDatabase', 'collation');
     $parts = ['datatype' => 'mediumtext', 'character set' => $charset, 'collate' => $collation, 'default' => $this->defaultVal, 'arrayValue' => $this->arrayValue];
     $values = ['type' => 'text', 'parts' => $parts];
     DB::require_field($this->tableName, $this->name, $values);
 }
 public function testTablesAreCreated()
 {
     $tables = DB::table_list();
     $check = array('versionableextensionstest_dataobject_test1_live', 'versionableextensionstest_dataobject_test2_live', 'versionableextensionstest_dataobject_test3_live', 'versionableextensionstest_dataobject_test1_versions', 'versionableextensionstest_dataobject_test2_versions', 'versionableextensionstest_dataobject_test3_versions');
     // Check that the right tables exist
     foreach ($check as $tableName) {
         $this->assertContains($tableName, array_keys($tables), 'Contains table: ' . $tableName);
     }
 }
 public function run($request)
 {
     $migrated = FileMigrationHelper::singleton()->run();
     if ($migrated) {
         DB::alteration_message("{$migrated} File DataObjects upgraded", "changed");
     } else {
         DB::alteration_message("No File DataObjects need upgrading", "notice");
     }
 }
 public function requireField()
 {
     // HACK: MSSQL does not support double so we're using float instead
     // @todo This should go into MSSQLDatabase ideally somehow
     if (DB::get_conn() instanceof MySQLDatabase) {
         DB::require_field($this->tableName, $this->name, "double");
     } else {
         DB::require_field($this->tableName, $this->name, "float");
     }
 }
 public function conditionSQL(&$parameters)
 {
     $parameters = array();
     // Ignore empty conditions
     $where = $this->whereQuery->getWhere();
     if (empty($where)) {
         return null;
     }
     // Allow database to manage joining of conditions
     $sql = DB::get_conn()->getQueryBuilder()->buildWhereFragment($this->whereQuery, $parameters);
     return preg_replace('/^\\s*WHERE\\s*/i', '', $sql);
 }
 function testValidAlternativeDatabaseName()
 {
     $prefix = defined('SS_DATABASE_PREFIX') ? SS_DATABASE_PREFIX : 'ss_';
     Config::inst()->update('SilverStripe\\Control\\Director', 'environment_type', 'dev');
     $this->assertTrue(DB::valid_alternative_database_name($prefix . 'tmpdb1234567'));
     $this->assertFalse(DB::valid_alternative_database_name($prefix . 'tmpdb12345678'));
     $this->assertFalse(DB::valid_alternative_database_name('tmpdb1234567'));
     $this->assertFalse(DB::valid_alternative_database_name('random'));
     $this->assertFalse(DB::valid_alternative_database_name(''));
     Config::inst()->update('SilverStripe\\Control\\Director', 'environment_type', 'live');
     $this->assertFalse(DB::valid_alternative_database_name($prefix . 'tmpdb1234567'));
     Config::inst()->update('SilverStripe\\Control\\Director', 'environment_type', 'dev');
 }
 /**
  * Returns the manifest of all classes which are present in the database.
  *
  * @param string $class Class name to check enum values for ClassName field
  * @param boolean $includeUnbacked Flag indicating whether or not to include
  * types that don't exist as implemented classes. By default these are excluded.
  * @return array List of subclasses
  */
 public static function getValidSubClasses($class = 'SilverStripe\\CMS\\Model\\SiteTree', $includeUnbacked = false)
 {
     if (is_string($class) && !class_exists($class)) {
         return array();
     }
     $class = self::class_name($class);
     if ($includeUnbacked) {
         $table = DataObject::getSchema()->tableName($class);
         $classes = DB::get_schema()->enumValuesForField($table, 'ClassName');
     } else {
         $classes = static::subclassesFor($class);
     }
     return $classes;
 }
 protected function excludeMany(DataQuery $query)
 {
     $this->model = $query->applyRelation($this->relation);
     $values = $this->getValue();
     $comparisonClause = DB::get_conn()->comparisonClause($this->getDbName(), null, false, true, $this->getCaseSensitive(), true);
     $parameters = array();
     foreach ($values as $value) {
         $parameters[] = $this->getMatchPattern($value);
     }
     // Since query connective is ambiguous, use AND explicitly here
     $count = count($values);
     $predicate = implode(' AND ', array_fill(0, $count, $comparisonClause));
     return $query->where(array($predicate => $parameters));
 }
 public function testBasicUpdate()
 {
     $query = SQLUpdate::create()->setTable('"SQLUpdateTestBase"')->assign('"Description"', 'Description 1a')->addWhere(array('"Title" = ?' => 'Object 1'));
     $sql = $query->sql($parameters);
     // Check SQL
     $this->assertSQLEquals('UPDATE "SQLUpdateTestBase" SET "Description" = ? WHERE ("Title" = ?)', $sql);
     $this->assertEquals(array('Description 1a', 'Object 1'), $parameters);
     // Check affected rows
     $query->execute();
     $this->assertEquals(1, DB::affected_rows());
     // Check item updated
     $item = DataObject::get_one('SQLUpdateTestBase', array('"Title"' => 'Object 1'));
     $this->assertEquals('Description 1a', $item->Description);
 }
 protected function foreignIDFilter($id = null)
 {
     if ($id === null) {
         $id = $this->getForeignID();
     }
     // Apply relation filter
     $key = DataObject::getSchema()->sqlColumnForField($this->dataClass(), $this->getForeignKey());
     if (is_array($id)) {
         return array("{$key} IN (" . DB::placeholders($id) . ")" => $id);
     } else {
         if ($id !== null) {
             return array($key => $id);
         }
     }
     return null;
 }
 public function testAffectedRows()
 {
     if (!DB::get_connector() instanceof PDOConnector) {
         $this->markTestSkipped('This test requires the current DB connector is PDO');
     }
     $query = new SQLUpdate('MySQLDatabaseTest_Data');
     $query->setAssignments(array('Title' => 'New Title'));
     // Test update which affects no rows
     $query->setWhere(array('Title' => 'Bob'));
     $result = $query->execute();
     $this->assertInstanceOf('SilverStripe\\ORM\\Connect\\PDOQuery', $result);
     $this->assertEquals(0, DB::affected_rows());
     // Test update which affects some rows
     $query->setWhere(array('Title' => 'First Item'));
     $result = $query->execute();
     $this->assertInstanceOf('SilverStripe\\ORM\\Connect\\PDOQuery', $result);
     $this->assertEquals(1, DB::affected_rows());
 }
 /**
  * Link this group set to a specific member.
  *
  * Recursively selects all groups applied to this member, as well as any
  * parent groups of any applied groups
  *
  * @param array|integer $id (optional) An ID or an array of IDs - if not provided, will use the current
  * ids as per getForeignID
  * @return array Condition In array(SQL => parameters format)
  */
 public function foreignIDFilter($id = null)
 {
     if ($id === null) {
         $id = $this->getForeignID();
     }
     // Find directly applied groups
     $manyManyFilter = parent::foreignIDFilter($id);
     $query = new SQLSelect('"Group_Members"."GroupID"', '"Group_Members"', $manyManyFilter);
     $groupIDs = $query->execute()->column();
     // Get all ancestors, iteratively merging these into the master set
     $allGroupIDs = array();
     while ($groupIDs) {
         $allGroupIDs = array_merge($allGroupIDs, $groupIDs);
         $groupIDs = DataObject::get("SilverStripe\\Security\\Group")->byIDs($groupIDs)->column("ParentID");
         $groupIDs = array_filter($groupIDs);
     }
     // Add a filter to this DataList
     if (!empty($allGroupIDs)) {
         $allGroupIDsPlaceholders = DB::placeholders($allGroupIDs);
         return array("\"Group\".\"ID\" IN ({$allGroupIDsPlaceholders})" => $allGroupIDs);
     } else {
         return array('"Group"."ID"' => 0);
     }
 }
 protected function overrideField($obj, $fieldName, $value, $fixtures = null)
 {
     $class = get_class($obj);
     $table = DataObject::getSchema()->tableForField($class, $fieldName);
     $value = $this->parseValue($value, $fixtures);
     DB::manipulate(array($table => array("command" => "update", "id" => $obj->ID, "class" => $class, "fields" => array($fieldName => $value))));
     $obj->{$fieldName} = $value;
 }
 public function requireField()
 {
     $parts = array('datatype' => 'tinyint', 'precision' => 1, 'sign' => 'unsigned', 'null' => 'not null', 'default' => $this->defaultVal, 'arrayValue' => $this->arrayValue);
     $values = array('type' => 'boolean', 'parts' => $parts);
     DB::require_field($this->tableName, $this->name, $values);
 }
 /**
  * Add default records to database. This function is called whenever the
  * database is built, after the database tables have all been created. Overload
  * this to add default records when the database is built, but make sure you
  * call parent::requireDefaultRecords().
  *
  * @uses DataExtension->requireDefaultRecords()
  */
 public function requireDefaultRecords()
 {
     $defaultRecords = $this->stat('default_records');
     if (!empty($defaultRecords)) {
         $hasData = DataObject::get_one($this->class);
         if (!$hasData) {
             $className = $this->class;
             foreach ($defaultRecords as $record) {
                 $obj = $this->model->{$className}->newObject($record);
                 $obj->write();
             }
             DB::alteration_message("Added default records to {$className} table", "created");
         }
     }
     // Let any extentions make their own database default data
     $this->extend('requireDefaultRecords', $dummy);
 }
Example #22
0
require_once 'core/startup/ErrorControlChain.php';
require_once 'core/startup/ParameterConfirmationToken.php';
// Prepare tokens and execute chain
$reloadToken = ParameterConfirmationToken::prepare_tokens(array('isTest', 'isDev', 'flush'));
$chain = new ErrorControlChain();
$chain->then(function ($chain) use($reloadToken) {
    // If no redirection is necessary then we can disable error supression
    if (!$reloadToken) {
        $chain->setSuppression(false);
    }
    // Load in core
    require_once 'core/Core.php';
    // Connect to database
    global $databaseConfig;
    if ($databaseConfig) {
        DB::connect($databaseConfig);
    }
    // Check if a token is requesting a redirect
    if (!$reloadToken) {
        return;
    }
    // Otherwise, we start up the session if needed
    if (!isset($_SESSION) && Session::request_contains_session_id()) {
        Session::start();
    }
    // Next, check if we're in dev mode, or the database doesn't have any security data, or we are admin
    if (Director::isDev() || !Security::database_is_ready() || Permission::check('ADMIN')) {
        return $reloadToken->reloadWithToken();
    }
    // Fail and redirect the user to the login page
    $loginPage = Director::absoluteURL(Security::config()->login_url);
 public function testTransactions()
 {
     $conn = DB::get_conn();
     if (!$conn->supportsTransactions()) {
         $this->markTestSkipped("DB Doesn't support transactions");
         return;
     }
     // Test that successful transactions are comitted
     $obj = new DatabaseTest_MyObject();
     $failed = false;
     $conn->withTransaction(function () use(&$obj) {
         $obj->MyField = 'Save 1';
         $obj->write();
     }, function () use(&$failed) {
         $failed = true;
     });
     $this->assertEquals('Save 1', DatabaseTest_MyObject::get()->first()->MyField);
     $this->assertFalse($failed);
     // Test failed transactions are rolled back
     $ex = null;
     $failed = false;
     try {
         $conn->withTransaction(function () use(&$obj) {
             $obj->MyField = 'Save 2';
             $obj->write();
             throw new Exception("error");
         }, function () use(&$failed) {
             $failed = true;
         });
     } catch (Exception $ex) {
     }
     $this->assertTrue($failed);
     $this->assertEquals('Save 1', DatabaseTest_MyObject::get()->first()->MyField);
     $this->assertInstanceOf('Exception', $ex);
     $this->assertEquals('error', $ex->getMessage());
 }
 /**
  * Get the list of classnames, including obsolete classes.
  *
  * If table or name are not set, or if it is not a valid field on the given table,
  * then only known classnames are returned.
  *
  * Values cached in this method can be cleared via `DBClassName::clear_classname_cache();`
  *
  * @return array
  */
 public function getEnumObsolete()
 {
     // Without a table or field specified, we can only retrieve known classes
     $table = $this->getTable();
     $name = $this->getName();
     if (empty($table) || empty($name)) {
         return $this->getEnum();
     }
     // Ensure the table level cache exists
     if (empty(self::$classname_cache[$table])) {
         self::$classname_cache[$table] = array();
     }
     // Check existing cache
     if (!empty(self::$classname_cache[$table][$name])) {
         return self::$classname_cache[$table][$name];
     }
     // Get all class names
     $classNames = $this->getEnum();
     if (DB::get_schema()->hasField($table, $name)) {
         $existing = DB::query("SELECT DISTINCT \"{$name}\" FROM \"{$table}\"")->column();
         $classNames = array_unique(array_merge($classNames, $existing));
     }
     // Cache and return
     self::$classname_cache[$table][$name] = $classNames;
     return $classNames;
 }
 /**
  * Reset the testing database's schema.
  * @param $includeExtraDataObjects If true, the extraDataObjects tables will also be included
  */
 public function resetDBSchema($includeExtraDataObjects = false)
 {
     if (self::using_temp_db()) {
         DataObject::reset();
         // clear singletons, they're caching old extension info which is used in DatabaseAdmin->doBuild()
         Injector::inst()->unregisterAllObjects();
         $dataClasses = ClassInfo::subclassesFor('SilverStripe\\ORM\\DataObject');
         array_shift($dataClasses);
         DB::quiet();
         $schema = DB::get_schema();
         $extraDataObjects = $includeExtraDataObjects ? $this->extraDataObjects : null;
         $schema->schemaUpdate(function () use($dataClasses, $extraDataObjects) {
             foreach ($dataClasses as $dataClass) {
                 // Check if class exists before trying to instantiate - this sidesteps any manifest weirdness
                 if (class_exists($dataClass)) {
                     $SNG = singleton($dataClass);
                     if (!$SNG instanceof TestOnly) {
                         $SNG->requireTable();
                     }
                 }
             }
             // If we have additional dataobjects which need schema, do so here:
             if ($extraDataObjects) {
                 foreach ($extraDataObjects as $dataClass) {
                     $SNG = singleton($dataClass);
                     if (singleton($dataClass) instanceof DataObject) {
                         $SNG->requireTable();
                     }
                 }
             }
         });
         ClassInfo::reset_db_cache();
         singleton('SilverStripe\\ORM\\DataObject')->flushCache();
     }
 }
 public function testFilterByNull()
 {
     $list = DataObjectTest_Fan::get();
     // Force DataObjectTest_Fan/fan5::Email to empty string
     $fan5id = $this->idFromFixture('DataObjectTest_Fan', 'fan5');
     DB::prepared_query("UPDATE \"DataObjectTest_Fan\" SET \"Email\" = '' WHERE \"ID\" = ?", array($fan5id));
     // Filter by null email
     $nullEmails = $list->filter('Email', null);
     $this->assertDOSEquals(array(array('Name' => 'Stephen'), array('Name' => 'Mitch')), $nullEmails);
     // Filter by non-null
     $nonNullEmails = $list->filter('Email:not', null);
     $this->assertDOSEquals(array(array('Name' => 'Damian', 'Email' => '*****@*****.**'), array('Name' => 'Richard', 'Email' => '*****@*****.**'), array('Name' => 'Hamish')), $nonNullEmails);
     // Filter by empty only
     $emptyOnly = $list->filter('Email', '');
     $this->assertDOSEquals(array(array('Name' => 'Hamish')), $emptyOnly);
     // Non-empty only. This should include null values, since ExactMatchFilter works around
     // the caveat that != '' also excludes null values in ANSI SQL-92 behaviour.
     $nonEmptyOnly = $list->filter('Email:not', '');
     $this->assertDOSEquals(array(array('Name' => 'Damian', 'Email' => '*****@*****.**'), array('Name' => 'Richard', 'Email' => '*****@*****.**'), array('Name' => 'Stephen'), array('Name' => 'Mitch')), $nonEmptyOnly);
     // Filter by many including null, empty string, and non-empty
     $items1 = $list->filter('Email', array(null, '', '*****@*****.**'));
     $this->assertDOSEquals(array(array('Name' => 'Damian', 'Email' => '*****@*****.**'), array('Name' => 'Stephen'), array('Name' => 'Mitch'), array('Name' => 'Hamish')), $items1);
     // Filter exclusion of above list
     $items2 = $list->filter('Email:not', array(null, '', '*****@*****.**'));
     $this->assertDOSEquals(array(array('Name' => 'Richard', 'Email' => '*****@*****.**')), $items2);
     // Filter by many including empty string and non-empty
     $items3 = $list->filter('Email', array('', '*****@*****.**'));
     $this->assertDOSEquals(array(array('Name' => 'Damian', 'Email' => '*****@*****.**'), array('Name' => 'Hamish')), $items3);
     // Filter by many including empty string and non-empty
     // This also relies no the workaround for null comparison as in the $nonEmptyOnly test
     $items4 = $list->filter('Email:not', array('', '*****@*****.**'));
     $this->assertDOSEquals(array(array('Name' => 'Richard', 'Email' => '*****@*****.**'), array('Name' => 'Stephen'), array('Name' => 'Mitch')), $items4);
     // Filter by many including empty string and non-empty
     // The extra null check isn't necessary, but check that this doesn't fail
     $items5 = $list->filterAny(array('Email:not' => array('', '*****@*****.**'), 'Email' => null));
     $this->assertDOSEquals(array(array('Name' => 'Richard', 'Email' => '*****@*****.**'), array('Name' => 'Stephen'), array('Name' => 'Mitch')), $items5);
     // Filter by null or empty values
     $items6 = $list->filter('Email', array(null, ''));
     $this->assertDOSEquals(array(array('Name' => 'Stephen'), array('Name' => 'Mitch'), array('Name' => 'Hamish')), $items6);
 }
 public function requireField()
 {
     $parts = array('datatype' => 'time', 'arrayValue' => $this->arrayValue);
     $values = array('type' => 'time', 'parts' => $parts);
     DB::require_field($this->tableName, $this->name, $values);
 }
 /**
  * Writes the fixture into the database directly using a database manipulation.
  * Does not use blueprints. Only supports tables with a primary key.
  *
  * @param String $table Existing database table name
  * @param String $identifier Unique identifier for this fixture type
  * @param Array $data Map of properties
  * @return Int Database identifier
  */
 public function createRaw($table, $identifier, $data)
 {
     $fields = array();
     foreach ($data as $fieldName => $fieldVal) {
         $fields["\"{$fieldName}\""] = $this->parseValue($fieldVal);
     }
     $insert = new SQLInsert("\"{$table}\"", $fields);
     $insert->execute();
     $id = DB::get_generated_id($table);
     $this->fixtures[$table][$identifier] = $id;
     return $id;
 }
 public function requireField()
 {
     $parts = array('datatype' => 'float', 'null' => 'not null', 'default' => $this->defaultVal, 'arrayValue' => $this->arrayValue);
     $values = array('type' => 'float', 'parts' => $parts);
     DB::require_field($this->tableName, $this->name, $values);
 }
 /**
  * Applies matches for several values, either as inclusive or exclusive
  *
  * @param DataQuery $query
  * @param bool $inclusive True if this is inclusive, or false if exclusive
  * @return DataQuery
  */
 protected function manyFilter(DataQuery $query, $inclusive)
 {
     $this->model = $query->applyRelation($this->relation);
     $caseSensitive = $this->getCaseSensitive();
     // Check values for null
     $field = $this->getDbName();
     $values = $this->getValue();
     if (empty($values)) {
         throw new \InvalidArgumentException("Cannot filter {$field} against an empty set");
     }
     $hasNull = in_array(null, $values, true);
     if ($hasNull) {
         $values = array_filter($values, function ($value) {
             return $value !== null;
         });
     }
     $connective = '';
     if (empty($values)) {
         $predicate = '';
     } elseif ($caseSensitive === null) {
         // For queries using the default collation (no explicit case) we can use the WHERE .. NOT IN .. syntax,
         // providing simpler SQL than many WHERE .. AND .. fragments.
         $column = $this->getDbName();
         $placeholders = DB::placeholders($values);
         if ($inclusive) {
             $predicate = "{$column} IN ({$placeholders})";
         } else {
             $predicate = "{$column} NOT IN ({$placeholders})";
         }
     } else {
         // Generate reusable comparison clause
         $comparisonClause = DB::get_conn()->comparisonClause($this->getDbName(), null, true, !$inclusive, $this->getCaseSensitive(), true);
         $count = count($values);
         if ($count > 1) {
             $connective = $inclusive ? ' OR ' : ' AND ';
             $conditions = array_fill(0, $count, $comparisonClause);
             $predicate = implode($connective, $conditions);
         } else {
             $predicate = $comparisonClause;
         }
     }
     // Always check for null when doing exclusive checks (either AND IS NOT NULL / OR IS NULL)
     // or when including the null value explicitly (OR IS NULL)
     if ($hasNull || !$inclusive) {
         // If excluding values which don't include null, or including
         // values which include null, we should do an `OR IS NULL`.
         // Otherwise we are excluding values that do include null, so `AND IS NOT NULL`.
         // Simplified from (!$inclusive && !$hasNull) || ($inclusive && $hasNull);
         $isNull = !$hasNull || $inclusive;
         $nullCondition = DB::get_conn()->nullCheckClause($field, $isNull);
         // Determine merge strategy
         if (empty($predicate)) {
             $predicate = $nullCondition;
         } else {
             // Merge null condition with predicate
             if ($isNull) {
                 $nullCondition = " OR {$nullCondition}";
             } else {
                 $nullCondition = " AND {$nullCondition}";
             }
             // If current predicate connective doesn't match the same as the null connective
             // make sure to group the prior condition
             if ($connective && ($connective === ' OR ') !== $isNull) {
                 $predicate = "({$predicate})";
             }
             $predicate .= $nullCondition;
         }
     }
     return $query->where(array($predicate => $values));
 }