oci8 schema adapter returns null for 'KEY' field in column info which causes strpos deprecation error
johnrembo opened this issue · 4 comments
johnrembo commented
What steps will reproduce the problem?
Create app with oci8 AR
$app = Yii::createWebApplication('protected/config/main.php');
...
Pack::Model()->findByPk(...)
...
Config is:
return array(
...
'components'=>array(
'db'=>array(
'class'=>'ext.oci8Pdo.OciDbConnection',
'connectionString' => 'oci:dbname=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST='.ORACLE_HOST.')
(PORT='.ORACLE_PORT.'))(CONNECT_DATA=(SERVICE_NAME='.ORACLE_SID.')));charset='.ORACLE_CP.';',
'username'=> ORACLE_USER,
'password'=> ORACLE_PASS
),
...
What is the expected result?
Create an AR model
What do you get instead?
PHP error
strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated
../yii/framework/db/schema/oci/COciSchema.php(234)
Additional info
Q | A |
---|---|
Yii version | 1.1.27 |
PHP version | 8.1.2 |
Operating system | Linux 5.15.0-53-generic #59-Ubuntu SMP |
marcovtwout commented
@johnrembo Could you post the full stack trace and also a simple example table that can be used to reproduce this issue?
johnrembo commented
Yeah why not.
Given Test.php
<?php
class Test extends CActiveRecord {
public static function model($className=__CLASS__)
{
return parent::model($className);
}
public function tableName()
{
return 'SCOTT.TEST';
}
public function primaryKey(){
return array('ID');
}
}
and test.php
<?php
define('YII_DEBUG', true);
require 'vendor/autoload.php';
$config = [
'components'=>array(
'db'=>array(
'class'=>'ext.oci8Pdo.OciDbConnection',
'connectionString' => 'oci:dbname=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=localhost)
(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=ORCL)));charset=UTF-8;',
'username'=> 'scott',
'password'=> 'tiger',
),
)
];
$app = Yii::createWebApplication($config);
echo 'Connection string: '; echo Yii::app()->db->connectionString; echo '<br />'.PHP_EOL;
$command = Yii::app()->db->createCommand("create table test (id number, col varchar2(1), constraint id_pk primary key (id))");
$command->execute();
$command = Yii::app()->db->createCommand("insert into test values (1, '1')");
$command->execute();
var_dump(Test::Model()->findByPk(1));
I get
PHP error
strpos(): Passing null to parameter #1 ($haystack) of type string is deprecated
/home/user/src/yii/framework/db/schema/oci/COciSchema.php(234)
222
223 /**
224 * Creates a table column.
225 * @param array $column column metadata
226 * @return CDbColumnSchema normalized column metadata
227 */
228 protected function createColumn($column)
229 {
230 $c=new COciColumnSchema;
231 $c->name=$column['COLUMN_NAME'];
232 $c->rawName=$this->quoteColumnName($c->name);
233 $c->allowNull=$column['NULLABLE']==='Y';
234 $c->isPrimaryKey=strpos($column['KEY'],'P')!==false;
235 $c->isForeignKey=false;
236 $c->init($column['DATA_TYPE'],$column['DATA_DEFAULT']);
237 $c->comment=$column['COLUMN_COMMENT']===null ? '' : $column['COLUMN_COMMENT'];
238
239 return $c;
240 }
241
242 /**
243 * Collects the primary and foreign key column details for the given table.
244 * @param COciTableSchema $table the table metadata
245 */
246 protected function findConstraints($table)
Stack Trace
#0
– /home/user/src/yii/framework/db/schema/oci/COciSchema.php(234): strpos(null, "P")
229 {
230 $c=new COciColumnSchema;
231 $c->name=$column['COLUMN_NAME'];
232 $c->rawName=$this->quoteColumnName($c->name);
233 $c->allowNull=$column['NULLABLE']==='Y';
234 $c->isPrimaryKey=strpos($column['KEY'],'P')!==false;
235 $c->isForeignKey=false;
236 $c->init($column['DATA_TYPE'],$column['DATA_DEFAULT']);
237 $c->comment=$column['COLUMN_COMMENT']===null ? '' : $column['COLUMN_COMMENT'];
238
239 return $c;
#1
– /home/user/src/yii/framework/db/schema/oci/COciSchema.php(205): COciSchema->createColumn(array("COLUMN_NAME" => "COL", "DATA_TYPE" => "VARCHAR2(1)", "NULLABLE" => "Y", "DATA_DEFAULT" => null, ...))
200 return false;
201 }
202
203 foreach($columns as $column)
204 {
205 $c=$this->createColumn($column);
206
207 $table->columns[$c->name]=$c;
208 if($c->isPrimaryKey)
209 {
210 if($table->primaryKey===null)
#2
– /home/user/src/yii/framework/db/schema/oci/COciSchema.php(123): COciSchema->findColumns(COciTableSchema)
118 protected function loadTable($name)
119 {
120 $table=new COciTableSchema;
121 $this->resolveTableNames($table,$name);
122
123 if(!$this->findColumns($table))
124 return null;
125 $this->findConstraints($table);
126
127 return $table;
128 }
#3
– /home/user/src/yii/framework/db/schema/CDbSchema.php(103): COciSchema->loadTable("SCOTT.TEST")
098 $cache->set($key,$table,$duration);
099 }
100 $this->_tables[$name]=$table;
101 }
102 else
103 $this->_tables[$name]=$table=$this->loadTable($realName);
104
105 if(isset($qcDuration)) // re-enable query caching
106 $this->_connection->queryCachingDuration=$qcDuration;
107
108 return $table;
#4
– /home/user/src/yii/framework/db/ar/CActiveRecord.php(2390): CDbSchema->getTable("SCOTT.TEST")
2385 public function __construct($model)
2386 {
2387 $this->_modelClassName=get_class($model);
2388
2389 $tableName=$model->tableName();
2390 if(($table=$model->getDbConnection()->getSchema()->getTable($tableName))===null)
2391 throw new CDbException(Yii::t('yii','The table "{table}" for active record class "{class}" cannot be found in the database.',
2392 array('{class}'=>$this->_modelClassName,'{table}'=>$tableName)));
2393
2394 if(($modelPk=$model->primaryKey())!==null || $table->primaryKey===null)
2395 {
#5
– /home/user/src/yii/framework/db/ar/CActiveRecord.php(413): CActiveRecordMetaData->__construct(Test)
408 {
409 $className=get_class($this);
410 if(!array_key_exists($className,self::$_md))
411 {
412 self::$_md[$className]=null; // preventing recursive invokes of {@link getMetaData()} via {@link __get()}
413 self::$_md[$className]=new CActiveRecordMetaData($this);
414 }
415 return self::$_md[$className];
416 }
417
418 /**
#6
– /home/user/src/yii/framework/db/ar/CActiveRecord.php(663): CActiveRecord->getMetaData()
658 * Returns the metadata of the table that this AR belongs to
659 * @return CDbTableSchema the metadata of the table that this AR belongs to
660 */
661 public function getTableSchema()
662 {
663 return $this->getMetaData()->tableSchema;
664 }
665
666 /**
667 * Returns the command builder used by this AR.
668 * @return CDbCommandBuilder the command builder used by this AR
#7
– /home/user/src/yii/framework/db/ar/CActiveRecord.php(1493): CActiveRecord->getTableSchema()
1488 */
1489 public function findByPk($pk,$condition='',$params=array())
1490 {
1491 Yii::trace(get_class($this).'.findByPk()','system.db.ar.CActiveRecord');
1492 $prefix=$this->getTableAlias(true).'.';
1493 $criteria=$this->getCommandBuilder()->createPkCriteria($this->getTableSchema(),$pk,$condition,$params,$prefix);
1494 return $this->query($criteria);
1495 }
1496
1497 /**
1498 * Finds all active records with the specified primary keys.
#8
– /home/user/work/arrest/front/test.php(22): CActiveRecord->findByPk(1)
17
18 $command = Yii::app()->db->createCommand("create table test (id number, col varchar2(1), constraint id_pk primary key (id))");
19 $command->execute();
20 $command = Yii::app()->db->createCommand("insert into test values (1, '1')");
21 $command->execute();
22 var_dump(Test::Model()->findByPk(1));
2022-12-08 14:54:03 Apache/2.4.52 (Ubuntu) Yii Framework/1.1.28-dev
Actually I ve already fixed it in a fork.
And slightly optimized the query. But now struggling to run unit test on phpunit v9.5.10:
phpunit framework ↑
PHP Fatal error: Declaration of CComponentTest::setUp() must be compatible with PHPUnit\Framework\TestCase::setUp(): vo
id in /home/user/src/yii/tests/framework/base/CComponentTest.php on line 23
PHP Stack trace:
PHP 1. {main}() /usr/bin/phpunit:0
PHP 2. PHPUnit\TextUI\Command::main($exit = *uninitialized*) /usr/bin/phpunit:73
PHP 3. PHPUnit\TextUI\Command->run($argv = [0 => '/usr/bin/phpunit', 1 => 'framework'], $exit = TRUE) /usr/share/php/P
HPUnit/TextUI/Command.php:96
PHP 4. PHPUnit\Runner\BaseTestRunner->getTest($suiteClassFile = '/home/user/src/yii/tests/framework', $suffixes
= [0 => 'Test.php', 1 => '.phpt']) /usr/share/php/PHPUnit/TextUI/Command.php:120
PHP 5. PHPUnit\Framework\TestSuite->addTestFiles($fileNames = [0 =>
Apparently this also needs a little php compatibility updates
marcovtwout commented
@johnrembo Could you test if #4510 solves your issue?
marcovtwout commented
Marking as fixed with #4510