Issues (104)

driver/postgres.php (9 issues)

Labels
Severity
1
<?php
2
/**
3
 *
4
 * Precise Similar Topics
5
 *
6
 * @copyright (c) 2018 Matt Friedman
7
 * @license GNU General Public License, version 2 (GPL-2.0)
8
 *
9
 */
10
11
namespace vse\similartopics\driver;
12
13
/**
14
 * This class handles similar topics queries for PostgreSQL dbms
15
 */
16
class postgres implements driver_interface
17
{
18
	/** @var \phpbb\db\driver\driver_interface */
0 ignored issues
show
The type phpbb\db\driver\driver_interface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
19
	protected $db;
20
21
	/** @var \phpbb\config\config */
0 ignored issues
show
The type phpbb\config\config was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
	protected $config;
23
24
	/** @var string */
25
	protected $ts_name;
26
27
	/**
28
	 * Constructor
29
	 *
30
	 * @param \phpbb\db\driver\driver_interface $db
31
	 * @param \phpbb\config\config              $config
32
	 */
33
	public function __construct(\phpbb\db\driver\driver_interface $db, \phpbb\config\config $config)
34
	{
35
		$this->db = $db;
36
		$this->config = $config;
37
38
		$this->set_ts_name($config['pst_postgres_ts_name']);
39
	}
40
41
	/**
42
	 * {@inheritdoc}
43
	 */
44
	public function get_name()
45
	{
46
		return 'postgres';
47
	}
48
49
	/**
50
	 * {@inheritdoc}
51
	 */
52
	public function get_type()
53
	{
54
		return 'postgres';
55
	}
56
57
	/**
58
	 * {@inheritdoc}
59
	 */
60
	public function get_query($topic_id, $topic_title, $length, $sensitivity)
61
	{
62
		$ts_name = $this->db->sql_escape($this->ts_name);
63
		$ts_query_text = $this->db->sql_escape(preg_replace(['/\s+/', '/\'/'], ['|', ''], $topic_title));
64
		$ts_rank_cd = "ts_rank_cd('{1,1,1,1}', to_tsvector('$ts_name', t.topic_title), to_tsquery('$ts_name', '$ts_query_text'), 32)";
65
66
		return array(
67
			'SELECT'	=> "f.forum_id, f.forum_name, t.*, $ts_rank_cd AS score",
68
69
			'FROM'		=> array(
70
				TOPICS_TABLE	=> 't',
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
71
			),
72
			'LEFT_JOIN'	=> array(
73
				array(
74
					'FROM'	=>	array(FORUMS_TABLE	=> 'f'),
0 ignored issues
show
The constant vse\similartopics\driver\FORUMS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
75
					'ON'	=> 'f.forum_id = t.forum_id',
76
				),
77
			),
78
			'WHERE'		=> "to_tsquery('$ts_name', '$ts_query_text') @@ to_tsvector('$ts_name', t.topic_title) AND $ts_rank_cd >= " . (float) $sensitivity . '
79
				AND t.topic_status <> ' . ITEM_MOVED . '
0 ignored issues
show
The constant vse\similartopics\driver\ITEM_MOVED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
80
				AND t.topic_visibility = ' . ITEM_APPROVED . '
0 ignored issues
show
The constant vse\similartopics\driver\ITEM_APPROVED was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
81
				AND t.topic_time > (extract(epoch from current_timestamp)::integer - ' . (int) $length . ')
82
				AND t.topic_id <> ' . (int) $topic_id,
83
			'ORDER_BY'	=> 'score DESC, t.topic_time DESC',
84
		);
85
	}
86
87
	/**
88
	 * {@inheritdoc}
89
	 */
90
	public function is_supported()
91
	{
92
		return ($this->db->get_sql_layer() === 'postgres');
93
	}
94
95
	/**
96
	 * {@inheritdoc}
97
	 */
98
	public function is_fulltext($column = 'topic_title', $table = TOPICS_TABLE)
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
99
	{
100
		return in_array($table . '_' . $this->ts_name . '_' . $column, $this->get_fulltext_indexes($column, $table), true);
101
	}
102
103
	/**
104
	 * {@inheritdoc}
105
	 */
106
	public function get_fulltext_indexes($column = 'topic_title', $table = TOPICS_TABLE)
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
107
	{
108
		$indexes = array();
109
110
		if (!$this->is_supported())
111
		{
112
			return $indexes;
113
		}
114
115
		$sql = "SELECT c2.relname
116
			FROM pg_catalog.pg_class c1, pg_catalog.pg_index i, pg_catalog.pg_class c2
117
			WHERE c1.relname = '" . $this->db->sql_escape($table) . "'
118
				AND position('to_tsvector' in pg_catalog.pg_get_indexdef(i.indexrelid, 0, true)) > 0
119
				AND pg_catalog.pg_table_is_visible(c1.oid)
120
				AND c1.oid = i.indrelid
121
				AND i.indexrelid = c2.oid";
122
		$result = $this->db->sql_query($sql);
123
		while ($row = $this->db->sql_fetchrow($result))
124
		{
125
			if (strpos($row['relname'], $column) !== false)
126
			{
127
				$indexes[] = $row['relname'];
128
			}
129
		}
130
		$this->db->sql_freeresult($result);
131
132
		return $indexes;
133
	}
134
135
	/**
136
	 * {@inheritdoc}
137
	 */
138
	public function create_fulltext_index($column = 'topic_title', $table = TOPICS_TABLE)
0 ignored issues
show
The constant vse\similartopics\driver\TOPICS_TABLE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
139
	{
140
		// Make sure ts_name is current
141
		$this->set_ts_name($this->config['pst_postgres_ts_name']);
142
143
		$new_index = $table . '_' . $this->ts_name . '_' . $column;
144
145
		$indexed = false;
146
147
		foreach ($this->get_fulltext_indexes($column, $table) as $index)
148
		{
149
			if ($index === $new_index)
150
			{
151
				$indexed = true;
152
			}
153
			else
154
			{
155
				$sql = 'DROP INDEX ' . $index;
156
				$this->db->sql_query($sql);
157
			}
158
		}
159
160
		if (!$indexed)
161
		{
162
			$sql = 'CREATE INDEX ' . $this->db->sql_escape($new_index) . '
163
				ON '  . $this->db->sql_escape($table) . "
164
				USING gin (to_tsvector ('" . $this->db->sql_escape($this->ts_name) . "', " . $this->db->sql_escape($column) . '))';
165
			$this->db->sql_query($sql);
166
		}
167
	}
168
169
	/**
170
	 * {@inheritdoc}
171
	 */
172
	public function get_engine()
173
	{
174
		return '';
175
	}
176
177
	/**
178
	 * Set the PostgreSQL Text Search name (dictionary)
179
	 *
180
	 * @param string $ts_name Dictionary name
181
	 */
182
	protected function set_ts_name($ts_name)
183
	{
184
		$this->ts_name = $ts_name ?: 'simple';
185
	}
186
}
187