Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions build/psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2073,6 +2073,11 @@
<code><![CDATA[new View('/' . $user)]]></code>
</InternalMethod>
</file>
<file src="apps/files_versions/lib/Db/VersionEntity.php">
<DeprecatedConstant>
<code><![CDATA[Types::JSON]]></code>
</DeprecatedConstant>
</file>
<file src="apps/files_versions/lib/Listener/FileEventsListener.php">
<InternalClass>
<code><![CDATA[new View($user . '/files')]]></code>
Expand All @@ -2082,6 +2087,11 @@
<code><![CDATA[new View($user . '/files')]]></code>
</InternalMethod>
</file>
<file src="apps/files_versions/lib/Migration/Version1020Date20221114144058.php">
<DeprecatedConstant>
<code><![CDATA[Types::JSON]]></code>
</DeprecatedConstant>
</file>
<file src="apps/files_versions/lib/Sabre/RestoreFolder.php">
<InvalidNullableReturnType>
<code><![CDATA[getChild]]></code>
Expand Down Expand Up @@ -3280,6 +3290,17 @@
<code><![CDATA[$this->request->server]]></code>
</NoInterfaceProperties>
</file>
<file src="core/Migrations/Version25000Date20220515204012.php">
<DeprecatedConstant>
<code><![CDATA[Types::JSON]]></code>
</DeprecatedConstant>
</file>
<file src="core/Migrations/Version33000Date20251106131209.php">
<DeprecatedConstant>
<code><![CDATA[IQueryBuilder::PARAM_JSON]]></code>
<code><![CDATA[IQueryBuilder::PARAM_JSON]]></code>
</DeprecatedConstant>
</file>
<file src="core/Service/LoginFlowV2Service.php">
<DeprecatedClass>
<code><![CDATA[IToken::DO_NOT_REMEMBER]]></code>
Expand Down
11 changes: 9 additions & 2 deletions core/Migrations/Version33000Date20251106131209.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,19 @@ public function __construct(
private readonly IDBConnection $connection,
) {
}

public function preSchemaChange(IOutput $output, \Closure $schemaClosure, array $options) {
$qb = $this->connection->getQueryBuilder();
$qb->update('share')
->set('attributes', $qb->createNamedParameter('[["permissions","download",true]]'))
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE, IQueryBuilder::PARAM_INT)))
->andWhere($qb->expr()->eq('attributes', $qb->createNamedParameter('[["permissions","download",null]]', IQueryBuilder::PARAM_STR)));
->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE, IQueryBuilder::PARAM_INT)));

if ($this->connection->getDatabaseProvider(true) === IDBConnection::PLATFORM_MYSQL) {
$qb->andWhere($qb->expr()->eq('attributes', $qb->createFunction("JSON_ARRAY(JSON_ARRAY('permissions','download',null))"), IQueryBuilder::PARAM_JSON));
} else {
$qb->andWhere($qb->expr()->eq('attributes', $qb->createNamedParameter('[["permissions","download",null]]'), IQueryBuilder::PARAM_JSON));
}

