Skip to content

Commit

Permalink
Create castAs method for generic casting
Browse files Browse the repository at this point in the history
  • Loading branch information
wilsonge committed Nov 17, 2019
1 parent 23c8a2b commit 400fafc
Show file tree
Hide file tree
Showing 13 changed files with 304 additions and 17 deletions.
26 changes: 26 additions & 0 deletions Tests/DatabaseQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Joomla\Database\DatabaseQuery;
use Joomla\Database\Exception\QueryTypeAlreadyDefinedException;
use Joomla\Database\ParameterType;
use Joomla\Database\Exception\UnknownTypeException;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

Expand Down Expand Up @@ -84,6 +85,31 @@ public function testCastAsChar()
$this->assertSame('foo', $this->query->castAsChar('foo'));
}

/**
* @testdox A string is cast as a character string for the driver
*/
public function testCastAs()
{
$this->assertSame('123', $this->query->castAs('CHAR', '123'));
}

/**
* @testdox The length param is ignored for castAs when the sql driver doesn't support it
*/
public function testCastAsLengthParamIgnoredWhenNotSupported()
{
$this->assertSame('123', $this->query->castAs('CHAR', '123', 2));
}

/**
* @testdox Test an unknown type case return an unknown type exception
*/
public function testCastAsWithUnknownType()
{
$this->expectException(UnknownTypeException::class);
$this->query->castAs('INT', '123');
}

/**
* Data provider for character length test cases
*
Expand Down
30 changes: 30 additions & 0 deletions Tests/Mysql/MysqlQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,34 @@ public function testRegexp()
$this->query->regexp('foo')
);
}

/**
* @testdox A string is cast as a character string for the driver
*/
public function testCastAsWithChar()
{
$this->assertSame('123', $this->query->castAs('CHAR', '123'));
}

/**
* @testdox The length param is added to the CAST statement when provided
*/
public function testCastAsWithCharAndLengthParam()
{
$this->assertSame(
'CAST(123 AS CHAR(2))',
$this->query->castAs('CHAR', '123', 2)
);
}

/**
* @testdox Test castAs behaviour with INT (adds 0 to the input)
*/
public function testCastAsWithIntegerType()
{
$this->assertSame(
'(123 + 0)',
$this->query->castAs('INT', '123')
);
}
}
30 changes: 30 additions & 0 deletions Tests/Mysqli/MysqliQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,34 @@ public function testRegexp()
$this->query->regexp('foo')
);
}

/**
* @testdox A string is cast as a character string for the driver
*/
public function testCastAsWithChar()
{
$this->assertSame('123', $this->query->castAs('CHAR', '123'));
}

/**
* @testdox The length param is added to the CAST statement when provided
*/
public function testCastAsWithCharAndLengthParam()
{
$this->assertSame(
'CAST(123 AS CHAR(2))',
$this->query->castAs('CHAR', '123', 2)
);
}

/**
* @testdox Test castAs behaviour with INT (adds 0 to the input)
*/
public function testCastAsWithIntegerType()
{
$this->assertSame(
'(123 + 0)',
$this->query->castAs('INT', '123')
);
}
}
30 changes: 30 additions & 0 deletions Tests/Pgsql/PgsqlQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,36 @@ public function testCastAsChar()
$this->assertSame('foo::text', $this->query->castAsChar('foo'));
}

/**
* @testdox A string is cast as a character string for the driver
*/
public function testCastAsWithChar()
{
$this->assertSame('foo::text', $this->query->castAs('CHAR', 'foo'));
}

/**
* @testdox The length param is added to the CAST statement when provided
*/
public function testCastAsWithCharAndLengthParam()
{
$this->assertSame(
'CAST(foo AS CHAR(2))',
$this->query->castAs('CHAR', 'foo', 2)
);
}

/**
* @testdox Test castAs behaviour with INT
*/
public function testCastAsWithIntegerType()
{
$this->assertSame(
'CAST(123 AS INTEGER)',
$this->query->castAs('INT', '123')
);
}

/**
* Data provider for concatenate test cases
*
Expand Down
30 changes: 30 additions & 0 deletions Tests/Sqlsrv/SqlsrvQueryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,36 @@ public function testCastAsChar()
$this->assertSame('CAST(foo as NVARCHAR(10))', $this->query->castAsChar('foo'));
}

/**
* @testdox A string is cast as a character string for the driver
*/
public function testCastAsWithChar()
{
$this->assertSame('CAST(foo as NVARCHAR(10))', $this->query->castAs('CHAR', 'foo'));
}

/**
* @testdox The length param is added to the CAST statement when provided
*/
public function testCastAsWithCharAndLengthParam()
{
$this->assertSame(
'CAST(foo as NVARCHAR(2))',
$this->query->castAs('CHAR', 'foo', 2)
);
}

/**
* @testdox Test castAs behaviour with INT
*/
public function testCastAsWithIntegerType()
{
$this->assertSame(
'CAST(123 AS INT)',
$this->query->castAs('INT', '123')
);
}

