Skip to content

Initial support for SQLite database backend, fixes #56 #57

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

AnnoyingTechnology
Copy link

Draft

@AnnoyingTechnology AnnoyingTechnology marked this pull request as draft March 21, 2023 14:44
@AnnoyingTechnology
Copy link
Author

This seems to be working pretty well now.

@liuch
Copy link
Owner

liuch commented Mar 23, 2023

Hello @AnnoyingTechnology, Sorry for the delay in reply. I'm a bit busy right now, but I promise, I'll take a look at your PR soon.

@AnnoyingTechnology AnnoyingTechnology changed the title Initial support for SQLite database backend Initial support for SQLite database backend, fixes #56 Mar 23, 2023
@AnnoyingTechnology
Copy link
Author

Hello @AnnoyingTechnology, Sorry for the delay in reply. I'm a bit busy right now, but I promise, I'll take a look at your PR soon.

no worries

@liuch liuch marked this pull request as ready for review March 27, 2023 16:35
@liuch
Copy link
Owner

liuch commented Mar 27, 2023

I don't think you've tested your code with the table prefix option. I'm right?

@AnnoyingTechnology
Copy link
Author

AnnoyingTechnology commented Mar 27, 2023

I don't think you've tested your code with the table prefix option. I'm right?

Correct. As SQLite isn't a DBMS the file is the database and the need for prefix to avoid collisions when sharing a single database for multiple uses doesn't exist.

There is still a real issue though, I removed an order by somewhere that should have been kept. But at the time I couldn't make it work properly.

Copy link
Owner

@liuch liuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've done a great job. Thank you for the PR. I have a few comments besides ones I left in your code:

  • Your code needs to be tested with the table prefix option enabled with one or more other tables without the prefix.
  • You have used spaces and tabs for indentation in your php code. Could you use spaces instead of tabs, please? I am sticking to PSR-2 in the php code of this project.
  • In all the new files that I saw, you have not been mentioned as the author of the code. Maybe you forgot to change it?

I haven't tested your code on a server with reports yet. Perhaps after these tests I will have some questions and comments.

