#!/bin/sh -e
#
# # DASHT-QUERY-EXEC 1            2020-05-16                            2.4.0
#
# ## NAME
#
# dasht-query-exec - searches a [Dash] docset's SQLite3 database file
#
# ## SYNOPSIS
#
# `dasht-query-exec` *PATTERN* *DATABASE* [*OPTIONS\_FOR\_SQLITE3*...]
#
# ## DESCRIPTION
#
# Searches for *PATTERN* in *DATABASE*, which is an SQLite3 database file
# located inside a [Dash] docset at `/Contents/Resources/docSet.dsidx`, while
# passing the optional *OPTIONS\_FOR\_SQLITE3* arguments down to sqlite3(1).
#
# If *PATTERN* is empty or solely consists of unescaped wildcard characters,
# topics having distinct leading characters are returned from the *DATABASE*.
#
# ### Searching
#
# SQL LIKE wildcard characters in *PATTERN* can be escaped with a backslash.
# For example, `\%` and `\_` are escaped, whereas `%` and `_` are not escaped.
#
# ## SEE ALSO
#
# sqlite3(1), dasht-query-line(1), dasht(1), [Dash]
#
# [Dash]: https://kapeli.com/dash
#
# ## AUTHOR
#
# Written in 2016 by Suraj N. Kurapati <https://github.com/sunaku/dasht>
# Distributed under the terms of the ISC license (see the LICENSE file).

test $# -ge 2
pattern=$1
database=$2
shift 2
test -f "$database"

# escape SQL single quotes by doubling them
pattern=$(echo "$pattern" | sed "s/'/&&/g")

#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
#   _                _          ____ ____  _                     _
#  | |__   ___  __ _(_)_ __    / ___|  _ \| |       ___ ___   __| | ___
#  | '_ \ / _ \/ _` | | '_ \  | |  _| |_) | |      / __/ _ \ / _` |/ _ \
#  | |_) |  __/ (_| | | | | | | |_| |  __/| |___  | (_| (_) | (_| |  __/
#  |_.__/ \___|\__, |_|_| |_|  \____|_|   |_____|  \___\___/ \__,_|\___|
#              |___/
#
# The following SQL queries were derived from snippets found at this URL:
#
#   https://github.com/zealdocs/zeal/blob/c6d4bab8bce62d39ceaec7eb853d12ca9c43a361/src/registry/docset.cpp#L268-L283
#
# The file at that URL is distributed under a different software license:
#
#   Copyright (C) 2015 Oleg Shparber
#   Copyright (C) 2013-2014 Jerzy Kozera
#   Contact: http://zealdocs.org/contact.html
#
#   This file is part of Zeal.
#
#   Zeal is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   Zeal is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with Zeal. If not, see <http://www.gnu.org/licenses/>.
#
searchIndex_topic=name
searchIndex_query="
  SELECT name AS name,
         type AS type,
         path AS url
  FROM searchIndex
"
ztoken_topic=ztokenname
ztoken_query="
  SELECT ztokenname                                      AS name,
         ztypename                                       AS type,
         zpath || ifnull('#' || nullif(zanchor, ''), '') AS url
  FROM ztoken
  JOIN ztokenmetainformation
    ON ztokenmetainformation.z_pk = ztoken.zmetainformation
  JOIN zfilepath
    ON zfilepath.z_pk = ztokenmetainformation.zfile
  JOIN ztokentype
    ON ztokentype.z_pk = ztoken.ztokentype
"
#                 _          __    ____ ____  _                     _
#   ___ _ __   __| |   ___  / _|  / ___|  _ \| |       ___ ___   __| | ___
#  / _ \ '_ \ / _` |  / _ \| |_  | |  _| |_) | |      / __/ _ \ / _` |/ _ \
# |  __/ | | | (_| | | (_) |  _| | |_| |  __/| |___  | (_| (_) | (_| |  __/
#  \___|_| |_|\__,_|  \___/|_|    \____|_|   |_____|  \___\___/ \__,_|\___|
#
#\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

if sqlite3 "$database" .tables | grep -F -q searchIndex; then
  topic=$searchIndex_topic
  query=$searchIndex_query
else
  topic=$ztoken_topic
  query=$ztoken_query
fi

if echo "$pattern" | tr -d '%_' | grep -q . ; then
  # something particular was searched; fetch first 100 matching topics
  where="WHERE $topic LIKE '$pattern' ESCAPE '\\'"
  group=
  limit='LIMIT 100'
else
  # nothing particular was searched; group topics by leading character
  query=$(echo "$query" | awk '
    # min() gets FIRST topic from each group; else we get the LAST one
    $1 == "SELECT" && $3 == "AS" { $2 = "min(" $2 " COLLATE NOCASE)" }
    { print }
  ')
  where=
  group="GROUP BY substr($topic,1,1)"
  limit=
fi
order="ORDER BY $topic COLLATE NOCASE"
query="$query $where $group $order $limit ;"

exec sqlite3 "$@" "$database" "$query"