/**
* Data provider for character length test cases
*
Expand Down
6 changes: 6 additions & 0 deletions docs/v1-to-v2-update.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,9 @@ Instead of `$query->from($subquery, 'alias')` use `$query->from($subquery->alias
Several methods which defined a query type (i.e. INSERT, SELECT, UPDATE) contained doc blocks indicating the query type should not be changed, but
this was not enforced in the code. As of 2.0, an exception will be thrown if trying to change a query type. If intending to change the query type,
either call `DatabaseQuery::clear()` (optionally only clearing the type clause) or a new query object should be created instead.

#### `castAsChar` deprecated. Replaced with `castAs`

`castAsChar($value)` has been deprecated in favour using of the more generic `castAs('CHAR', $value)` method. This
method has support for supplying the length of a string and also accepting other types of casts such as integers.
The intent is to add more cast types in the subsequent versions.
42 changes: 39 additions & 3 deletions src/DatabaseQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
namespace Joomla\Database;

use Joomla\Database\Exception\QueryTypeAlreadyDefinedException;
use Joomla\Database\Exception\UnknownTypeException;

/**
* Joomla Framework Query Building Class.
Expand Down Expand Up @@ -555,6 +556,40 @@ public function call($columns)
return $this;
}

/**
* Casts a value to a char.
*
* Ensure that the value is properly quoted before passing to the method.
*
* Usage:
* $query->select($query->castAs('CHAR', 'a'));
*
* @param string $type The type of string to cast as.
* @param string $value The value to cast as a char.
* @param string $length Optionally specify the length of the field (if the type supports it otherwise
* ignored).
*
* @return string SQL statement to cast the value as a char type.
*
* @since 1.0
*/
public function castAs(string $type, string $value, ?string $length = null)
{
switch (strtoupper($type))
{
case 'CHAR':
return $value;

default:
throw new UnknownTypeException(
sprintf(
'Type %s was not recognised by the database driver as valid for casting',
$type
)
);
}
}

/**
* Casts a value to a char.
*
Expand All @@ -565,13 +600,14 @@ public function call($columns)
*
* @param string $value The value to cast as a char.
*
* @return string Returns the cast value.
* @return string SQL statement to cast the value as a char type.
*
* @since 1.0
* @since 1.0
* @deprecated 3.0 Use $query->castAs('CHAR', $value)
*/
public function castAsChar($value)
{
return $value;
return $this->castAs('CHAR', $value);
}

/**
Expand Down
18 changes: 18 additions & 0 deletions src/Exception/UnknownTypeException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
/**
* Part of the Joomla Framework Database Package
*
* @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved.
* @license GNU General Public License version 2 or later; see LICENSE
*/

namespace Joomla\Database\Exception;

/**
* Class representing an unknown type for a given database driver.
*
* @since __DEPLOY_VERSION__
*/
class UnknownTypeException extends \InvalidArgumentException
{
}
37 changes: 37 additions & 0 deletions src/Query/MysqlQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -224,4 +224,41 @@ public function selectRowNumber($orderBy, $orderColumnAlias)

return $this->select("(SELECT @rownum := @rownum + 1 FROM (SELECT @rownum := 0) AS r) AS $orderColumnAlias");
}

/**
* Casts a value to a char.
*
* Ensure that the value is properly quoted before passing to the method.
*
* Usage:
* $query->select($query->castAs('CHAR', 'a'));
*
* @param string $type The type of string to cast as.
* @param string $value The value to cast as a char.
* @param string $length The value to cast as a char.
*
* @return string SQL statement to cast the value as a char type.
*
* @since 1.0
*/
public function castAs(string $type, string $value, ?string $length = null)
{
switch (strtoupper($type))
{
case 'CHAR':
if (!$length)
{
return $value;
}
else
{
return 'CAST(' . $value . ' AS CHAR(' . $length . '))';
}

case 'INT':
return '(' . $value . ' + 0)';
}

return parent::castAs($type, $value, $length);
}
}
31 changes: 25 additions & 6 deletions src/Query/PostgresqlQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -308,23 +308,42 @@ public function clear($clause = null)
return $this;
}


/**
* Casts a value to a char.
*
* Ensure that the value is properly quoted before passing to the method.
*
* Usage:
* $query->select($query->castAsChar('a'));
* $query->select($query->castAs('CHAR', 'a'));
*
* @param string $value The value to cast as a char.
* @param string $type The type of string to cast as.
* @param string $value The value to cast as a char.
* @param string $length The value to cast as a char.
*
* @return string Returns the cast value.
* @return string SQL statement to cast the value as a char type.
*
* @since __DEPLOY_VERSION__
* @since 1.0
*/
public function castAsChar($value)
public function castAs(string $type, string $value, ?string $length = null)
{
return $value . '::text';
switch (strtoupper($type))
{
case 'CHAR':
if (!$length)
{
return $value . '::text';
}
else
{
return 'CAST(' . $value . ' AS CHAR(' . $length . '))';
}

case 'INT':
return 'CAST(' . $value . ' AS INTEGER)';
}

return parent::castAs($type, $value, $length);
}

/**
Expand Down
Loading

0 comments on commit 400fafc

Please sign in to comment.