$qb->executeStatement();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public function castColumn($column, $type): IQueryFunction {
switch ($type) {
case IQueryBuilder::PARAM_STR:
return new QueryFunction('CAST(' . $this->helper->quoteColumnName($column) . ' AS CHAR)');
case IQueryBuilder::PARAM_JSON:
return new QueryFunction('CAST(' . $this->helper->quoteColumnName($column) . ' AS JSON)');
default:
return parent::castColumn($column, $type);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,32 @@ protected function prepareColumn($column, $type) {
return parent::prepareColumn($column, $type);
}

/**
* @inheritdoc
*/
public function eq($x, $y, $type = null): string {
if ($type === IQueryBuilder::PARAM_JSON) {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
return (string)(new QueryFunction('JSON_EQUAL(' . $x . ',' . $y . ')'));
}

return parent::eq($x, $y, $type);
}

/**
* @inheritdoc
*/
public function neq($x, $y, $type = null): string {
if ($type === IQueryBuilder::PARAM_JSON) {
$x = $this->prepareColumn($x, $type);
$y = $this->prepareColumn($y, $type);
return (string)(new QueryFunction('NOT JSON_EQUAL(' . $x . ',' . $y . ')'));
}

return parent::neq($x, $y, $type);
}

/**
* @inheritdoc
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
namespace OC\DB\QueryBuilder\ExpressionBuilder;

use OC\DB\QueryBuilder\QueryFunction;
use OCP\DB\QueryBuilder\ILiteral;
use OCP\DB\QueryBuilder\IParameter;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\DB\QueryBuilder\IQueryFunction;

Expand All @@ -25,12 +27,24 @@ public function castColumn($column, $type): IQueryFunction {
case IQueryBuilder::PARAM_INT:
return new QueryFunction('CAST(' . $this->helper->quoteColumnName($column) . ' AS BIGINT)');
case IQueryBuilder::PARAM_STR:
case IQueryBuilder::PARAM_JSON:
return new QueryFunction('CAST(' . $this->helper->quoteColumnName($column) . ' AS TEXT)');
default:
return parent::castColumn($column, $type);
}
}

/**
* @inheritdoc
*/
protected function prepareColumn($column, $type) {
if ($type === IQueryBuilder::PARAM_JSON && !is_array($column) && !($column instanceof IParameter) && !($column instanceof ILiteral)) {
$column = $this->castColumn($column, $type);
}

return parent::prepareColumn($column, $type);
}

/**
* @inheritdoc
*/
Expand Down
2 changes: 2 additions & 0 deletions lib/public/DB/QueryBuilder/IQueryBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ interface IQueryBuilder {

/**
* @since 24.0.0
* @deprecated 33.0.0 JSON fields can not properly be used in WHERE statements of Oracle and MySQL.
* It is recommended to use a simple STRING field and handle JSON within PHP
*/
public const PARAM_JSON = 'json';

Expand Down
2 changes: 2 additions & 0 deletions lib/public/DB/Types.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ final class Types {
/**
* @var string
* @since 24.0.0
* @deprecated 33.0.0 JSON fields can not properly be used in WHERE statements of Oracle and MySQL.
* It is recommended to use a simple STRING field and handle JSON within PHP
*/
public const JSON = 'json';
}
49 changes: 49 additions & 0 deletions tests/lib/DB/QueryBuilder/ExpressionBuilderDBTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,55 @@ public function testLongText(): void {
self::assertEquals('myvalue', $entries[0]['configvalue']);
}

public function testJson(): void {
if ($this->connection->getDatabaseProvider(true) === IDBConnection::PLATFORM_ORACLE) {
$result = $this->connection->executeQuery('SELECT VERSION FROM PRODUCT_COMPONENT_VERSION');
$version = $result->fetchOne();
$result->closeCursor();
if (str_starts_with($version, '11.')) {
$this->markTestSkipped('JSON is not supported on Oracle 11, skipping until deprecation was clarified: ' . $version);
}
}


$appId = $this->getUniqueID('testing');
$query = $this->connection->getQueryBuilder();
$query->insert('share')
->values([
'uid_owner' => $query->createNamedParameter('uid_owner'),
'item_type' => $query->createNamedParameter('item_type'),
'permissions' => $query->createNamedParameter(0),
'stime' => $query->createNamedParameter(0),
'accepted' => $query->createNamedParameter(0),
'mail_send' => $query->createNamedParameter(0),
'share_type' => $query->createNamedParameter(0),
'share_with' => $query->createNamedParameter($appId),
'attributes' => $query->createNamedParameter('[["permissions","before"]]'),
])
->executeStatement();

$query = $this->connection->getQueryBuilder();
$query->update('share')
->set('attributes', $query->createNamedParameter('[["permissions","after"]]'));
if ($this->connection->getDatabaseProvider(true) === IDBConnection::PLATFORM_MYSQL) {
$query->where($query->expr()->eq('attributes', $query->createFunction("JSON_ARRAY(JSON_ARRAY('permissions','before'))"), IQueryBuilder::PARAM_JSON));
} else {
$query->where($query->expr()->eq('attributes', $query->createNamedParameter('[["permissions","before"]]'), IQueryBuilder::PARAM_JSON));
}
$query->executeStatement();

$query = $this->connection->getQueryBuilder();
$query->select('attributes')
->from('share')
->where($query->expr()->eq('share_with', $query->createNamedParameter($appId)));

$result = $query->executeQuery();
$entries = $result->fetchAll();
$result->closeCursor();
self::assertCount(1, $entries);
self::assertEquals([['permissions','after']], json_decode($entries[0]['attributes'], true));
}

public function testDateTimeEquals(): void {
$dateTime = new \DateTime('2023-01-01');
$insert = $this->connection->getQueryBuilder();
Expand Down
Loading