Comment on lines +174 to +176
break;
case 'sqlite':
$type = 'sqlite';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
break;
case 'sqlite':
$type = 'sqlite';
break;
case 'sqlite':
$type = 'sqlite';

],
'additional' => '',
'table_options' => '',
'sub_queries' => []
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may have forgotten to create an unique index on the fqdn field.

);
while ($row = $st->fetch(\PDO::FETCH_ASSOC)) {
$tname = $row['name'];
$rcnt = $this->dbh->query('SELECT COUNT(*) FROM ' . $tname . '')->fetch(\PDO::FETCH_NUM)[0];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$rcnt = $this->dbh->query('SELECT COUNT(*) FROM ' . $tname . '')->fetch(\PDO::FETCH_NUM)[0];
$rcnt = $this->dbh->query('SELECT COUNT(*) FROM ' . $tname)->fetch(\PDO::FETCH_NUM)[0];

$db->query('PRAGMA FOREIGN_KEYS = OFF');
$st = $db->query($this->sqlShowTablesQuery());
while ($table = $st->fetchColumn(0)) {
$db->query('DROP TABLE ' . $table . '');
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$db->query('DROP TABLE ' . $table . '');
$db->query('DROP TABLE ' . $table);

if ($col_num > 0) {
$query .= ', ';
}
$query .= '' . $column['name'] . ' ' . $column['definition'];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$query .= '' . $column['name'] . ' ' . $column['definition'];
$query .= $column['name'] . ' ' . $column['definition'];

Comment on lines +282 to +294
try {

$st = $db->prepare(
'SELECT org, begin_time, end_time, fqdn, external_id, seen, SUM(rcount) AS rcount,'
. ' MIN(dkim_align) AS dkim_align, MIN(spf_align) AS spf_align,'
. ' MIN(disposition) AS disposition FROM ' . $this->connector->tablePrefix('reports')
. ' AS rp LEFT JOIN ' . $this->connector->tablePrefix('rptrecords')
. ' AS rr ON rp.id = rr.report_id'
. ' INNER JOIN ' . $this->connector->tablePrefix('domains')
. ' AS d ON d.id = rp.domain_id'
. ' GROUP BY rp.id'
. $cond_str1 . $order_str . $limit_str
);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
try {
$st = $db->prepare(
'SELECT org, begin_time, end_time, fqdn, external_id, seen, SUM(rcount) AS rcount,'
. ' MIN(dkim_align) AS dkim_align, MIN(spf_align) AS spf_align,'
. ' MIN(disposition) AS disposition FROM ' . $this->connector->tablePrefix('reports')
. ' AS rp LEFT JOIN ' . $this->connector->tablePrefix('rptrecords')
. ' AS rr ON rp.id = rr.report_id'
. ' INNER JOIN ' . $this->connector->tablePrefix('domains')
. ' AS d ON d.id = rp.domain_id'
. ' GROUP BY rp.id'
. $cond_str1 . $order_str . $limit_str
);
try {
$st = $db->prepare(
'SELECT org, begin_time, end_time, fqdn, external_id, seen, SUM(rcount) AS rcount,'
. ' MIN(dkim_align) AS dkim_align, MIN(spf_align) AS spf_align,'
. ' MIN(disposition) AS disposition FROM ' . $this->connector->tablePrefix('reports')
. ' AS rp LEFT JOIN ' . $this->connector->tablePrefix('rptrecords')
. ' AS rr ON rp.id = rr.report_id'
. ' INNER JOIN ' . $this->connector->tablePrefix('domains')
. ' AS d ON d.id = rp.domain_id'
. ' GROUP BY rp.id'
. $cond_str1 . $order_str . $limit_str
);

Comment on lines +419 to +424
$st = $this->connector->dbh()->query(
'SELECT DISTINCT strftime("%Y-%m", date) AS month FROM'
. ' (SELECT DISTINCT begin_time AS date FROM ' . $rep_tn
. ' UNION SELECT DISTINCT end_time AS date FROM ' . $rep_tn
. ') AS r ORDER BY month DESC'
);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$st = $this->connector->dbh()->query(
'SELECT DISTINCT strftime("%Y-%m", date) AS month FROM'
. ' (SELECT DISTINCT begin_time AS date FROM ' . $rep_tn
. ' UNION SELECT DISTINCT end_time AS date FROM ' . $rep_tn
. ') AS r ORDER BY month DESC'
);
$st = $this->connector->dbh()->query(
'SELECT DISTINCT strftime("%Y-%m", date) AS month FROM'
. ' (SELECT DISTINCT begin_time AS date FROM ' . $rep_tn
. ' UNION SELECT DISTINCT end_time AS date FROM ' . $rep_tn
. ') AS r ORDER BY month DESC'
);

$st->closeCursor();

$st = $db->prepare(
'SELECT COUNT(*) FROM (SELECT org FROM ' . $this->connector->tablePrefix('reports') . ''
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'SELECT COUNT(*) FROM (SELECT org FROM ' . $this->connector->tablePrefix('reports') . ''
'SELECT COUNT(*) FROM (SELECT org FROM ' . $this->connector->tablePrefix('reports')

Comment on lines +123 to +129
'SELECT ip, SUM(rcount) AS rcount, SUM(CASE WHEN dkim_align = 2 THEN rcount ELSE 0 END) AS dkim_aligned,'
. ' SUM(CASE WHEN spf_align = 2 THEN rcount ELSE 0 END) AS spf_aligned'
. ' FROM ' . $this->connector->tablePrefix('rptrecords') . ' AS rr'
. ' INNER JOIN ' . $this->connector->tablePrefix('reports')
. ' AS rp ON rr.report_id = rp.id'
. $this->sqlCondition($domain ? true : false) . ' GROUP BY ip ORDER BY rcount DESC'
);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'SELECT ip, SUM(rcount) AS rcount, SUM(CASE WHEN dkim_align = 2 THEN rcount ELSE 0 END) AS dkim_aligned,'
. ' SUM(CASE WHEN spf_align = 2 THEN rcount ELSE 0 END) AS spf_aligned'
. ' FROM ' . $this->connector->tablePrefix('rptrecords') . ' AS rr'
. ' INNER JOIN ' . $this->connector->tablePrefix('reports')
. ' AS rp ON rr.report_id = rp.id'
. $this->sqlCondition($domain ? true : false) . ' GROUP BY ip ORDER BY rcount DESC'
);
'SELECT ip, SUM(rcount) AS rcount, SUM(CASE WHEN dkim_align = 2 THEN rcount ELSE 0 END) AS dkim_aligned,'
. ' SUM(CASE WHEN spf_align = 2 THEN rcount ELSE 0 END) AS spf_aligned'
. ' FROM ' . $this->connector->tablePrefix('rptrecords') . ' AS rr'
. ' INNER JOIN ' . $this->connector->tablePrefix('reports')
. ' AS rp ON rr.report_id = rp.id'
. $this->sqlCondition($domain ? true : false) . ' GROUP BY ip ORDER BY rcount DESC'
);

Comment on lines +177 to +187
private function columnExists($db, string $table, string $column): bool
{
$st = $db->prepare(
'PRAGMA table_info(?)'
);
$st->bindValue(2, $table, \PDO::PARAM_STR);
$st->execute();
$res = $st->fetch(\PDO::FETCH_ASSOC);
$st->closeCursor();
return $res ? true : false;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is the column existence tested here?

@liuch
Copy link
Owner

liuch commented Mar 27, 2023

Correct. As SQLite isn't a DBMS the file is the database and the need for prefix to avoid collisions when sharing a single database for multiple uses doesn't exist.

Yes, I understand you. But different prefixes can be used within the same project. For example, for tests or quick reports. The current code may delete tables beyond the prefix.

Added: What about Write-Ahead Logging: https://www.sqlite.org/wal.html ?

@AnnoyingTechnology
Copy link
Author

AnnoyingTechnology commented Mar 31, 2023

Thanks for the feedback, I'll fix all of this.

Added: What about Write-Ahead Logging: https://www.sqlite.org/wal.html ?

What about it ? This is a performance/concurrency per-database setting.
You you're concerned about what/where it is stored, it is comprised of the database name, with -wal suffix and (if enabled) lives in the same folder as the database.

But different prefixes can be used within the same project. For example, for tests or quick reports

The simplicity of changing the database file path, or copying a database file generally renders this moot. But I'll bring prefixes back.

@liuch
Copy link
Owner

liuch commented Apr 4, 2023

At least there is support for prefixes, there is support for sqlite, but nowhere is it stated that the prefixes will not work with sqlite. Your code only creates the appearance of working with prefixes. That's the main problem. If you don't want prefixes to be used with sqlite, it makes sense to EXPLICITLY disable running this configuration.

@AnnoyingTechnology
Copy link
Author

If you don't want prefixes to be used with sqlite, it makes sense to EXPLICITLY disable running this configuration.

If you're OK with that, I'm fine with the application dying with Prefixes aren't supported with SQLite if the parameter isn't left empty.

@liuch
Copy link
Owner

liuch commented Apr 6, 2023

Okay. So be it.

@williamdes
Copy link
Contributor

bump rebase merge ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants