1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-30 09:39:51 +02:00

Elasticsearch: New condition operators as the combination of query type and match type

- Support for regexp conditions.
- Proper formatting of boolean values.
This commit is contained in:
Peter Knut
2024-10-12 01:33:25 +02:00
parent 13752c0498
commit 3e81c3871f
3 changed files with 89 additions and 57 deletions

View File

@@ -318,6 +318,11 @@ class Adminer {
* @return string
*/
function editVal($val, $field) {
// Format Elasticsearch boolean value, but do not touch PostgreSQL boolean that use string value 't' or 'f'.
if ($field["type"] == "boolean" && is_bool($val)) {
return $val ? "true" : "false";
}
return $val;
}
@@ -627,6 +632,8 @@ class Adminer {
&& (preg_match('~^[-\d.' . (preg_match('~IN$~', $op) ? ',' : '') . ']+$~', $val) || !preg_match('~' . number_type() . '|bit~', $field["type"]))
&& (!preg_match("~[\x80-\xFF]~", $val) || preg_match('~char|text|enum|set~', $field["type"]))
&& (!preg_match('~date|timestamp~', $field["type"]) || preg_match('~^\d+-\d+-\d+~', $val))
&& (!preg_match('~^elastic~', DRIVER) || $field["type"] != "boolean" || preg_match('~true|false~', $val)) // Elasticsearch needs boolean value properly formatted.
&& (!preg_match('~^elastic~', DRIVER) || strpos($op, "regexp") === false || preg_match('~text|keyword~', $field["type"])) // Elasticsearch can use regexp only on text and keyword fields.
) {
$cols[] = $prefix . $driver->convertSearch(idf_escape($name), $where, $field) . $cond;
}

View File

@@ -155,28 +155,12 @@ if (isset($_GET["elastic"])) {
foreach ($where as $val) {
if (preg_match('~^\((.+ OR .+)\)$~', $val, $matches)) {
$parts = explode(" OR ", $matches[1]);
$terms = array();
foreach ($parts as $part) {
list($col, $op, $val) = explode(" ", $part, 3);
$term = array($col => $val);
if ($op == "=") {
$terms[] = array("term" => $term);
} elseif (in_array($op, array("must", "should", "must_not"))) {
$data["query"]["bool"][$op][]["match"] = $term;
}
}
if (!empty($terms)) {
$data["query"]["bool"]["filter"][]["bool"]["should"] = $terms;
foreach ($parts as $part) {
$this->addQueryCondition($part, $data);
}
} else {
list($col, $op, $val) = explode(" ", $val, 3);
$term = array($col => $val);
if ($op == "=") {
$data["query"]["bool"]["filter"][] = array("term" => $term);
} elseif (in_array($op, array("must", "should", "must_not"))) {
$data["query"]["bool"][$op][]["match"] = $term;
}
$this->addQueryCondition($val, $data);
}
}
@@ -216,6 +200,33 @@ if (isset($_GET["elastic"])) {
return new Min_Result($return);
}
private function addQueryCondition($val, &$data)
{
list($col, $op, $val) = explode(" ", $val, 3);
if (!preg_match('~^([^(]+)\(([^)]+)\)$~', $op, $matches)) {
return;
}
$queryType = $matches[1]; // must, should, must_not
$matchType = $matches[2]; // term, match, regexp
if ($matchType == "regexp") {
$data["query"]["bool"][$queryType][] = [
"regexp" => [
$col => [
"value" => $val,
"flags" => "ALL",
"case_insensitive" => true,
]
]
];
} else {
$data["query"]["bool"][$queryType][] = [
$matchType => [$col => $val]
];
}
}
function update($type, $record, $queryWhere, $limit = 0, $separator = "\n") {
//! use $limit
$parts = preg_split('~ *= *~', $queryWhere);
@@ -448,18 +459,13 @@ if (isset($_GET["elastic"])) {
$result = array(
"_id" => array(
"field" => "_id",
"full_type" => "text",
"type" => "text",
"full_type" => "_id",
"type" => "_id",
"privileges" => array("insert" => 1, "select" => 1, "where" => 1, "order" => 1),
)
);
foreach ($mappings as $name => $field) {
$has_index = !isset($field["index"]) || $field["index"];
// TODO: privileges: where => $has_index
// TODO: privileges: sort => $field["type"] != "text"
$result[$name] = array(
"field" => $name,
"full_type" => $field["type"],
@@ -564,9 +570,9 @@ if (isset($_GET["elastic"])) {
$structured_types = array();
foreach (array(
lang('Numbers') => array("long" => 3, "integer" => 5, "short" => 8, "byte" => 10, "double" => 20, "float" => 66, "half_float" => 12, "scaled_float" => 21),
lang('Numbers') => array("long" => 3, "integer" => 5, "short" => 8, "byte" => 10, "double" => 20, "float" => 66, "half_float" => 12, "scaled_float" => 21, "boolean" => 1),
lang('Date and time') => array("date" => 10),
lang('Strings') => array("string" => 65535, "text" => 65535),
lang('Strings') => array("string" => 65535, "text" => 65535, "keyword" => 65535),
lang('Binary') => array("binary" => 255),
) as $key => $val) {
$types += $val;
@@ -576,8 +582,13 @@ if (isset($_GET["elastic"])) {
return array(
'possible_drivers' => array("json + allow_url_fopen"),
'jush' => "elastic",
'operators' => array("=", "must", "should", "must_not"),
'operator_like' => "should",
'operators' => array(
"must(term)", "must(match)", "must(regexp)",
"should(term)", "should(match)", "should(regexp)",
"must_not(term)", "must_not(match)", "must_not(regexp)",
),
'operator_like' => "should(match)",
'operator_regexp' => "should(regexp)",
'functions' => array(),
'grouping' => array(),
'edit_functions' => array(array("json")),

View File

@@ -154,28 +154,12 @@ if (isset($_GET["elastic5"])) {
foreach ($where as $val) {
if (preg_match('~^\((.+ OR .+)\)$~', $val, $matches)) {
$parts = explode(" OR ", $matches[1]);
$terms = array();
foreach ($parts as $part) {
list($col, $op, $val) = explode(" ", $part, 3);
$term = array($col => $val);
if ($op == "=") {
$terms[] = array("term" => $term);
} elseif (in_array($op, array("must", "should", "must_not"))) {
$data["query"]["bool"][$op][]["match"] = $term;
}
}
if (!empty($terms)) {
$data["query"]["bool"]["filter"][]["bool"]["should"] = $terms;
foreach ($parts as $part) {
$this->addQueryCondition($part, $data);
}
} else {
list($col, $op, $val) = explode(" ", $val, 3);
$term = array($col => $val);
if ($op == "=") {
$data["query"]["bool"]["filter"][] = array("term" => $term);
} elseif (in_array($op, array("must", "should", "must_not"))) {
$data["query"]["bool"][$op][]["match"] = $term;
}
$this->addQueryCondition($val, $data);
}
}
@@ -218,6 +202,33 @@ if (isset($_GET["elastic5"])) {
return new Min_Result($return);
}
private function addQueryCondition($val, &$data)
{
list($col, $op, $val) = explode(" ", $val, 3);
if (!preg_match('~^([^(]+)\(([^)]+)\)$~', $op, $matches)) {
return;
}
$queryType = $matches[1]; // must, should, must_not
$matchType = $matches[2]; // term, match, regexp
if ($matchType == "regexp") {
$data["query"]["bool"][$queryType][] = [
"regexp" => [
$col => [
"value" => $val,
"flags" => "ALL",
"case_insensitive" => true,
]
]
];
} else {
$data["query"]["bool"][$queryType][] = [
$matchType => [$col => $val]
];
}
}
function update($type, $record, $queryWhere, $limit = 0, $separator = "\n") {
//! use $limit
$parts = preg_split('~ *= *~', $queryWhere);
@@ -427,15 +438,13 @@ if (isset($_GET["elastic5"])) {
$return = array(
"_id" => array(
"field" => "_id",
"full_type" => "text",
"type" => "text",
"full_type" => "_id",
"type" => "_id",
"privileges" => array("insert" => 1, "select" => 1, "where" => 1, "order" => 1),
)
);
foreach ($mappings as $name => $field) {
if (isset($field["index"]) && !$field["index"]) continue;
$return[$name] = array(
"field" => $name,
"full_type" => $field["type"],
@@ -544,9 +553,9 @@ if (isset($_GET["elastic5"])) {
$structured_types = array();
foreach (array(
lang('Numbers') => array("long" => 3, "integer" => 5, "short" => 8, "byte" => 10, "double" => 20, "float" => 66, "half_float" => 12, "scaled_float" => 21),
lang('Numbers') => array("long" => 3, "integer" => 5, "short" => 8, "byte" => 10, "double" => 20, "float" => 66, "half_float" => 12, "scaled_float" => 21, "boolean" => 1),
lang('Date and time') => array("date" => 10),
lang('Strings') => array("string" => 65535, "text" => 65535),
lang('Strings') => array("string" => 65535, "text" => 65535, "keyword" => 65535),
lang('Binary') => array("binary" => 255),
) as $key => $val) {
$types += $val;
@@ -556,8 +565,13 @@ if (isset($_GET["elastic5"])) {
return array(
'possible_drivers' => array("json + allow_url_fopen"),
'jush' => "elastic",
'operators' => array("=", "must", "should", "must_not"),
'operator_like' => "should",
'operators' => array(
"must(term)", "must(match)", "must(regexp)",
"should(term)", "should(match)", "should(regexp)",
"must_not(term)", "must_not(match)", "must_not(regexp)",
),
'operator_like' => "should(match)",
'operator_regexp' => "should(regexp)",
'functions' => array(),
'grouping' => array(),
'edit_functions' => array(array("json")),