diff --git a/CHANGELOG.md b/CHANGELOG.md
index ccfca383c..93bb4d293 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,15 @@
+### 12.1.0 (2026-??-??)
+
+#### New
+
+* Added vector query support to the query builder for the following databases:
+ - `MariaDB`
+ - `MySQL`
+ - `Postgres`
+* Now possible to define custom input/output value objects for the query builder.
+
+--------------------------------------------------------
+
### 11.4.6, 12.0.2 (2026-01-08)
diff --git a/src/mako/Mako.php b/src/mako/Mako.php
index b1aa0e11b..468a574c7 100644
--- a/src/mako/Mako.php
+++ b/src/mako/Mako.php
@@ -15,7 +15,7 @@ final class Mako
/**
* Mako version.
*/
- public const string VERSION = '12.0.2';
+ public const string VERSION = '12.1.0';
/**
* Mako major version.
@@ -25,10 +25,10 @@ final class Mako
/**
* Mako minor version.
*/
- public const int VERSION_MINOR = 0;
+ public const int VERSION_MINOR = 1;
/**
* Mako patch version.
*/
- public const int VERSION_PATCH = 2;
+ public const int VERSION_PATCH = 0;
}
diff --git a/src/mako/application/cli/commands/app/preloader/core.php b/src/mako/application/cli/commands/app/preloader/core.php
index cd6282cd9..a6e3ba784 100644
--- a/src/mako/application/cli/commands/app/preloader/core.php
+++ b/src/mako/application/cli/commands/app/preloader/core.php
@@ -78,6 +78,13 @@
mako\database\query\Result::class,
mako\database\query\ResultSet::class,
mako\database\query\Subquery::class,
+ mako\database\query\values\in\Vector::class,
+ mako\database\query\values\out\Value::class,
+ mako\database\query\values\out\ValueWithAliasInterface::class,
+ mako\database\query\values\out\Vector::class,
+ mako\database\query\values\out\VectorDistance::class,
+ mako\database\query\values\ValueInterface::class,
+ mako\database\query\VectorDistance::class,
mako\error\ErrorHandler::class,
mako\file\FileSystem::class,
mako\file\Permission::class,
diff --git a/src/mako/database/query/Query.php b/src/mako/database/query/Query.php
index 4cbaa76e5..87dcf6833 100644
--- a/src/mako/database/query/Query.php
+++ b/src/mako/database/query/Query.php
@@ -545,6 +545,16 @@ public function where(array|Closure|Raw|string $column, ?string $operator = null
return $this;
}
+ /**
+ * Adds a OR WHERE clause.
+ *
+ * @return $this
+ */
+ public function orWhere(array|Closure|Raw|string $column, ?string $operator = null, mixed $value = null): static
+ {
+ return $this->where($column, $operator, $value, 'OR');
+ }
+
/**
* Adds a raw WHERE clause.
*
@@ -565,16 +575,6 @@ public function whereRaw(array|Raw|string $column, null|array|string $operator =
return $this->where($column, $operator, new Raw($raw), $separator);
}
- /**
- * Adds a OR WHERE clause.
- *
- * @return $this
- */
- public function orWhere(array|Closure|Raw|string $column, ?string $operator = null, mixed $value = null): static
- {
- return $this->where($column, $operator, $value, 'OR');
- }
-
/**
* Adds a raw OR WHERE clause.
*
@@ -642,6 +642,35 @@ public function orWhereColumn(array|string $column1, string $operator, array|str
return $this->whereColumn($column1, $operator, $column2, 'OR');
}
+ /**
+ * Adds a vector distance clause.
+ *
+ * @return $this
+ */
+ public function whereVectorDistance(string $column, array|string|Subquery $vector, float $maxDistance = 0.2, VectorDistance $vectorDistance = VectorDistance::COSINE, string $separator = 'AND'): static
+ {
+ $this->wheres[] = [
+ 'type' => 'whereVectorDistance',
+ 'column' => $column,
+ 'vector' => $vector,
+ 'maxDistance' => $maxDistance,
+ 'vectorDistance' => $vectorDistance,
+ 'separator' => $separator,
+ ];
+
+ return $this;
+ }
+
+ /**
+ * Adds a vector distance clause.
+ *
+ * @return $this
+ */
+ public function orWhereVectorDistance(string $column, array|string|Subquery $vector, float $maxDistance = 0.2, VectorDistance $vectorDistance = VectorDistance::COSINE): static
+ {
+ return $this->whereVectorDistance($column, $vector, $maxDistance, $vectorDistance, 'OR');
+ }
+
/**
* Adds a BETWEEN clause.
*
@@ -1040,6 +1069,7 @@ public function orHavingRaw(string $raw, string $operator, mixed $value): static
public function orderBy(array|Raw|string $columns, string $order = 'ASC'): static
{
$this->orderings[] = [
+ 'type' => 'basicOrdering',
'column' => is_array($columns) ? $columns : [$columns],
'order' => ($order === 'ASC' || $order === 'asc') ? 'ASC' : 'DESC',
];
@@ -1097,6 +1127,38 @@ public function descendingRaw(string $raw, array $parameters = []): static
return $this->orderByRaw($raw, $parameters, 'DESC');
}
+ /**
+ * Adds a vector ORDER BY clause.
+ */
+ public function orderByVectorDistance(string $column, array|string|Subquery $vector, VectorDistance $vectorDistance = VectorDistance::COSINE, string $order = 'ASC'): static
+ {
+ $this->orderings[] = [
+ 'type' => 'vectorDistanceOrdering',
+ 'column' => $column,
+ 'vector' => $vector,
+ 'vectorDistance' => $vectorDistance,
+ 'order' => ($order === 'ASC' || $order === 'asc') ? 'ASC' : 'DESC',
+ ];
+
+ return $this;
+ }
+
+ /**
+ * Adds a ascending vector ORDER BY clause.
+ */
+ public function ascendingVectorDistance(string $column, array|string|Subquery $vector, VectorDistance $vectorDistance = VectorDistance::COSINE): static
+ {
+ return $this->orderByVectorDistance($column, $vector, $vectorDistance, 'ASC');
+ }
+
+ /**
+ * Adds a descending vector ORDER BY clause.
+ */
+ public function descendingVectorDistance(string $column, array|string|Subquery $vector, VectorDistance $vectorDistance = VectorDistance::COSINE): static
+ {
+ return $this->orderByVectorDistance($column, $vector, $vectorDistance, 'DESC');
+ }
+
/**
* Clears the ordering clauses.
*
diff --git a/src/mako/database/query/VectorDistance.php b/src/mako/database/query/VectorDistance.php
new file mode 100644
index 000000000..52a23b6dd
--- /dev/null
+++ b/src/mako/database/query/VectorDistance.php
@@ -0,0 +1,17 @@
+getSql();
}
+ /**
+ * Compiles a value.
+ */
+ protected function value(ValueInterface $value): string
+ {
+ $parameters = $value->getParameters();
+
+ if (!empty($parameters)) {
+ $this->params = [...$this->params, ...$parameters];
+ }
+
+ $sql = $value->getSql($this);
+
+ if ($value instanceof ValueWithAliasInterface) {
+ if (($alias = $value->getAlias()) !== null) {
+ $sql .= " AS {$this->escapeIdentifier($alias)}";
+ }
+ }
+
+ return $sql;
+ }
+
/**
* Compiles a subselect and merges the parameters.
*/
@@ -210,11 +234,13 @@ public function escapeTableNames(array $tables): string
*/
public function table(Raw|string|Subquery $table): string
{
- if ($table instanceof Raw) {
- return $this->raw($table);
- }
- elseif ($table instanceof Subquery) {
- return $this->subquery($table);
+ if (is_object($table)) {
+ if ($table instanceof Raw) {
+ return $this->raw($table);
+ }
+ elseif ($table instanceof Subquery) {
+ return $this->subquery($table);
+ }
}
return $this->escapeTableNameWithAlias($table);
@@ -286,15 +312,21 @@ public function columnNames(array $columns): string
/**
* Compiles a column.
*/
- public function column(Raw|string|Subquery $column, bool $allowAlias = false): string
+ public function column(Raw|string|Subquery|ValueInterface $column, bool $allowAlias = false): string
{
- if ($column instanceof Raw) {
- return $this->raw($column);
- }
- elseif ($column instanceof Subquery) {
- return $this->subquery($column);
+ if (is_object($column)) {
+ if ($column instanceof Raw) {
+ return $this->raw($column);
+ }
+ elseif ($column instanceof Subquery) {
+ return $this->subquery($column);
+ }
+ elseif ($column instanceof ValueInterface) {
+ return $this->value($column);
+ }
}
- elseif ($allowAlias && stripos($column, ' AS ') !== false) {
+
+ if ($allowAlias && stripos($column, ' AS ') !== false) {
[$column, , $alias] = explode(' ', $column, 3);
return "{$this->columnName($column)} AS {$this->columnName($alias)}";
@@ -378,6 +410,9 @@ protected function param(mixed $param, bool $enclose = true): string
return '?';
}
+ elseif ($param instanceof ValueInterface) {
+ return $this->value($param);
+ }
}
$this->params[] = $param;
@@ -483,6 +518,14 @@ protected function whereColumn(array $where): string
return "{$this->columnName($where['column1'])} {$where['operator']} {$this->columnName($where['column2'])}";
}
+ /**
+ * Compiles vector distance clauses.
+ */
+ protected function whereVectorDistance(array $where): string
+ {
+ throw new DatabaseException(sprintf('The [ %s ] query compiler does not support vector distance calculations.', static::class));
+ }
+
/**
* Compiles BETWEEN clauses.
*/
@@ -631,6 +674,22 @@ protected function groupings(array $groupings): string
return empty($groupings) ? '' : " GROUP BY {$this->columns($groupings)}";
}
+ /**
+ * Compiles a basic ordering clause.
+ */
+ protected function basicOrdering(array $order): string
+ {
+ return "{$this->columns($order['column'])} {$order['order']}";
+ }
+
+ /**
+ * Compiles vector distance ordering clause.
+ */
+ protected function vectorDistanceOrdering(array $order): string
+ {
+ throw new DatabaseException(sprintf('The [ %s ] query compiler does not support vector distance calculations.', static::class));
+ }
+
/**
* Compiles ORDER BY clauses.
*/
@@ -643,7 +702,7 @@ protected function orderings(array $orderings): string
$sql = [];
foreach ($orderings as $order) {
- $sql[] = "{$this->columns($order['column'])} {$order['order']}";
+ $sql[] = $this->{$order['type']}($order);
}
return ' ORDER BY ' . implode(', ', $sql);
diff --git a/src/mako/database/query/compilers/MariaDB.php b/src/mako/database/query/compilers/MariaDB.php
index ff6d6a214..bc9074f54 100644
--- a/src/mako/database/query/compilers/MariaDB.php
+++ b/src/mako/database/query/compilers/MariaDB.php
@@ -7,13 +7,62 @@
namespace mako\database\query\compilers;
+use mako\database\query\Subquery;
+use mako\database\query\VectorDistance;
use Override;
+use function is_array;
+use function json_encode;
+
/**
* Compiles MariaDB queries.
*/
class MariaDB extends MySQL
{
+ /**
+ * Returns a vector distance calculation.
+ */
+ protected function vectorDistance(array $vectorDistance): string
+ {
+ $vector = $vectorDistance['vector'];
+
+ if ($vector instanceof Subquery) {
+ $vector = $this->subquery($vector);
+ }
+ else {
+ if (is_array($vector)) {
+ $vector = json_encode($vector);
+ }
+
+ $vector = "VEC_FromText({$this->param($vector)})";
+ }
+
+ $function = match ($vectorDistance['vectorDistance']) {
+ VectorDistance::COSINE => 'VEC_DISTANCE_COSINE',
+ VectorDistance::EUCLIDEAN => 'VEC_DISTANCE_EUCLIDEAN',
+ };
+
+ return "{$function}({$this->column($vectorDistance['column'], false)}, {$vector})";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ protected function whereVectorDistance(array $where): string
+ {
+ return "{$this->vectorDistance($where)} <= {$this->param($where['maxDistance'])}";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ protected function vectorDistanceOrdering(array $order): string
+ {
+ return "{$this->vectorDistance($order)} {$order['order']}";
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/mako/database/query/compilers/MySQL.php b/src/mako/database/query/compilers/MySQL.php
index b142cf595..8cc81fde5 100644
--- a/src/mako/database/query/compilers/MySQL.php
+++ b/src/mako/database/query/compilers/MySQL.php
@@ -8,8 +8,12 @@
namespace mako\database\query\compilers;
use mako\database\query\compilers\traits\JsonPathBuilderTrait;
+use mako\database\query\Subquery;
+use mako\database\query\VectorDistance;
use Override;
+use function is_array;
+use function json_encode;
use function str_replace;
/**
@@ -52,6 +56,50 @@ protected function buildJsonSet(string $column, array $segments, string $param):
return "{$column} = JSON_SET({$column}, '{$this->buildJsonPath($segments)}', CAST({$param} AS JSON))";
}
+ /**
+ * Returns a vector distance calculation.
+ */
+ protected function vectorDistance(array $vectorDistance): string
+ {
+ $vector = $vectorDistance['vector'];
+
+ if ($vector instanceof Subquery) {
+ $vector = $this->subquery($vector);
+ }
+ else {
+ if (is_array($vector)) {
+ $vector = json_encode($vector);
+ }
+
+ $vector = "STRING_TO_VECTOR({$this->param($vector)})";
+ }
+
+ $function = match ($vectorDistance['vectorDistance']) {
+ VectorDistance::COSINE => 'COSINE',
+ VectorDistance::EUCLIDEAN => 'EUCLIDEAN',
+ };
+
+ return "DISTANCE({$this->column($vectorDistance['column'], false)}, {$vector}, '{$function}')";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ protected function whereVectorDistance(array $where): string
+ {
+ return "{$this->vectorDistance($where)} <= {$this->param($where['maxDistance'])}";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ protected function vectorDistanceOrdering(array $order): string
+ {
+ return "{$this->vectorDistance($order)} {$order['order']}";
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/mako/database/query/compilers/Postgres.php b/src/mako/database/query/compilers/Postgres.php
index 1d5717eac..39e73b51b 100644
--- a/src/mako/database/query/compilers/Postgres.php
+++ b/src/mako/database/query/compilers/Postgres.php
@@ -7,11 +7,15 @@
namespace mako\database\query\compilers;
+use mako\database\query\Subquery;
+use mako\database\query\VectorDistance;
use Override;
use function array_pop;
use function implode;
+use function is_array;
use function is_numeric;
+use function json_encode;
use function str_replace;
/**
@@ -55,6 +59,50 @@ protected function buildJsonSet(string $column, array $segments, string $param):
return $column . " = JSONB_SET({$column}, '{" . str_replace("'", "''", implode(',', $segments)) . "}', '{$param}')";
}
+ /**
+ * Returns a vector distance calculation.
+ */
+ protected function vectorDistance(array $vectorDistance): string
+ {
+ $vector = $vectorDistance['vector'];
+
+ if ($vector instanceof Subquery) {
+ $vector = $this->subquery($vector);
+ }
+ else {
+ if (is_array($vector)) {
+ $vector = json_encode($vector);
+ }
+
+ $vector = $this->param($vector);
+ }
+
+ $function = match ($vectorDistance['vectorDistance']) {
+ VectorDistance::COSINE => '<=>',
+ VectorDistance::EUCLIDEAN => '<->',
+ };
+
+ return "{$this->column($vectorDistance['column'], false)} {$function} {$vector}";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ protected function whereVectorDistance(array $where): string
+ {
+ return "{$this->vectorDistance($where)} <= {$this->param($where['maxDistance'])}";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ protected function vectorDistanceOrdering(array $order): string
+ {
+ return "{$this->vectorDistance($order)} {$order['order']}";
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/src/mako/database/query/values/ValueInterface.php b/src/mako/database/query/values/ValueInterface.php
new file mode 100644
index 000000000..e2e91ae20
--- /dev/null
+++ b/src/mako/database/query/values/ValueInterface.php
@@ -0,0 +1,26 @@
+ 'VEC_FromText(?)',
+ MySQL::class => 'STRING_TO_VECTOR(?)',
+ Postgres::class => '?',
+ default => throw new DatabaseException(sprintf('Vector values are not supported by the [ %s ] compiler.', $compiler::class)),
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ public function getParameters(): ?array
+ {
+ return [
+ is_array($this->vector) ? json_encode($this->vector) : $this->vector,
+ ];
+ }
+}
diff --git a/src/mako/database/query/values/out/Value.php b/src/mako/database/query/values/out/Value.php
new file mode 100644
index 000000000..2b6d6563b
--- /dev/null
+++ b/src/mako/database/query/values/out/Value.php
@@ -0,0 +1,47 @@
+alias = $alias;
+
+ return $this;
+ }
+
+ /**
+ * Returns the value alias.
+ */
+ public function getAlias(): ?string
+ {
+ return $this->alias;
+ }
+}
diff --git a/src/mako/database/query/values/out/ValueWithAliasInterface.php b/src/mako/database/query/values/out/ValueWithAliasInterface.php
new file mode 100644
index 000000000..908d9ac02
--- /dev/null
+++ b/src/mako/database/query/values/out/ValueWithAliasInterface.php
@@ -0,0 +1,28 @@
+ "VEC_ToText({$compiler->escapeColumnName($this->column)})",
+ MySQL::class => "VECTOR_TO_STRING({$compiler->escapeColumnName($this->column)})",
+ Postgres::class => "{$compiler->escapeColumnName($this->column)}",
+ default => throw new DatabaseException(sprintf('Vector values are not supported by the [ %s ] compiler.', $compiler::class)),
+ };
+ }
+}
diff --git a/src/mako/database/query/values/out/VectorDistance.php b/src/mako/database/query/values/out/VectorDistance.php
new file mode 100644
index 000000000..97d9c8ff4
--- /dev/null
+++ b/src/mako/database/query/values/out/VectorDistance.php
@@ -0,0 +1,96 @@
+vectorDistance) {
+ VectorDistanceType::COSINE => 'VEC_DISTANCE_COSINE',
+ VectorDistanceType::EUCLIDEAN => 'VEC_DISTANCE_EUCLIDEAN',
+ };
+
+ return "{$function}({$compiler->escapeColumnName($this->column)}, VEC_FromText(?))";
+ }
+
+ /**
+ * Gets the MySQL distance SQL.
+ */
+ protected function getMySqlDistance(Compiler $compiler): string
+ {
+ $function = match ($this->vectorDistance) {
+ VectorDistanceType::COSINE => 'COSINE',
+ VectorDistanceType::EUCLIDEAN => 'EUCLIDEAN',
+ };
+
+ return "DISTANCE({$compiler->escapeColumnName($this->column)}, STRING_TO_VECTOR(?), '{$function}')";
+ }
+
+ /**
+ * Gets the Postgres distance SQL.
+ */
+ protected function getPostgresDistance(Compiler $compiler): string
+ {
+ $function = match ($this->vectorDistance) {
+ VectorDistanceType::COSINE => '<=>',
+ VectorDistanceType::EUCLIDEAN => '<->',
+ };
+
+ return "{$compiler->columnName($this->column)} {$function} ?";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ public function getSql(Compiler $compiler): string
+ {
+ return match ($compiler::class) {
+ MariaDB::class => $this->getMariaDbDistance($compiler),
+ MySQL::class => $this->getMySqlDistance($compiler),
+ Postgres::class => $this->getPostgresDistance($compiler),
+ default => throw new DatabaseException(sprintf('Vector values are not supported by the [ %s ] compiler.', $compiler::class)),
+ };
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ #[Override]
+ public function getParameters(): ?array
+ {
+ return [
+ is_array($this->vector) ? json_encode($this->vector) : $this->vector,
+ ];
+ }
+}
diff --git a/tests/unit/database/midgard/QueryTest.php b/tests/unit/database/midgard/QueryTest.php
index 20357f881..939fca02a 100644
--- a/tests/unit/database/midgard/QueryTest.php
+++ b/tests/unit/database/midgard/QueryTest.php
@@ -404,7 +404,7 @@ public function testBatch(): void
});
- $this->assertEquals([['column' => ['foobar'], 'order' => 'ASC']], $query->getOrderings());
+ $this->assertEquals([['type' => 'basicOrdering', 'column' => ['foobar'], 'order' => 'ASC']], $query->getOrderings());
//
@@ -419,6 +419,6 @@ public function testBatch(): void
});
- $this->assertEquals([['column' => ['barfoo'], 'order' => 'DESC']], $query->getOrderings());
+ $this->assertEquals([['type' => 'basicOrdering', 'column' => ['barfoo'], 'order' => 'DESC']], $query->getOrderings());
}
}
diff --git a/tests/unit/database/query/compilers/MariaDBCompilerTest.php b/tests/unit/database/query/compilers/MariaDBCompilerTest.php
index 5cdbe7766..5778d5c49 100644
--- a/tests/unit/database/query/compilers/MariaDBCompilerTest.php
+++ b/tests/unit/database/query/compilers/MariaDBCompilerTest.php
@@ -11,6 +11,11 @@
use mako\database\query\compilers\MariaDB as MariaDBCompiler;
use mako\database\query\helpers\HelperInterface;
use mako\database\query\Query;
+use mako\database\query\Subquery;
+use mako\database\query\values\in\Vector as InVector;
+use mako\database\query\values\out\Vector as OutVector;
+use mako\database\query\values\out\VectorDistance as OutVectorDistance;
+use mako\database\query\VectorDistance;
use mako\tests\TestCase;
use Mockery;
use Mockery\MockInterface;
@@ -43,6 +48,263 @@ protected function getBuilder($table = 'foobar')
return (new Query($this->getConnection()))->table($table);
}
+ /**
+ *
+ */
+ public function testBasicCosineWhereVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', [1, 2, 3, 4, 5], maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` WHERE VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?)) <= ?', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testBasicEuclidianWhereVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', [1, 2, 3, 4, 5], maxDistance: 0.5, vectorDistance: VectorDistance::EUCLIDEAN)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` WHERE VEC_DISTANCE_EUCLIDEAN(`embedding`, VEC_FromText(?)) <= ?', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testBasicCosineWhereVectorDistanceWithStringVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', '[1,2,3,4,5]', maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` WHERE VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?)) <= ?', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testCosineWhereVectorDistanceFromSubquery(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', new Subquery(function (Query $query): void {
+ $query->table('embeddings')->select(['embedding'])->where('id', '=', 1);
+ }), maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` WHERE VEC_DISTANCE_COSINE(`embedding`, (SELECT `embedding` FROM `embeddings` WHERE `id` = ?)) <= ?', $query['sql']);
+ $this->assertEquals([1, 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosine(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` ORDER BY VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?)) ASC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosineWithStringVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', '[1,2,3,4,5]')
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` ORDER BY VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?)) ASC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosineWithSubqueryVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', new Subquery(function (Query $query): void {
+ $query->table('embeddings')->select(['embedding'])->where('id', '=', 1);
+ }))
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` ORDER BY VEC_DISTANCE_COSINE(`embedding`, (SELECT `embedding` FROM `embeddings` WHERE `id` = ?)) ASC', $query['sql']);
+ $this->assertEquals([1], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceEuclidean(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', [1, 2, 3, 4, 5], VectorDistance::EUCLIDEAN)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` ORDER BY VEC_DISTANCE_EUCLIDEAN(`embedding`, VEC_FromText(?)) ASC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testAscendingVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->ascendingVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` ORDER BY VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?)) ASC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testDescendingVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->descendingVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM `foobar` ORDER BY VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?)) DESC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVector('embedding')])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT VEC_ToText(`embedding`) FROM `foobar`', $query['sql']);
+ $this->assertEquals([], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorSelectValueWithAlias(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVector('embedding')->as('vector')])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT VEC_ToText(`embedding`) AS `vector` FROM `foobar`', $query['sql']);
+ $this->assertEquals([], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorCosineDistanceSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4])])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?)) FROM `foobar`', $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorEuclideanDistanceSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4], VectorDistance::EUCLIDEAN)])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT VEC_DISTANCE_EUCLIDEAN(`embedding`, VEC_FromText(?)) FROM `foobar`', $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorDistanceSelectValueWithAlias(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4])->as('distance')])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?)) AS `distance` FROM `foobar`', $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorInsertValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->getCompiler()->insert(['embedding' => new InVector([1, 2, 3])]);
+
+ $this->assertEquals('INSERT INTO `foobar` (`embedding`) VALUES (VEC_FromText(?))', $query['sql']);
+ $this->assertEquals(['[1,2,3]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testStringVectorInsertValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->getCompiler()->insert(['embedding' => new InVector('[1,2,3]')]);
+
+ $this->assertEquals('INSERT INTO `foobar` (`embedding`) VALUES (VEC_FromText(?))', $query['sql']);
+ $this->assertEquals(['[1,2,3]'], $query['params']);
+ }
+
/**
*
*/
diff --git a/tests/unit/database/query/compilers/MySQLCompilerTest.php b/tests/unit/database/query/compilers/MySQLCompilerTest.php
index 35a14ad41..355e695e9 100644
--- a/tests/unit/database/query/compilers/MySQLCompilerTest.php
+++ b/tests/unit/database/query/compilers/MySQLCompilerTest.php
@@ -11,6 +11,11 @@
use mako\database\query\compilers\MySQL as MySQLCompiler;
use mako\database\query\helpers\HelperInterface;
use mako\database\query\Query;
+use mako\database\query\Subquery;
+use mako\database\query\values\in\Vector as InVector;
+use mako\database\query\values\out\Vector as OutVector;
+use mako\database\query\values\out\VectorDistance as OutVectorDistance;
+use mako\database\query\VectorDistance;
use mako\tests\TestCase;
use Mockery;
use Mockery\MockInterface;
@@ -232,6 +237,263 @@ public function testBasicInsertWithNoValues(): void
$this->assertEquals([], $query['params']);
}
+ /**
+ *
+ */
+ public function testBasicCosineWhereVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', [1, 2, 3, 4, 5], maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` WHERE DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'COSINE') <= ?", $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testBasicEuclidianWhereVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', [1, 2, 3, 4, 5], maxDistance: 0.5, vectorDistance: VectorDistance::EUCLIDEAN)
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` WHERE DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'EUCLIDEAN') <= ?", $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testBasicCosineWhereVectorDistanceWithStringVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', '[1,2,3,4,5]', maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` WHERE DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'COSINE') <= ?", $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testCosineWhereVectorDistanceFromSubquery(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', new Subquery(function (Query $query): void {
+ $query->table('embeddings')->select(['embedding'])->where('id', '=', 1);
+ }), maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` WHERE DISTANCE(`embedding`, (SELECT `embedding` FROM `embeddings` WHERE `id` = ?), 'COSINE') <= ?", $query['sql']);
+ $this->assertEquals([1, 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosine(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` ORDER BY DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'COSINE') ASC", $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosineWithStringVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', '[1,2,3,4,5]')
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` ORDER BY DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'COSINE') ASC", $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosineWithSubqueryVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', new Subquery(function (Query $query): void {
+ $query->table('embeddings')->select(['embedding'])->where('id', '=', 1);
+ }))
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` ORDER BY DISTANCE(`embedding`, (SELECT `embedding` FROM `embeddings` WHERE `id` = ?), 'COSINE') ASC", $query['sql']);
+ $this->assertEquals([1], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceEuclidean(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', [1, 2, 3, 4, 5], VectorDistance::EUCLIDEAN)
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` ORDER BY DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'EUCLIDEAN') ASC", $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testAscendingVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->ascendingVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` ORDER BY DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'COSINE') ASC", $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testDescendingVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->descendingVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT * FROM `foobar` ORDER BY DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'COSINE') DESC", $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVector('embedding')])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT VECTOR_TO_STRING(`embedding`) FROM `foobar`', $query['sql']);
+ $this->assertEquals([], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorSelectValueWithAlias(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVector('embedding')->as('vector')])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT VECTOR_TO_STRING(`embedding`) AS `vector` FROM `foobar`', $query['sql']);
+ $this->assertEquals([], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorCosineDistanceSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4])])
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'COSINE') FROM `foobar`", $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorEuclideanDistanceSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4], VectorDistance::EUCLIDEAN)])
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'EUCLIDEAN') FROM `foobar`", $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorDistanceSelectValueWithAlias(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4])->as('distance')])
+ ->getCompiler()->select();
+
+ $this->assertEquals("SELECT DISTANCE(`embedding`, STRING_TO_VECTOR(?), 'COSINE') AS `distance` FROM `foobar`", $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorInsertValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->getCompiler()->insert(['embedding' => new InVector([1, 2, 3])]);
+
+ $this->assertEquals('INSERT INTO `foobar` (`embedding`) VALUES (STRING_TO_VECTOR(?))', $query['sql']);
+ $this->assertEquals(['[1,2,3]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testStringVectorInsertValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->getCompiler()->insert(['embedding' => new InVector('[1,2,3]')]);
+
+ $this->assertEquals('INSERT INTO `foobar` (`embedding`) VALUES (STRING_TO_VECTOR(?))', $query['sql']);
+ $this->assertEquals(['[1,2,3]'], $query['params']);
+ }
+
/**
*
*/
diff --git a/tests/unit/database/query/compilers/PostgresCompilerTest.php b/tests/unit/database/query/compilers/PostgresCompilerTest.php
index bccb430bd..18e290744 100644
--- a/tests/unit/database/query/compilers/PostgresCompilerTest.php
+++ b/tests/unit/database/query/compilers/PostgresCompilerTest.php
@@ -11,6 +11,11 @@
use mako\database\query\compilers\Postgres as PostgresCompiler;
use mako\database\query\helpers\HelperInterface;
use mako\database\query\Query;
+use mako\database\query\Subquery;
+use mako\database\query\values\in\Vector as InVector;
+use mako\database\query\values\out\Vector as OutVector;
+use mako\database\query\values\out\VectorDistance as OutVectorDistance;
+use mako\database\query\VectorDistance;
use mako\tests\TestCase;
use Mockery;
use Mockery\MockInterface;
@@ -204,6 +209,263 @@ public function testUpdateWithJSONColumn(): void
$this->assertEquals([1], $query['params']);
}
+ /**
+ *
+ */
+ public function testBasicCosineWhereVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', [1, 2, 3, 4, 5], maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" WHERE "embedding" <=> ? <= ?', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testBasicEuclidianWhereVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', [1, 2, 3, 4, 5], maxDistance: 0.5, vectorDistance: VectorDistance::EUCLIDEAN)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" WHERE "embedding" <-> ? <= ?', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testCosineWhereVectorDistanceStringVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', '[1,2,3,4,5]', maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" WHERE "embedding" <=> ? <= ?', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]', 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testCosineWhereVectorDistanceFromSubquery(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->whereVectorDistance('embedding', new Subquery(function (Query $query): void {
+ $query->table('embeddings')->select(['embedding'])->where('id', '=', 1);
+ }), maxDistance: 0.5)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" WHERE "embedding" <=> (SELECT "embedding" FROM "embeddings" WHERE "id" = ?) <= ?', $query['sql']);
+ $this->assertEquals([1, 0.5], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosine(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" ORDER BY "embedding" <=> ? ASC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosineWithStringVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', '[1,2,3,4,5]')
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" ORDER BY "embedding" <=> ? ASC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceCosineWithSubqueryVector(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', new Subquery(function (Query $query): void {
+ $query->table('embeddings')->select(['embedding'])->where('id', '=', 1);
+ }))
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" ORDER BY "embedding" <=> (SELECT "embedding" FROM "embeddings" WHERE "id" = ?) ASC', $query['sql']);
+ $this->assertEquals([1], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testOrderByVectorDistanceEuclidean(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->orderByVectorDistance('embedding', [1, 2, 3, 4, 5], VectorDistance::EUCLIDEAN)
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" ORDER BY "embedding" <-> ? ASC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testAscendingVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->ascendingVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" ORDER BY "embedding" <=> ? ASC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testDescendingVectorDistance(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->descendingVectorDistance('embedding', [1, 2, 3, 4, 5])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT * FROM "foobar" ORDER BY "embedding" <=> ? DESC', $query['sql']);
+ $this->assertEquals(['[1,2,3,4,5]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVector('embedding')])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT "embedding" FROM "foobar"', $query['sql']);
+ $this->assertEquals([], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorSelectValueWithAlias(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVector('embedding')->as('vector')])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT "embedding" AS "vector" FROM "foobar"', $query['sql']);
+ $this->assertEquals([], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorCosineDistanceSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4])])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT "embedding" <=> ? FROM "foobar"', $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorEuclideanDistanceSelectValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4], VectorDistance::EUCLIDEAN)])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT "embedding" <-> ? FROM "foobar"', $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorDistanceSelectValueWithAlias(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->select([new OutVectorDistance('embedding', [1, 2, 3, 4])->as('distance')])
+ ->getCompiler()->select();
+
+ $this->assertEquals('SELECT "embedding" <=> ? AS "distance" FROM "foobar"', $query['sql']);
+ $this->assertEquals(['[1,2,3,4]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testVectorInsertValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->getCompiler()->insert(['embedding' => new InVector([1, 2, 3])]);
+
+ $this->assertEquals('INSERT INTO "foobar" ("embedding") VALUES (?)', $query['sql']);
+ $this->assertEquals(['[1,2,3]'], $query['params']);
+ }
+
+ /**
+ *
+ */
+ public function testStringVectorInsertValue(): void
+ {
+ $query = $this->getBuilder();
+
+ $query = $query->table('foobar')
+ ->getCompiler()->insert(['embedding' => new InVector('[1,2,3]')]);
+
+ $this->assertEquals('INSERT INTO "foobar" ("embedding") VALUES (?)', $query['sql']);
+ $this->assertEquals(['[1,2,3]'], $query['params']);
+ }
+
/**
*
*/