diff --git a/data/data.sqlite.example b/data/data.sqlite.example

index 5f2a56d6a519463f35094e6313da5f70419d41f2..924a85fd9649d51a764099c4b68e05731365d751 100644

Binary files a/data/data.sqlite.example and b/data/data.sqlite.example differ

diff --git a/faqs.pl b/faqs.pl

index f3ffefbd6308c67f27f7c9adf2b58eaef854d60f..cfccd2a99fabfe126c0702ed7564c5176d09aab6 100755

--- a/faqs.pl

+++ b/faqs.pl

@@ -38,11 +38,11 @@ return "SELECT * FROM questions q ORDER BY question;";

}

if ( $query =~ /tag=([0-9]+)/i ) {

- return "SELECT q.* FROM questions q JOIN tags_questions tq ON q.id = tq.q_id WHERE tq.t_id = $1";

+ return "SELECT q.* FROM questions q LEFT JOIN tags_questions tq ON q.id = tq.q_id WHERE tq.t_id = $1";

}

if ( $query =~ /faq=([0-9]+)/i ) {

- return "SELECT q.* FROM questions q JOIN tags_questions tq ON q.id = tq.q_id WHERE q.id = $1";

+ return "SELECT q.* FROM questions q LEFT JOIN tags_questions tq ON q.id = tq.q_id WHERE q.id = $1";

}

write_response('INTERNAL_SERVER_ERROR', 'CGI execution error', undef);

}

@@ -53,17 +53,25 @@ my @return;

my $dbh = DBI->connect($CONF{'dsn'}, '', '', { RaiseError => 1 }) or die $DBI::errstr;

my @rows = $dbh->selectall_array(sql());

- $dbh->disconnect();

if ( !scalar @rows ) {

push @return, 'No faqs found!';

}

else {

foreach (@rows) {

- push @return, sprintf("### %s", @$_[1]);

+ push @return, sprintf("## %s", @$_[1]);

+ my @tags = $dbh->selectall_array("SELECT id, name FROM tags t LEFT JOIN tags_questions tq ON tq.t_id = t.id WHERE tq.q_id = @$_[0];");

+

+ if ( scalar @tags ) {

+ push @return, ('', 'Tags:');

+ foreach (@tags) {

+ push @return, sprintf("=> ./faqs.pl?tag=%d %s", @$_[0], @$_[1]);

+ }

+ }

push @return, ('', @$_[2], '');

}

}

+ $dbh->disconnect();

push @return, '';

return @return;

}

diff --git a/scripts.sql b/scripts.sql

new file mode 100644

index 0000000000000000000000000000000000000000..6adfe8dfa40bcd67acda96cbb409a12c368ee33d

--- /dev/null

+++ b/scripts.sql

@@ -0,0 +1,17 @@

+select DISTINCT tags.*, count(tags_questions.q_id) as count from fts_data inner join tags on tags.id = fts_data.t_id

+left join tags_questions on tags_questions.t_id = tags.id

+where fts_data match '"text": "gemin"'

+ORDER BY rank

+

+select DISTINCT q_id, questions.question from fts_data inner join questions on questions.id = q_id

+where fts_data match '"text": "linux"'

+ORDER BY rank;

+

+-- fill fts_data

+INSERT INTO fts_data (q_id, text) SELECT id, question FROM questions;

+INSERT INTO fts_data (q_id, text) SELECT id, answer FROM questions;

+INSERT INTO fts_data (t_id, text) SELECT id, name FROM tags;

+

+-- create fts_data table

+CREATE VIRTUAL TABLE fts_data

+USING FTS5(t_id, q_id, text, tokenize = "porter unicode61")

diff --git a/search.pl b/search.pl

index b506809600c3d4ef36c6c82d8afd4f078abb3a3a..2428f41ab3d990e60c136db035ba4ecf76a19847 100755

--- a/search.pl

+++ b/search.pl

@@ -22,7 +22,7 @@ write_response('CGI_ERROR', 'CGI execution error', undef);

}

my $query = lc(uri_unescape($ENV{'QUERY_STRING'}));

-if ($query eq '' || $query !~ /^[0-9a-z]*$/i)

+if ($query eq '' || $query !~ /^[0-9a-z\s]*$/i)

{

write_response('INPUT', 'Search faqs for the following terms (separate by blank)', undef);

}

@@ -42,15 +42,15 @@ my ($term) = @_;

my @result = ();

my $dbh = DBI->connect($CONF{'dsn'}, '', '', { RaiseError => 1 }) or die $DBI::errstr;

- my @matchingtags = $dbh->selectall_array("SELECT id, name, count(t_id) FROM tags LEFT JOIN tags_questions ON tags_questions.t_id = tags.id WHERE name LIKE '%$term%' GROUP BY t_id");

- my @matchingfaqs = $dbh->selectall_array("SELECT * FROM questions WHERE question LIKE '%$term%' OR answer LIKE '%$term%'");

+ my @matchingtags = $dbh->selectall_array("SELECT DISTINCT t.*, count(tq.q_id) AS count FROM fts_data INNER JOIN tags t ON t.id = fts_data.t_id LEFT JOIN tags_questions tq ON tq.t_id = t.id WHERE fts_data MATCH '\"text\": \"$term\"' GROUP BY t.id ORDER BY rank");

+ my @matchingfaqs = $dbh->selectall_array("SELECT DISTINCT q_id, q.question FROM fts_data INNER JOIN questions q ON q.id = q_id WHERE fts_data MATCH '\"text\": \"$term\"' ORDER BY rank;");

$dbh->disconnect();

- if ( !scalar(@matchingtags) && !scalar(@matchingfaqs)) {

+ if ( !scalar @matchingtags && !scalar @matchingfaqs) {

push @result, ('Sorry, we can\'t find an entry that matches your search data.', '');

}

- if ( scalar(@matchingtags)) {

+ if ( scalar @matchingtags) {

push @result, ('## matching tags', '');

foreach (@matchingtags) {

push @result, sprintf("=> ./faqs.pl?tag=%d %s (%d entrys)", @$_[0], @$_[1], @$_[2]);

@@ -58,7 +58,7 @@ }

push @result, '';

}

- if ( scalar(@matchingfaqs)) {

+ if ( scalar @matchingfaqs) {

push @result, ('## matching FAQs', '');

foreach (@matchingfaqs) {

push @result, sprintf("=> ./faqs.pl?faq=%d %s", @$_[0], @$_[1]);

diff --git a/tags.pl b/tags.pl

index 5b1ddc47f2313f053b1a7e2e3a6541629f3196aa..81996bdf9c9adfd898f6308c91bc65e2239243db 100755

--- a/tags.pl

+++ b/tags.pl

@@ -34,7 +34,7 @@ {

my $dbh = DBI->connect($CONF{'dsn'}, '', '', { RaiseError => 1 }) or die $DBI::errstr;

my @result;

- my @rows = $dbh->selectall_array('SELECT id, name, count(t_id) FROM tags LEFT JOIN tags_questions ON tags_questions.t_id = tags.id GROUP BY t_id');

+ my @rows = $dbh->selectall_array('SELECT id, name, count(t_id) FROM tags t LEFT JOIN tags_questions tq ON tq.t_id = t.id GROUP BY t_id');

$dbh->disconnect();

if ( !scalar @rows ) {