summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrant Lanham <contact@grantlanham.com>2024-09-29 20:56:59 -0400
committerMarkus Heiser <markus.heiser@darmarIT.de>2024-10-03 13:04:06 +0200
commit2a29e16d25ae19d9216b959f177cdcd71c43511e (patch)
treee41231c4d32c3a9ebca3b21a488d4cfd38cc0578
parentd48f04e8094c8b9ddb7808a9798f71549146a38e (diff)
downloadsearxng-2a29e16d25ae19d9216b959f177cdcd71c43511e.tar.gz
searxng-2a29e16d25ae19d9216b959f177cdcd71c43511e.zip
[feat] implement mariadb engine
-rw-r--r--searx/engines/mariadb_server.py79
-rw-r--r--searx/settings.yml10
-rw-r--r--tests/unit/test_engine_mariadb_server.py44
-rw-r--r--tests/unit/test_engine_tineye.py (renamed from tests/unit/test_tineye.py)0
4 files changed, 133 insertions, 0 deletions
diff --git a/searx/engines/mariadb_server.py b/searx/engines/mariadb_server.py
new file mode 100644
index 000000000..7cf7eec33
--- /dev/null
+++ b/searx/engines/mariadb_server.py
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+"""MariaDB is a community driven fork of MySQL. Before enabling MariaDB engine,
+you must the install the pip package ``mariadb`` along with the necessary
+prerequities.
+
+`See the following documentation for more details
+<https://mariadb.com/docs/server/connect/programming-languages/c/install/>`_
+
+Example
+=======
+
+This is an example configuration for querying a MariaDB server:
+
+.. code:: yaml
+
+ - name: my_database
+ engine: mariadb_server
+ database: my_database
+ username: searxng
+ password: password
+ limit: 5
+ query_str: 'SELECT * from my_table WHERE my_column=%(query)s'
+
+"""
+
+from typing import TYPE_CHECKING
+
+try:
+ import mariadb
+except ImportError:
+ # import error is ignored because the admin has to install mysql manually to use
+ # the engine
+ pass
+
+if TYPE_CHECKING:
+ import logging
+
+ logger = logging.getLogger()
+
+
+engine_type = 'offline'
+host = "127.0.0.1"
+port = 3306
+database = ""
+username = ""
+password = ""
+query_str = ""
+limit = 10
+paging = True
+result_template = 'key-value.html'
+_connection = None
+
+
+def init(engine_settings):
+ global _connection # pylint: disable=global-statement
+
+ if 'query_str' not in engine_settings:
+ raise ValueError('query_str cannot be empty')
+
+ if not engine_settings['query_str'].lower().startswith('select '):
+ raise ValueError('only SELECT query is supported')
+
+ _connection = mariadb.connect(database=database, user=username, password=password, host=host, port=port)
+
+
+def search(query, params):
+ query_params = {'query': query}
+ query_to_run = query_str + ' LIMIT {0} OFFSET {1}'.format(limit, (params['pageno'] - 1) * limit)
+ logger.debug("SQL Query: %s", query_to_run)
+
+ with _connection.cursor() as cur:
+ cur.execute(query_to_run, query_params)
+ results = []
+ col_names = [i[0] for i in cur.description]
+ for res in cur:
+ result = dict(zip(col_names, map(str, res)))
+ result['template'] = result_template
+ results.append(result)
+ return results
diff --git a/searx/settings.yml b/searx/settings.yml
index 44245ab7c..8b264eaf6 100644
--- a/searx/settings.yml
+++ b/searx/settings.yml
@@ -2031,6 +2031,16 @@ engines:
# query_str: 'SELECT * from mytable WHERE fieldname=%(query)s'
# shortcut: mysql
+ # Required dependency: mariadb
+ # - name: mariadb
+ # engine: mariadb_server
+ # database: mydatabase
+ # username: user
+ # password: pass
+ # limit: 10
+ # query_str: 'SELECT * from mytable WHERE fieldname=%(query)s'
+ # shortcut: mdb
+
- name: 1337x
engine: 1337x
shortcut: 1337x
diff --git a/tests/unit/test_engine_mariadb_server.py b/tests/unit/test_engine_mariadb_server.py
new file mode 100644
index 000000000..423132e34
--- /dev/null
+++ b/tests/unit/test_engine_mariadb_server.py
@@ -0,0 +1,44 @@
+# SPDX-License-Identifier: AGPL-3.0-or-later
+# pylint: disable=missing-module-docstring
+
+from unittest.mock import MagicMock, Mock
+from searx.engines import load_engines, mariadb_server
+from tests import SearxTestCase
+
+
+class MariadbServerTests(SearxTestCase): # pylint: disable=missing-class-docstring
+ def setUp(self):
+ load_engines(
+ [
+ {
+ 'name': 'mariadb server',
+ 'engine': 'mariadb_server',
+ 'shortcut': 'mdb',
+ 'timeout': 9.0,
+ 'disabled': True,
+ }
+ ]
+ )
+
+ def tearDown(self):
+ load_engines([])
+
+ def test_init_no_query_str_raises(self):
+ self.assertRaises(ValueError, lambda: mariadb_server.init({}))
+
+ def test_init_non_select_raises(self):
+ self.assertRaises(ValueError, lambda: mariadb_server.init({'query_str': 'foobar'}))
+
+ def test_search_returns_results(self):
+ test_string = 'FOOBAR'
+ cursor_mock = MagicMock()
+ with cursor_mock as setup: # pylint: disable=not-context-manager
+ setup.__iter__ = Mock(return_value=iter([{test_string, 1}]))
+ setup.description = [[test_string]]
+ conn_mock = Mock()
+ conn_mock.cursor.return_value = cursor_mock
+ mariadb_server._connection = conn_mock # pylint: disable=protected-access
+ results = mariadb_server.search(test_string, {'pageno': 1})
+ self.assertEqual(1, len(results))
+ self.assertIn(test_string, results[0])
+ self.assertEqual(mariadb_server.result_template, results[0]['template'])
diff --git a/tests/unit/test_tineye.py b/tests/unit/test_engine_tineye.py
index 5855a7313..5855a7313 100644
--- a/tests/unit/test_tineye.py
+++ b/tests/unit/test_engine_tineye.py