mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
Code review for FETCH/MOVE 0 changes. Improve documentation, do the
right thing with the destination when FETCH 0 can't return a row, don't try to stuff LONG_MAX into an int value.
This commit is contained in:
parent
1bc9e98549
commit
061168d38f
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/fetch.sgml,v 1.22 2002/12/30 15:31:47 momjian Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/fetch.sgml,v 1.23 2003/01/08 00:22:26 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ PostgreSQL documentation
|
|||||||
</refsynopsisdivinfo>
|
</refsynopsisdivinfo>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
FETCH [ <replaceable class="PARAMETER">direction</replaceable> ] [ <replaceable class="PARAMETER">count</replaceable> ] { IN | FROM } <replaceable class="PARAMETER">cursor</replaceable>
|
FETCH [ <replaceable class="PARAMETER">direction</replaceable> ] [ <replaceable class="PARAMETER">count</replaceable> ] { IN | FROM } <replaceable class="PARAMETER">cursor</replaceable>
|
||||||
FETCH [ FORWARD | BACKWARD | RELATIVE ] [ <replaceable class="PARAMETER">#</replaceable> | ALL | NEXT | PRIOR ]
|
FETCH [ FORWARD | BACKWARD | RELATIVE ] [ <replaceable class="PARAMETER">#</replaceable> | ALL | LAST | NEXT | PRIOR ]
|
||||||
{ IN | FROM } <replaceable class="PARAMETER">cursor</replaceable>
|
{ IN | FROM } <replaceable class="PARAMETER">cursor</replaceable>
|
||||||
</synopsis>
|
</synopsis>
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ <replaceable class="PARAMETER">#</repl
|
|||||||
<term><replaceable class="PARAMETER">direction</replaceable></term>
|
<term><replaceable class="PARAMETER">direction</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<replaceable class="PARAMETER">selector</replaceable>
|
<replaceable class="PARAMETER">direction</replaceable>
|
||||||
defines the fetch direction. It can be one of
|
defines the fetch direction. It can be one of
|
||||||
the following:
|
the following:
|
||||||
|
|
||||||
@ -50,7 +50,7 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ <replaceable class="PARAMETER">#</repl
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
fetch next row(s). This is the default
|
fetch next row(s). This is the default
|
||||||
if <replaceable class="PARAMETER">selector</replaceable> is omitted.
|
if <replaceable class="PARAMETER">direction</replaceable> is omitted.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -87,9 +87,9 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ <replaceable class="PARAMETER">#</repl
|
|||||||
<term><replaceable class="PARAMETER">#</replaceable></term>
|
<term><replaceable class="PARAMETER">#</replaceable></term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
A signed integer that specifies how many rows to fetch.
|
A signed integer constant that specifies how many rows to fetch.
|
||||||
Note that a negative integer is equivalent to changing the sense of
|
Note that a negative integer is equivalent to changing the sense of
|
||||||
FORWARD and BACKWARD. Zero re-fetches the current row.
|
FORWARD and BACKWARD. Zero re-fetches the current row, if any.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -105,6 +105,17 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ <replaceable class="PARAMETER">#</repl
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term>
|
||||||
|
LAST
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Same as <literal>ALL</>, but conforms to SQL92 syntax.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
NEXT
|
NEXT
|
||||||
@ -151,7 +162,8 @@ FETCH [ FORWARD | BACKWARD | RELATIVE ] [ <replaceable class="PARAMETER">#</repl
|
|||||||
Outputs
|
Outputs
|
||||||
</title>
|
</title>
|
||||||
<para>
|
<para>
|
||||||
<command>FETCH</command> returns the results of the query defined by the specified cursor.
|
<command>FETCH</command> returns rows from the result of the query defined
|
||||||
|
by the specified cursor.
|
||||||
The following messages will be returned if the query fails:
|
The following messages will be returned if the query fails:
|
||||||
|
|
||||||
<variablelist>
|
<variablelist>
|
||||||
@ -200,10 +212,33 @@ WARNING: FETCH/ABSOLUTE not supported, using RELATIVE
|
|||||||
If the number of rows remaining in the cursor is less
|
If the number of rows remaining in the cursor is less
|
||||||
than <replaceable class="PARAMETER">#</replaceable>,
|
than <replaceable class="PARAMETER">#</replaceable>,
|
||||||
then only those available are fetched.
|
then only those available are fetched.
|
||||||
Substituting the keyword ALL in place of a number will
|
Substituting the keyword ALL or LAST in place of a number will
|
||||||
cause all remaining rows in the cursor to be retrieved.
|
cause all remaining rows in the cursor to be retrieved.
|
||||||
Instances may be fetched in both FORWARD and BACKWARD
|
Rows may be fetched in both FORWARD and BACKWARD
|
||||||
directions. The default direction is FORWARD.
|
directions. The default direction is FORWARD.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The cursor position can be before the first row of the query result, or on
|
||||||
|
any particular row of the result, or after the last row of the result.
|
||||||
|
When created, a cursor is positioned before the first row. After fetching
|
||||||
|
some rows, the cursor is positioned on the last row retrieved. A new
|
||||||
|
<command>FETCH</command> always steps one row in the specified direction
|
||||||
|
(if possible) before beginning to return rows. If the
|
||||||
|
<command>FETCH</command> requests more rows than available, the cursor is
|
||||||
|
left positioned after the last row of the query result (or before the first
|
||||||
|
row, in the case of a backward fetch). This will always be the case after
|
||||||
|
<command>FETCH ALL</>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<tip>
|
||||||
|
<para>
|
||||||
|
A zero row count requests fetching the current row without moving the
|
||||||
|
cursor --- that is, re-fetching the most recently fetched row.
|
||||||
|
This will succeed unless the cursor is positioned before the
|
||||||
|
first row or after the last row; in which case, no row is returned.
|
||||||
|
</para>
|
||||||
|
</tip>
|
||||||
|
|
||||||
<tip>
|
<tip>
|
||||||
<para>
|
<para>
|
||||||
@ -213,7 +248,6 @@ WARNING: FETCH/ABSOLUTE not supported, using RELATIVE
|
|||||||
<command>FORWARD -1</command> is the same as <command>BACKWARD 1</command>.
|
<command>FORWARD -1</command> is the same as <command>BACKWARD 1</command>.
|
||||||
</para>
|
</para>
|
||||||
</tip>
|
</tip>
|
||||||
</para>
|
|
||||||
|
|
||||||
<refsect2 id="R2-SQL-FETCH-3">
|
<refsect2 id="R2-SQL-FETCH-3">
|
||||||
<refsect2info>
|
<refsect2info>
|
||||||
@ -224,11 +258,9 @@ WARNING: FETCH/ABSOLUTE not supported, using RELATIVE
|
|||||||
</title>
|
</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Note that the FORWARD and BACKWARD keywords are
|
Note that the FORWARD, BACKWARD, and ALL keywords are
|
||||||
<productname>PostgreSQL</productname> extensions.
|
<productname>PostgreSQL</productname> extensions.
|
||||||
The <acronym>SQL92</acronym> syntax is also supported, specified
|
See below for details on compatibility issues.
|
||||||
in the second form of the command. See below for details
|
|
||||||
on compatibility issues.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@ -246,11 +278,11 @@ WARNING: FETCH/ABSOLUTE not supported, using RELATIVE
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
|
<xref linkend="sql-declare" endterm="sql-declare-title">
|
||||||
|
is used to define a cursor.
|
||||||
Use
|
Use
|
||||||
<xref linkend="sql-move" endterm="sql-move-title">
|
<xref linkend="sql-move" endterm="sql-move-title">
|
||||||
to change cursor position.
|
to change cursor position without retrieving data.
|
||||||
<xref linkend="sql-declare" endterm="sql-declare-title">
|
|
||||||
will define a cursor.
|
|
||||||
Refer to
|
Refer to
|
||||||
<xref linkend="sql-begin" endterm="sql-begin-title">,
|
<xref linkend="sql-begin" endterm="sql-begin-title">,
|
||||||
<xref linkend="sql-commit" endterm="sql-commit-title">,
|
<xref linkend="sql-commit" endterm="sql-commit-title">,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/ref/move.sgml,v 1.15 2002/12/30 15:31:47 momjian Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/ref/move.sgml,v 1.16 2003/01/08 00:22:26 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -13,7 +13,7 @@ PostgreSQL documentation
|
|||||||
MOVE
|
MOVE
|
||||||
</refname>
|
</refname>
|
||||||
<refpurpose>
|
<refpurpose>
|
||||||
position a cursor on a specified row of a table
|
reposition a cursor
|
||||||
</refpurpose>
|
</refpurpose>
|
||||||
</refnamediv>
|
</refnamediv>
|
||||||
<refsynopsisdiv>
|
<refsynopsisdiv>
|
||||||
@ -21,9 +21,7 @@ PostgreSQL documentation
|
|||||||
<date>1999-07-20</date>
|
<date>1999-07-20</date>
|
||||||
</refsynopsisdivinfo>
|
</refsynopsisdivinfo>
|
||||||
<synopsis>
|
<synopsis>
|
||||||
MOVE [ <replaceable class="PARAMETER">direction</replaceable> ]
|
MOVE [ <replaceable class="PARAMETER">direction</replaceable> ] [ <replaceable class="PARAMETER">count</replaceable> ] { IN | FROM } <replaceable class="PARAMETER">cursor</replaceable>
|
||||||
{<replaceable class="PARAMETER">count</replaceable> | LAST }
|
|
||||||
{ IN | FROM } <replaceable class="PARAMETER">cursor</replaceable>
|
|
||||||
</synopsis>
|
</synopsis>
|
||||||
</refsynopsisdiv>
|
</refsynopsisdiv>
|
||||||
|
|
||||||
@ -35,12 +33,10 @@ MOVE [ <replaceable class="PARAMETER">direction</replaceable> ]
|
|||||||
Description
|
Description
|
||||||
</title>
|
</title>
|
||||||
<para>
|
<para>
|
||||||
<command>MOVE</command> allows a user to move the cursor position a
|
<command>MOVE</command> allows the user to move the cursor position a
|
||||||
specified number of rows.
|
specified number of rows, or all the way to the end or start of the query.
|
||||||
<command>MOVE</command> works like the <command>FETCH</command> command,
|
<command>MOVE</command> works exactly like the <command>FETCH</command>
|
||||||
but only positions the cursor and does not return rows.
|
command, except it only repositions the cursor and does not return rows.
|
||||||
<replaceable class="PARAMETER">LAST</replaceable> moves to the end
|
|
||||||
of the cursor.
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Refer to
|
Refer to
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.175 2003/01/06 18:53:23 petere Exp $
|
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.176 2003/01/08 00:22:26 tgl Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<appendix id="release">
|
<appendix id="release">
|
||||||
@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
|
|||||||
worries about funny characters.
|
worries about funny characters.
|
||||||
-->
|
-->
|
||||||
<literallayout><![CDATA[
|
<literallayout><![CDATA[
|
||||||
|
FETCH 0 now re-fetches cursor's current row, per SQL spec
|
||||||
Revised executor state representation; plan trees are read-only to executor now
|
Revised executor state representation; plan trees are read-only to executor now
|
||||||
Information schema
|
Information schema
|
||||||
Domains now support CHECK constraints
|
Domains now support CHECK constraints
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.7 2002/12/30 15:31:47 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/commands/portalcmds.c,v 1.8 2003/01/08 00:22:27 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -55,7 +55,7 @@ PortalCleanup(Portal portal)
|
|||||||
*
|
*
|
||||||
* name: name of portal
|
* name: name of portal
|
||||||
* forward: forward or backward fetch?
|
* forward: forward or backward fetch?
|
||||||
* count: # of tuples to fetch
|
* count: # of tuples to fetch (INT_MAX means "all"; 0 means "refetch")
|
||||||
* dest: where to send results
|
* dest: where to send results
|
||||||
* completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
|
* completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
|
||||||
* in which to store a command completion status string.
|
* in which to store a command completion status string.
|
||||||
@ -100,18 +100,15 @@ PerformPortalFetch(char *name,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If zero count, handle specially */
|
/*
|
||||||
|
* Zero count means to re-fetch the current row, if any (per SQL92)
|
||||||
|
*/
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
{
|
{
|
||||||
bool on_row = false;
|
bool on_row;
|
||||||
|
|
||||||
/* Are we sitting on a row? */
|
/* Are we sitting on a row? */
|
||||||
oldcontext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
|
on_row = (portal->atStart == false && portal->atEnd == false);
|
||||||
queryDesc = PortalGetQueryDesc(portal);
|
|
||||||
estate = queryDesc->estate;
|
|
||||||
if (portal->atStart == false && portal->atEnd == false)
|
|
||||||
on_row = true;
|
|
||||||
MemoryContextSwitchTo(oldcontext);
|
|
||||||
|
|
||||||
if (dest == None)
|
if (dest == None)
|
||||||
{
|
{
|
||||||
@ -122,26 +119,25 @@ PerformPortalFetch(char *name,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* If we are not on a row, FETCH 0 returns nothing */
|
/*
|
||||||
if (!on_row)
|
* If we are sitting on a row, back up one so we can re-fetch it.
|
||||||
return;
|
* If we are not sitting on a row, we still have to start up and
|
||||||
|
* shut down the executor so that the destination is initialized
|
||||||
/* Since we are sitting on a row, return the row */
|
* and shut down correctly; so keep going. Further down in the
|
||||||
/* Back up so we can reread the row */
|
* routine, count == 0 means we will retrieve no row.
|
||||||
PerformPortalFetch(name, false /* backward */, 1,
|
*/
|
||||||
None, /* throw away output */
|
if (on_row)
|
||||||
NULL /* do not modify the command tag */);
|
{
|
||||||
|
PerformPortalFetch(name, false /* backward */, 1L,
|
||||||
/* Set up to fetch one row */
|
None, /* throw away output */
|
||||||
count = 1;
|
NULL /* do not modify the command tag */);
|
||||||
forward = true;
|
/* Set up to fetch one row forward */
|
||||||
|
count = 1;
|
||||||
|
forward = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internally, zero count processes all portal rows */
|
|
||||||
if (count == LONG_MAX)
|
|
||||||
count = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* switch into the portal context
|
* switch into the portal context
|
||||||
*/
|
*/
|
||||||
@ -185,31 +181,45 @@ PerformPortalFetch(char *name,
|
|||||||
*/
|
*/
|
||||||
if (forward)
|
if (forward)
|
||||||
{
|
{
|
||||||
if (portal->atEnd)
|
if (portal->atEnd || count == 0)
|
||||||
direction = NoMovementScanDirection;
|
direction = NoMovementScanDirection;
|
||||||
else
|
else
|
||||||
direction = ForwardScanDirection;
|
direction = ForwardScanDirection;
|
||||||
|
|
||||||
ExecutorRun(queryDesc, direction, (long) count);
|
/* In the executor, zero count processes all portal rows */
|
||||||
|
if (count == INT_MAX)
|
||||||
|
count = 0;
|
||||||
|
|
||||||
if (estate->es_processed > 0)
|
ExecutorRun(queryDesc, direction, count);
|
||||||
portal->atStart = false; /* OK to back up now */
|
|
||||||
if (count <= 0 || (int) estate->es_processed < count)
|
if (direction != NoMovementScanDirection)
|
||||||
portal->atEnd = true; /* we retrieved 'em all */
|
{
|
||||||
|
if (estate->es_processed > 0)
|
||||||
|
portal->atStart = false; /* OK to back up now */
|
||||||
|
if (count <= 0 || (long) estate->es_processed < count)
|
||||||
|
portal->atEnd = true; /* we retrieved 'em all */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (portal->atStart)
|
if (portal->atStart || count == 0)
|
||||||
direction = NoMovementScanDirection;
|
direction = NoMovementScanDirection;
|
||||||
else
|
else
|
||||||
direction = BackwardScanDirection;
|
direction = BackwardScanDirection;
|
||||||
|
|
||||||
ExecutorRun(queryDesc, direction, (long) count);
|
/* In the executor, zero count processes all portal rows */
|
||||||
|
if (count == INT_MAX)
|
||||||
|
count = 0;
|
||||||
|
|
||||||
if (estate->es_processed > 0)
|
ExecutorRun(queryDesc, direction, count);
|
||||||
portal->atEnd = false; /* OK to go forward now */
|
|
||||||
if (count <= 0 || (int) estate->es_processed < count)
|
if (direction != NoMovementScanDirection)
|
||||||
portal->atStart = true; /* we retrieved 'em all */
|
{
|
||||||
|
if (estate->es_processed > 0)
|
||||||
|
portal->atEnd = false; /* OK to go forward now */
|
||||||
|
if (count <= 0 || (long) estate->es_processed < count)
|
||||||
|
portal->atStart = true; /* we retrieved 'em all */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return command status if wanted */
|
/* Return command status if wanted */
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.390 2003/01/06 00:31:44 tgl Exp $
|
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.391 2003/01/08 00:22:27 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -2594,7 +2594,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name
|
|||||||
if ($3 < 0)
|
if ($3 < 0)
|
||||||
{
|
{
|
||||||
$3 = -$3;
|
$3 = -$3;
|
||||||
$2 = (($2 == FORWARD)? BACKWARD: FORWARD);
|
$2 = (($2 == FORWARD) ? BACKWARD : FORWARD);
|
||||||
}
|
}
|
||||||
n->direction = $2;
|
n->direction = $2;
|
||||||
n->howMany = $3;
|
n->howMany = $3;
|
||||||
@ -2652,7 +2652,7 @@ FetchStmt: FETCH direction fetch_how_many from_in name
|
|||||||
if ($3 < 0)
|
if ($3 < 0)
|
||||||
{
|
{
|
||||||
$3 = -$3;
|
$3 = -$3;
|
||||||
$2 = (($2 == FORWARD) ? BACKWARD: FORWARD);
|
$2 = (($2 == FORWARD) ? BACKWARD : FORWARD);
|
||||||
}
|
}
|
||||||
n->direction = $2;
|
n->direction = $2;
|
||||||
n->howMany = $3;
|
n->howMany = $3;
|
||||||
@ -2720,8 +2720,8 @@ direction: FORWARD { $$ = FORWARD; }
|
|||||||
fetch_how_many:
|
fetch_how_many:
|
||||||
Iconst { $$ = $1; }
|
Iconst { $$ = $1; }
|
||||||
| '-' Iconst { $$ = - $2; }
|
| '-' Iconst { $$ = - $2; }
|
||||||
| ALL { $$ = LONG_MAX; }
|
| ALL { $$ = INT_MAX; }
|
||||||
| LAST { $$ = LONG_MAX; }
|
| LAST { $$ = INT_MAX; }
|
||||||
| NEXT { $$ = 1; }
|
| NEXT { $$ = 1; }
|
||||||
| PRIOR { $$ = -1; }
|
| PRIOR { $$ = -1; }
|
||||||
;
|
;
|
||||||
@ -7115,8 +7115,8 @@ unreserved_keyword:
|
|||||||
| INVOKER
|
| INVOKER
|
||||||
| ISOLATION
|
| ISOLATION
|
||||||
| KEY
|
| KEY
|
||||||
| LANGUAGE
|
|
||||||
| LANCOMPILER
|
| LANCOMPILER
|
||||||
|
| LANGUAGE
|
||||||
| LAST
|
| LAST
|
||||||
| LEVEL
|
| LEVEL
|
||||||
| LISTEN
|
| LISTEN
|
||||||
|
Loading…
Reference in New Issue
Block a user