PHP Classes

File: vendor/gabordemooij/redbean/RedBeanPHP/QueryWriter/Firebird.php

Recommend this page to a friend!
  Classes of Adrian M   upMVC   vendor/gabordemooij/redbean/RedBeanPHP/QueryWriter/Firebird.php   Download  
File: vendor/gabordemooij/redbean/RedBeanPHP/QueryWriter/Firebird.php
Role: Class source
Content type: text/plain
Description: Class source
Class: upMVC
Pure PHP web development without other frameworks
Author: By
Last change:
Date: 25 days ago
Size: 10,483 bytes
 

Contents

Class file image Download
<?php namespace RedBeanPHP\QueryWriter; /* Experimental */ /** * This driver has been created in 2015 but it has never been distributed * because it was never finished. However, in the true spirit of open source * it is now available in the source of RedBeanPHP. * * Consider this driver experimental or help me finish it to * support the Firebird/Interbase database series. * */ use RedBeanPHP\QueryWriter\AQueryWriter as AQueryWriter; use RedBeanPHP\QueryWriter as QueryWriter; use RedBeanPHP\Adapter\DBAdapter as DBAdapter; use RedBeanPHP\Adapter as Adapter; use RedBeanPHP\RedException\SQL as SQLException; /** * RedBeanPHP Firebird/Interbase QueryWriter. * This is a QueryWriter class for RedBeanPHP. * This QueryWriter provides support for the Firebird/Interbase database platform. * * *** Warning - Experimental Software | Not ready for Production **** * * @file RedBeanPHP/QueryWriter/Firebird.php * @author Gabor de Mooij and the RedBeanPHP Community * @license BSD/GPLv2 * * @copyright * (c) G.J.G.T. (Gabor) de Mooij and the RedBeanPHP Community. * This source file is subject to the BSD/GPLv2 License that is bundled * with this source code in the file license.txt. */ class Firebird extends AQueryWriter implements QueryWriter { /** * Data types */ const C_DATATYPE_INTEGER = 2; const C_DATATYPE_FLOAT = 3; const C_DATATYPE_TEXT = 5; /** * @var DBAdapter */ protected $adapter; /** * @var string */ protected $quoteCharacter = '"'; /** * Returns the insert suffix SQL Snippet * * @param string $table table * * @return string $sql SQL Snippet */ protected function getInsertSuffix( $table ) { return 'RETURNING id '; } /** * @see AQueryWriter::getKeyMapForType */ protected function getKeyMapForType( $type ) { $table = $this->esc( $type, TRUE ); $keys = $this->adapter->get(' SELECT information_schema.key_column_usage.constraint_name AS `name`, information_schema.key_column_usage.referenced_table_name AS `table`, information_schema.key_column_usage.column_name AS `from`, information_schema.key_column_usage.referenced_column_name AS `to`, information_schema.referential_constraints.update_rule AS `on_update`, information_schema.referential_constraints.delete_rule AS `on_delete` FROM information_schema.key_column_usage INNER JOIN information_schema.referential_constraints ON ( information_schema.referential_constraints.constraint_name = information_schema.key_column_usage.constraint_name AND information_schema.referential_constraints.constraint_schema = information_schema.key_column_usage.constraint_schema AND information_schema.referential_constraints.constraint_catalog = information_schema.key_column_usage.constraint_catalog ) WHERE information_schema.key_column_usage.table_schema IN ( SELECT DATABASE() ) AND information_schema.key_column_usage.table_name = ? AND information_schema.key_column_usage.constraint_name != \'PRIMARY\' AND information_schema.key_column_usage.referenced_table_name IS NOT NULL ', array($table)); $keyInfoList = array(); foreach ( $keys as $k ) { $label = $this->makeFKLabel( $k['from'], $k['table'], $k['to'] ); $keyInfoList[$label] = array( 'name' => $k['name'], 'from' => $k['from'], 'table' => $k['table'], 'to' => $k['to'], 'on_update' => $k['on_update'], 'on_delete' => $k['on_delete'] ); } return $keyInfoList; } /** * Constructor * * @param Adapter $adapter Database Adapter */ public function __construct( Adapter $adapter ) { $this->typeno_sqltype = array( Firebird::C_DATATYPE_INTEGER => 'INTEGER', Firebird::C_DATATYPE_FLOAT => 'FLOAT', Firebird::C_DATATYPE_TEXT => 'VARCHAR(8190)', ); $this->sqltype_typeno = array(); foreach ( $this->typeno_sqltype as $k => $v ) { $this->sqltype_typeno[trim( strtoupper( $v ) )] = $k; } $this->adapter = $adapter; $this->encoding = $this->adapter->getDatabase()->getMysqlEncoding(); } /** * This method returns the datatype to be used for primary key IDS and * foreign keys. Returns one if the data type constants. * * @return integer $const data type to be used for IDS. */ public function getTypeForID() { return self::C_DATATYPE_INTEGER; } /** * @see QueryWriter::getTables */ public function getTables() { return $this->adapter->getCol( 'SELECT RDB$RELATION_NAME FROM RDB$RELATIONS WHERE RDB$VIEW_BLR IS NULL AND (RDB$SYSTEM_FLAG IS NULL OR RDB$SYSTEM_FLAG = 0)'); } /** * @see QueryWriter::createTable */ public function createTable( $table ) { $tableNoQ = $this->esc( $table ); $tableSQL = "CREATE TABLE \"{$table}\" ( id INT )"; $dropGeneratorSQL = "DROP GENERATOR gen{$table}"; $generatorSQL = "CREATE GENERATOR gen{$table}"; $generatorSQL2 = "SET GENERATOR gen{$table} TO 0"; $triggerSQL = " CREATE TRIGGER ai{$table} FOR \"{$table}\" ACTIVE BEFORE INSERT POSITION 0 AS BEGIN if (NEW.id is NULL) then NEW.id = GEN_ID(gen{$table}, 1); END "; try { $this->adapter->exec( $dropGeneratorSQL ); }catch( SQLException $e ) {}; $this->adapter->exec( $tableSQL ); $this->adapter->exec( $generatorSQL ); $this->adapter->exec( $generatorSQL2 ); $this->adapter->exec( $triggerSQL ); } /** * @see QueryWriter::widenColumn */ public function widenColumn( $type, $property, $dataType ) { if ( !isset($this->typeno_sqltype[$dataType]) ) return FALSE; $table = $this->esc( $type ); $column = $this->esc( $property ); $newType = $this->typeno_sqltype[$dataType]; $this->adapter->exec( "ALTER TABLE $table ALTER COLUMN $column TYPE $newType " ); return TRUE; } /** * @see QueryWriter::getColumns */ public function getColumns( $table ) { $columnsRaw = $this->adapter->getAssoc( ' SELECT RDB$RELATION_FIELDS.RDB$FIELD_NAME, CASE RDB$FIELDS.RDB$FIELD_TYPE WHEN 10 THEN \'FLOAT\' WHEN 8 THEN \'INTEGER\' WHEN 37 THEN \'VARCHAR\' ELSE RDB$FIELDS.RDB$FIELD_TYPE END AS FTYPE FROM RDB$RELATION_FIELDS LEFT JOIN RDB$FIELDS ON RDB$RELATION_FIELDS.RDB$FIELD_SOURCE = RDB$FIELDS.RDB$FIELD_NAME WHERE RDB$RELATION_FIELDS.RDB$RELATION_NAME = \''.($this->esc($table, true)).'\' ORDER BY RDB$RELATION_FIELDS.RDB$FIELD_POSITION '); $columns = array(); foreach( $columnsRaw as $rawKey => $columnRaw ) { $columns[ trim( $rawKey ) ] = trim( $columnRaw ); } return $columns; } /** * @see QueryWriter::scanType */ public function scanType( $value, $flagSpecial = FALSE ) { if ( AQueryWriter::canBeTreatedAsInt( $value ) ) { return FireBird::C_DATATYPE_INTEGER; } if ( !$this->startsWithZeros( $value ) && is_numeric( $value ) ) { return FireBird::C_DATATYPE_DOUBLE; } return FireBird::C_DATATYPE_TEXT; } /** * @see QueryWriter::code */ public function code( $typedescription, $includeSpecials = FALSE ) { if ( isset( $this->sqltype_typeno[$typedescription] ) ) { return $this->sqltype_typeno[$typedescription]; } else { return self::C_DATATYPE_SPECIFIED; } } /** * @see QueryWriter::addUniqueIndex */ public function addUniqueConstraint( $type, $properties ) { $tableNoQ = $this->esc( $type, TRUE ); $columns = array(); foreach( $properties as $key => $column ) $columns[$key] = $this->esc( $column ); $table = $this->esc( $type ); sort( $columns ); // Else we get multiple indexes due to order-effects $name = 'UQ_'.substr( sha1( implode( ',', $columns ) ), 0, 28); try { $sql = "ALTER TABLE $table ADD CONSTRAINT $name UNIQUE (" . implode( ',', $columns ) . ")"; $this->adapter->exec( $sql ); } catch ( SQLException $e ) { //do nothing, don't use alter table ignore, this will delete duplicate records in 3-ways! return FALSE; } return TRUE; } /** * @see QueryWriter::addIndex */ public function addIndex( $type, $name, $property ) { try { $table = $this->esc( $type ); $name = preg_replace( '/\W/', '', $name ); $column = $this->esc( $property ); $this->adapter->exec( "CREATE INDEX $name ON $table ($column) " ); return TRUE; } catch ( SQLException $e ) { return FALSE; } } /** * @see QueryWriter::addFK */ public function addFK( $type, $targetType, $property, $targetProperty, $isDependent = FALSE ) { $table = $this->esc( $type ); $targetTable = $this->esc( $targetType ); $targetTableNoQ = $this->esc( $targetType, TRUE ); $field = $this->esc( $property ); $fieldNoQ = $this->esc( $property, TRUE ); $targetField = $this->esc( $targetProperty ); $targetFieldNoQ = $this->esc( $targetProperty, TRUE ); $tableNoQ = $this->esc( $type, TRUE ); $fieldNoQ = $this->esc( $property, TRUE ); if ( !is_null( $this->getForeignKeyForTypeProperty( $tableNoQ, $fieldNoQ ) ) ) return FALSE; //Widen the column if it's incapable of representing a foreign key (at least INT). $columns = $this->getColumns( $tableNoQ ); $idType = $this->getTypeForID(); if ( $this->code( $columns[$fieldNoQ] ) !== $idType ) { $this->widenColumn( $type, $property, $idType ); } $fkName = 'fk_'.($tableNoQ.'_'.$fieldNoQ); $cName = 'c_'.$fkName; try { $this->adapter->exec( " ALTER TABLE {$table} ADD CONSTRAINT $cName FOREIGN KEY $fkName ( {$fieldNoQ} ) REFERENCES {$targetTableNoQ} ({$targetFieldNoQ}) ON DELETE " . ( $isDependent ? 'CASCADE' : 'SET NULL' ) . ' ON UPDATE '.( $isDependent ? 'CASCADE' : 'SET NULL' ).';'); } catch ( SQLException $e ) { // Failure of fk-constraints is not a problem } } /** * @see QueryWriter::sqlStateIn */ public function sqlStateIn( $state, $list, $extraDriverDetails = array() ) { $stateMap = array( '42S02' => QueryWriter::C_SQLSTATE_NO_SUCH_TABLE, '42S22' => QueryWriter::C_SQLSTATE_NO_SUCH_COLUMN, '23000' => QueryWriter::C_SQLSTATE_INTEGRITY_CONSTRAINT_VIOLATION ); return in_array( ( isset( $stateMap[$state] ) ? $stateMap[$state] : '0' ), $list ); } /** * @see QueryWriter::wipeAll */ public function wipeAll() { if (AQueryWriter::$noNuke) throw new \Exception('The nuke() command has been disabled using noNuke() or R::feature(novice/...).'); $tables = $this->getTables(); foreach( $tables as $table ) { $table = trim( $table ); $this->adapter->exec( "DROP TABLE \"{$table}\" " ); } } }