diff --git a/WebFiori/Database/MsSql/MSSQLInsertBuilder.php b/WebFiori/Database/MsSql/MSSQLInsertBuilder.php index ee49374..930f4f5 100644 --- a/WebFiori/Database/MsSql/MSSQLInsertBuilder.php +++ b/WebFiori/Database/MsSql/MSSQLInsertBuilder.php @@ -26,7 +26,12 @@ public function parseValues(array $values) { foreach ($values as $valsArr) { foreach ($valsArr as $col => $val) { $colObj = $this->getTable()->getColByKey($col); - $arr[] = $val; + + if ($colObj !== null && in_array($colObj->getDatatype(), ['binary', 'varbinary'])) { + $arr[] = [$val, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY), SQLSRV_SQLTYPE_VARBINARY('max')]; + } else { + $arr[] = $val; + } } $index++; } diff --git a/WebFiori/Database/MySql/MySQLColumn.php b/WebFiori/Database/MySql/MySQLColumn.php index 473ee6b..615ae6d 100644 --- a/WebFiori/Database/MySql/MySQLColumn.php +++ b/WebFiori/Database/MySql/MySQLColumn.php @@ -695,8 +695,10 @@ private function firstColPart() { } else { $retVal .= $colDataType.'('.$this->getSize().') '; } - } else if ($colDataType == 'varchar' || $colDataType == 'text') { + } else if ($colDataType == 'varchar') { $retVal .= $colDataType.'('.$this->getSize().') '; + } else if ($colDataType == 'text') { + $retVal .= 'text '; } else if (in_array($colDataType, Column::BOOL_TYPES)) { $retVal .= 'bit(1) '; } else if ($colDataType == 'decimal' || $colDataType == 'float' || $colDataType == 'double') { diff --git a/WebFiori/Database/Query/SelectExpression.php b/WebFiori/Database/Query/SelectExpression.php index baac0aa..9ddd047 100644 --- a/WebFiori/Database/Query/SelectExpression.php +++ b/WebFiori/Database/Query/SelectExpression.php @@ -652,6 +652,8 @@ public function select(array $colsOrExpressions) { } else { if (gettype($index) == 'integer') { $this->addColumn($colArrOrExpr); + } else if (is_string($colArrOrExpr)) { + $this->addColumn($index, ['alias' => $colArrOrExpr]); } else { $this->addColumn($index, $colArrOrExpr); } diff --git a/tests/WebFiori/Tests/Database/MsSql/MSSQLQueryBuilderTest.php b/tests/WebFiori/Tests/Database/MsSql/MSSQLQueryBuilderTest.php index f7dcf6b..0736813 100644 --- a/tests/WebFiori/Tests/Database/MsSql/MSSQLQueryBuilderTest.php +++ b/tests/WebFiori/Tests/Database/MsSql/MSSQLQueryBuilderTest.php @@ -4,9 +4,11 @@ use InvalidArgumentException; use PHPUnit\Framework\TestCase; +use WebFiori\Database\ColOption; use WebFiori\Database\ConnectionInfo; use WebFiori\Database\Database; use WebFiori\Database\DatabaseException; +use WebFiori\Database\DataType; use WebFiori\Database\Query\Expression; use WebFiori\Database\MsSql\MSSQLConnection; use WebFiori\Tests\Database\MsSql\MSSQLTestSchema; @@ -1411,4 +1413,38 @@ public function testUpdateWithNewCol() { $this->assertStringContainsString('update [users] set', $query); $this->assertStringContainsString('[first_name] = ?', $query); } + /** + * @test + * Issue #170: Inserting PHP string into varbinary(max) column should not fail. + */ + public function testInsertVarbinaryData() { + $connInfo = new ConnectionInfo('mssql', 'sa', getenv('SA_SQL_SERVER_PASSWORD'), 'testing_db', SQL_SERVER_HOST, 1433, [ + 'TrustServerCertificate' => 'true' + ]); + $db = new Database($connInfo); + $db->createBlueprint('bin_test')->addColumns([ + 'id' => [ + ColOption::TYPE => DataType::INT, + ColOption::PRIMARY => true, + ], + 'data' => [ + ColOption::TYPE => DataType::VARBINARY, + ColOption::SIZE => -1, + ], + ]); + $db->table('bin_test')->createTable()->execute(); + + try { + $binaryData = random_bytes(16); + $db->table('bin_test')->insert([ + 'id' => 1, + 'data' => $binaryData, + ])->execute(); + + $result = $db->table('bin_test')->select()->where('id', 1)->execute(); + $this->assertCount(1, $result); + } finally { + $db->raw("DROP TABLE [bin_test]")->execute(); + } + } } diff --git a/tests/WebFiori/Tests/Database/MySql/MySQLColumnTest.php b/tests/WebFiori/Tests/Database/MySql/MySQLColumnTest.php index 57cb799..75d75cd 100644 --- a/tests/WebFiori/Tests/Database/MySql/MySQLColumnTest.php +++ b/tests/WebFiori/Tests/Database/MySql/MySQLColumnTest.php @@ -869,6 +869,16 @@ public function testAutoMapMSSQLVarbinaryToMySQL() { $this->assertInstanceOf(MySQLColumn::class, $col); $this->assertEquals('blob', $col->getDatatype()); } + /** + * @test + * Issue #171: DataType::TEXT should map to MySQL TEXT, not TINYTEXT. + */ + public function testTextTypeMapsToText() { + $col = new MySQLColumn('content', 'text'); + $ddl = $col . ''; + $this->assertStringContainsString('text ', $ddl); + $this->assertStringNotContainsString('text(', $ddl, 'TEXT column should not have a size parameter (text(n) becomes TINYTEXT in MySQL)'); + } /** * @test * Test that native MySQL types are not affected by auto-mapping. diff --git a/tests/WebFiori/Tests/Database/MySql/MySQLQueryBuilderTest.php b/tests/WebFiori/Tests/Database/MySql/MySQLQueryBuilderTest.php index 9c9b55a..e8d6c6a 100644 --- a/tests/WebFiori/Tests/Database/MySql/MySQLQueryBuilderTest.php +++ b/tests/WebFiori/Tests/Database/MySql/MySQLQueryBuilderTest.php @@ -2312,4 +2312,62 @@ public function testInsertBoolColumnMultiRowCastsToInt() { $this->assertSame(1, $params['values'][1][2], 'Row 1: true should be cast to int 1'); $this->assertSame(0, $params['values'][1][3], 'Row 1: false should be cast to int 0'); } + /** + * @test + * Issue #172: Inserting values into BIT(1) columns should not fail. + */ + public function testInsertBitColumnIntegration() { + $connInfo = new ConnectionInfo('mysql', 'root', getenv('MYSQL_ROOT_PASSWORD'), 'testing_db', '127.0.0.1'); + $db = new Database($connInfo); + $db->createBlueprint('bit_test')->addColumns([ + 'id' => [ + \WebFiori\Database\ColOption::TYPE => \WebFiori\Database\DataType::INT, + \WebFiori\Database\ColOption::PRIMARY => true, + ], + 'flag' => [ + \WebFiori\Database\ColOption::TYPE => \WebFiori\Database\DataType::BOOL, + \WebFiori\Database\ColOption::DEFAULT => false, + ], + ]); + $db->table('bit_test')->createTable()->execute(); + + try { + // Case 1: Explicit boolean value + $db->table('bit_test')->insert([ + 'id' => 1, + 'flag' => true, + ])->execute(); + + // Case 2: Explicit false value + $db->table('bit_test')->insert([ + 'id' => 2, + 'flag' => false, + ])->execute(); + + // Case 3: Omit flag, rely on default value + $db->table('bit_test')->insert([ + 'id' => 3, + ])->execute(); + + $result = $db->table('bit_test')->select()->execute(); + $this->assertCount(3, $result); + } finally { + $db->raw("DROP TABLE `bit_test`")->execute(); + } + } + /** + * @test + * Issue #173: select() with column aliases as string values should work. + */ + public function testSelectWithStringAlias() { + $schema = new MySQLTestSchema(); + $schema->table('users')->select([ + 'first-name' => 'full_name', + 'age', + ]); + $query = $schema->getLastQuery(); + $this->assertStringContainsString('`full_name`', $query); + $this->assertStringContainsString('`age`', $query); + } } +