mirror of
https://github.com/owntone/owntone-server.git
synced 2024-12-27 15:45:56 -05:00
06aaacbe8f
keyword
466 lines
12 KiB
Plaintext
466 lines
12 KiB
Plaintext
/*
|
|
* Copyright (C) 2015 Christian Meffert <christian.meffert@googlemail.com>
|
|
*
|
|
* This program 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 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
tree grammar SMARTPL2SQL;
|
|
|
|
options {
|
|
tokenVocab = SMARTPL;
|
|
ASTLabelType = pANTLR3_BASE_TREE;
|
|
language = C;
|
|
}
|
|
|
|
@header {
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <limits.h>
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#include <sqlite3.h>
|
|
|
|
#include "logger.h"
|
|
#include "db.h"
|
|
}
|
|
|
|
@members {
|
|
}
|
|
|
|
playlist returns [ pANTLR3_STRING title, pANTLR3_STRING query, pANTLR3_STRING orderby, pANTLR3_STRING having, int limit ]
|
|
@init { $title = NULL; $query = NULL; $orderby = NULL; $having = NULL; $limit = -1; }
|
|
: STR '{' e = expression '}'
|
|
{
|
|
pANTLR3_UINT8 val;
|
|
val = $STR.text->toUTF8($STR.text)->chars;
|
|
val++;
|
|
val[strlen((const char *)val) - 1] = '\0';
|
|
|
|
$title = $STR.text->factory->newRaw($STR.text->factory);
|
|
$title->append8($title, (const char *)val);
|
|
|
|
$query = $e.result->factory->newRaw($e.result->factory);
|
|
$query->append8($query, "(");
|
|
$query->appendS($query, $e.result);
|
|
$query->append8($query, ")");
|
|
|
|
$limit = $e.limit;
|
|
|
|
$orderby = $e.result->factory->newRaw($e.result->factory);
|
|
$orderby->appendS($orderby, $e.orderby);
|
|
|
|
$having = $e.result->factory->newRaw($e.result->factory);
|
|
$having->appendS($having, $e.having);
|
|
}
|
|
;
|
|
|
|
expression returns [ pANTLR3_STRING result, pANTLR3_STRING orderby, pANTLR3_STRING having, int limit ]
|
|
@init { $result = NULL; $orderby = NULL; $having = NULL; $limit = -1; }
|
|
: ^(LIMIT a = expression INT)
|
|
{
|
|
$result = $a.result->factory->newRaw($a.result->factory);
|
|
$result->appendS($result, $a.result);
|
|
|
|
$having = $a.result->factory->newRaw($a.result->factory);
|
|
$having->appendS($having, $a.having);
|
|
|
|
$orderby = $a.result->factory->newRaw($a.result->factory);
|
|
$orderby->appendS($orderby, $a.orderby);
|
|
|
|
$limit = atoi((const char *)$INT.text->chars);
|
|
}
|
|
| ^(ORDERBY a = expression o = ordertag SORTDIR)
|
|
{
|
|
$result = $a.result->factory->newRaw($a.result->factory);
|
|
$result->appendS($result, $a.result);
|
|
|
|
$having = $a.result->factory->newRaw($a.result->factory);
|
|
$having->appendS($having, $a.having);
|
|
|
|
$orderby = $o.result->factory->newRaw($o.result->factory);
|
|
$orderby->appendS($orderby, $o.result);
|
|
$orderby->append8($orderby, " ");
|
|
$orderby->appendS($orderby, $SORTDIR.text->toUTF8($SORTDIR.text));
|
|
}
|
|
| ^(HAVING a = expression b = expression)
|
|
{
|
|
$result = $a.result->factory->newRaw($a.result->factory);
|
|
$result->appendS($result, $a.result);
|
|
|
|
$having = $b.result->factory->newRaw($b.result->factory);
|
|
$having->appendS($having, $b.result);
|
|
}
|
|
| ^(NOT a = expression)
|
|
{
|
|
$result = $a.result->factory->newRaw($a.result->factory);
|
|
$result->append8($result, "NOT(");
|
|
$result->appendS($result, $a.result);
|
|
$result->append8($result, ")");
|
|
}
|
|
| ^(AND a = expression b = expression)
|
|
{
|
|
$result = $a.result->factory->newRaw($a.result->factory);
|
|
$result->append8($result, "(");
|
|
$result->appendS($result, $a.result);
|
|
$result->append8($result, " AND ");
|
|
$result->appendS($result, $b.result);
|
|
$result->append8($result, ")");
|
|
}
|
|
| ^(OR a = expression b = expression)
|
|
{
|
|
$result = $a.result->factory->newRaw($a.result->factory);
|
|
$result->append8($result, "(");
|
|
$result->appendS($result, $a.result);
|
|
$result->append8($result, " OR ");
|
|
$result->appendS($result, $b.result);
|
|
$result->append8($result, ")");
|
|
}
|
|
| STRTAG INCLUDES STR
|
|
{
|
|
pANTLR3_UINT8 val;
|
|
char *tmp;
|
|
|
|
val = $STR.text->toUTF8($STR.text)->chars;
|
|
val++;
|
|
val[strlen((const char *)val) - 1] = '\0';
|
|
|
|
tmp = sqlite3_mprintf("\%q", (const char *)val);
|
|
|
|
$result = $STR.text->factory->newRaw($STR.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $STRTAG.text->toUTF8($STRTAG.text));
|
|
$result->append8($result, " LIKE '\%");
|
|
$result->append8($result, tmp);
|
|
$result->append8($result, "\%'");
|
|
|
|
sqlite3_free(tmp);
|
|
}
|
|
| STRTAG IS STR
|
|
{
|
|
pANTLR3_UINT8 val;
|
|
char *tmp;
|
|
|
|
val = $STR.text->toUTF8($STR.text)->chars;
|
|
val++;
|
|
val[strlen((const char *)val) - 1] = '\0';
|
|
|
|
tmp = sqlite3_mprintf("\%q", (const char *)val);
|
|
|
|
$result = $STR.text->factory->newRaw($STR.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $STRTAG.text->toUTF8($STRTAG.text));
|
|
$result->append8($result, " LIKE '");
|
|
$result->append8($result, tmp);
|
|
$result->append8($result, "'");
|
|
|
|
sqlite3_free(tmp);
|
|
}
|
|
| STRTAG STARTSWITH STR
|
|
{
|
|
pANTLR3_UINT8 val;
|
|
char *tmp;
|
|
|
|
val = $STR.text->toUTF8($STR.text)->chars;
|
|
val++;
|
|
val[strlen((const char *)val) - 1] = '\0';
|
|
|
|
tmp = sqlite3_mprintf("\%q", (const char *)val);
|
|
|
|
$result = $STR.text->factory->newRaw($STR.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $STRTAG.text->toUTF8($STRTAG.text));
|
|
$result->append8($result, " LIKE '");
|
|
$result->append8($result, tmp);
|
|
$result->append8($result, "\%'");
|
|
|
|
sqlite3_free(tmp);
|
|
}
|
|
| INTTAG INTBOOL INT
|
|
{
|
|
$result = $INTTAG.text->factory->newRaw($INTTAG.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $INTTAG.text->toUTF8($INTTAG.text));
|
|
$result->append8($result, " ");
|
|
$result->appendS($result, $INTBOOL.text->toUTF8($INTBOOL.text));
|
|
$result->append8($result, " ");
|
|
$result->appendS($result, $INT.text->toUTF8($INT.text));
|
|
}
|
|
| DATETAG AFTER dateval
|
|
{
|
|
char str[15];
|
|
sprintf(str, "\%d", $dateval.result);
|
|
|
|
$result = $DATETAG.text->factory->newRaw($DATETAG.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $DATETAG.text->toUTF8($DATETAG.text));
|
|
$result->append8($result, " > ");
|
|
$result->append8($result, str);
|
|
}
|
|
| DATETAG BEFORE dateval
|
|
{
|
|
char str[15];
|
|
sprintf(str, "\%d", $dateval.result);
|
|
|
|
$result = $DATETAG.text->factory->newRaw($DATETAG.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $DATETAG.text->toUTF8($DATETAG.text));
|
|
$result->append8($result, " < ");
|
|
$result->append8($result, str);
|
|
}
|
|
| ENUMTAG IS ENUMVAL
|
|
{
|
|
pANTLR3_UINT8 tag;
|
|
pANTLR3_UINT8 val;
|
|
char str[20];
|
|
|
|
sprintf(str, "1=1");
|
|
|
|
tag = $ENUMTAG.text->chars;
|
|
val = $ENUMVAL.text->chars;
|
|
if (strcmp((char *)tag, "media_kind") == 0)
|
|
{
|
|
if (strcmp((char *)val, "music") == 0)
|
|
{
|
|
sprintf(str, "f.media_kind = \%d", MEDIA_KIND_MUSIC);
|
|
}
|
|
else if (strcmp((char *)val, "movie") == 0)
|
|
{
|
|
sprintf(str, "f.media_kind = \%d", MEDIA_KIND_MOVIE);
|
|
}
|
|
else if (strcmp((char *)val, "podcast") == 0)
|
|
{
|
|
sprintf(str, "f.media_kind = \%d", MEDIA_KIND_PODCAST);
|
|
}
|
|
else if (strcmp((char *)val, "audiobook") == 0)
|
|
{
|
|
sprintf(str, "f.media_kind = \%d", MEDIA_KIND_AUDIOBOOK);
|
|
}
|
|
else if (strcmp((char *)val, "tvshow") == 0)
|
|
{
|
|
sprintf(str, "f.media_kind = \%d", MEDIA_KIND_TVSHOW);
|
|
}
|
|
}
|
|
else if (strcmp((char *)tag, "data_kind") == 0)
|
|
{
|
|
if (strcmp((char *)val, "file") == 0)
|
|
{
|
|
sprintf(str, "f.data_kind = \%d", DATA_KIND_FILE);
|
|
}
|
|
else if (strcmp((char *)val, "url") == 0)
|
|
{
|
|
sprintf(str, "f.data_kind = \%d", DATA_KIND_HTTP);
|
|
}
|
|
else if (strcmp((char *)val, "spotify") == 0)
|
|
{
|
|
sprintf(str, "f.data_kind = \%d", DATA_KIND_SPOTIFY);
|
|
}
|
|
else if (strcmp((char *)val, "pipe") == 0)
|
|
{
|
|
sprintf(str, "f.data_kind = \%d", DATA_KIND_PIPE);
|
|
}
|
|
}
|
|
|
|
$result = $ENUMTAG.text->factory->newRaw($ENUMTAG.text->factory);
|
|
$result->append8($result, str);
|
|
}
|
|
| GROUPTAG INTBOOL INT
|
|
{
|
|
$result = $GROUPTAG.text->factory->newRaw($GROUPTAG.text->factory);
|
|
$result->appendS($result, $GROUPTAG.text->toUTF8($GROUPTAG.text));
|
|
$result->append8($result, " ");
|
|
$result->appendS($result, $INTBOOL.text->toUTF8($INTBOOL.text));
|
|
$result->append8($result, " ");
|
|
$result->appendS($result, $INT.text->toUTF8($INT.text));
|
|
}
|
|
;
|
|
|
|
ordertag returns [ pANTLR3_STRING result ]
|
|
@init { $result = NULL; }
|
|
: STRTAG
|
|
{
|
|
$result = $STRTAG.text->factory->newRaw($STRTAG.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $STRTAG.text->toUTF8($STRTAG.text));
|
|
}
|
|
| INTTAG
|
|
{
|
|
$result = $INTTAG.text->factory->newRaw($INTTAG.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $INTTAG.text->toUTF8($INTTAG.text));
|
|
}
|
|
| DATETAG
|
|
{
|
|
$result = $DATETAG.text->factory->newRaw($DATETAG.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $DATETAG.text->toUTF8($DATETAG.text));
|
|
}
|
|
| ENUMTAG
|
|
{
|
|
$result = $ENUMTAG.text->factory->newRaw($ENUMTAG.text->factory);
|
|
$result->append8($result, "f.");
|
|
$result->appendS($result, $ENUMTAG.text->toUTF8($ENUMTAG.text));
|
|
}
|
|
;
|
|
|
|
dateval returns [ int result ]
|
|
@init { $result = 0; }
|
|
: DATE
|
|
{
|
|
pANTLR3_UINT8 datval;
|
|
|
|
datval = $DATE.text->chars;
|
|
|
|
if (strcmp((char *)datval, "today") == 0)
|
|
{
|
|
$result = time(NULL);
|
|
}
|
|
else if (strcmp((char *)datval, "yesterday") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600;
|
|
}
|
|
else if (strcmp((char *)datval, "last week") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 7;
|
|
}
|
|
else if (strcmp((char *)datval, "last month") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 30;
|
|
}
|
|
else if (strcmp((char *)datval, "last year") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 365;
|
|
}
|
|
else
|
|
{
|
|
struct tm tm;
|
|
char year[5];
|
|
char month[3];
|
|
char day[3];
|
|
|
|
memset((void*)&tm,0,sizeof(tm));
|
|
memset(year, 0, sizeof(year));
|
|
memset(month, 0, sizeof(month));
|
|
memset(day, 0, sizeof(day));
|
|
|
|
strncpy(year, (const char *)datval, 4);
|
|
strncpy(month, (const char *)datval + 5, 2);
|
|
strncpy(day, (const char *)datval + 8, 2);
|
|
|
|
tm.tm_year = atoi(year) - 1900;
|
|
tm.tm_mon = atoi(month) - 1;
|
|
tm.tm_mday = atoi(day);
|
|
|
|
$result = mktime(&tm);
|
|
}
|
|
}
|
|
| interval BEFORE DATE
|
|
{
|
|
pANTLR3_UINT8 datval;
|
|
|
|
datval = $DATE.text->chars;
|
|
|
|
if (strcmp((char *)datval, "yesterday") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600;
|
|
}
|
|
else if (strcmp((char *)datval, "last week") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 7;
|
|
}
|
|
else if (strcmp((char *)datval, "last month") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 30;
|
|
}
|
|
else if (strcmp((char *)datval, "last year") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 365;
|
|
}
|
|
else
|
|
{
|
|
$result = time(NULL);
|
|
}
|
|
|
|
$result = $result - $interval.result;
|
|
}
|
|
| interval AFTER DATE
|
|
{
|
|
pANTLR3_UINT8 datval;
|
|
|
|
datval = $DATE.text->chars;
|
|
|
|
if (strcmp((char *)datval, "yesterday") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600;
|
|
}
|
|
else if (strcmp((char *)datval, "last week") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 7;
|
|
}
|
|
else if (strcmp((char *)datval, "last month") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 30;
|
|
}
|
|
else if (strcmp((char *)datval, "last year") == 0)
|
|
{
|
|
$result = time(NULL) - 24 * 3600 * 365;
|
|
}
|
|
else
|
|
{
|
|
$result = time(NULL);
|
|
}
|
|
|
|
$result = $result + $interval.result;
|
|
}
|
|
| interval AGO
|
|
{
|
|
$result = time(NULL) - $interval.result;
|
|
}
|
|
;
|
|
|
|
interval returns [ int result ]
|
|
@init { $result = 0; }
|
|
: INT DATINTERVAL
|
|
{
|
|
pANTLR3_UINT8 interval;
|
|
|
|
$result = atoi((const char *)$INT.text->chars);
|
|
interval = $DATINTERVAL.text->chars;
|
|
|
|
if (strcmp((char *)interval, "days") == 0)
|
|
{
|
|
$result = $result * 24 * 3600;
|
|
}
|
|
else if (strcmp((char *)interval, "weeks") == 0)
|
|
{
|
|
$result = $result * 24 * 3600 * 7;
|
|
}
|
|
else if (strcmp((char *)interval, "months") == 0)
|
|
{
|
|
$result = $result * 24 * 3600 * 30;
|
|
}
|
|
else if (strcmp((char *)interval, "weeks") == 0)
|
|
{
|
|
$result = $result * 24 * 3600 * 365;
|
|
}
|
|
else
|
|
{
|
|
$result = 0;
|
|
}
|
|
}
|
|
;
|
|
|
|
|