mirror of
https://github.com/postgres/postgres.git
synced 2025-07-17 06:41:09 +03:00
Pass attypmod through to executor by adding to Var and Resdom.
This commit is contained in:
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.69 1998/02/06 16:46:28 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.70 1998/02/10 04:01:38 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -307,7 +307,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
te = makeNode(TargetEntry);
|
||||
te->resdom = makeResdom(defval[ndef].adnum,
|
||||
att[defval[ndef].adnum - 1]->atttypid,
|
||||
att[defval[ndef].adnum - 1]->attlen,
|
||||
att[defval[ndef].adnum - 1]->atttypmod,
|
||||
pstrdup(nameout(&(att[defval[ndef].adnum - 1]->attname))),
|
||||
0, 0, 0);
|
||||
te->fjoin = NULL;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.104 1998/02/04 06:11:46 thomas Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 1.105 1998/02/10 04:01:44 momjian Exp $
|
||||
*
|
||||
* HISTORY
|
||||
* AUTHOR DATE MAJOR EVENT
|
||||
@ -1314,6 +1314,7 @@ def_arg: ColId { $$ = (Node *)makeString($1); }
|
||||
n->name = $2;
|
||||
n->setof = TRUE;
|
||||
n->arrayBounds = NULL;
|
||||
n->typmod = -1;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| DOUBLE { $$ = (Node *)makeString("double"); }
|
||||
@ -2218,6 +2219,7 @@ LockStmt: LOCK_P relation_name
|
||||
c->val.val.str = "f";
|
||||
c->typename = makeNode(TypeName);
|
||||
c->typename->name = xlateSqlType("bool");
|
||||
c->typename->typmod = -1;
|
||||
|
||||
n->relname = $2;
|
||||
n->whereClause = (Node *)c;
|
||||
@ -2656,6 +2658,7 @@ Generic: generic
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType($1);
|
||||
$$->typmod = -1;
|
||||
}
|
||||
;
|
||||
|
||||
@ -2674,16 +2677,19 @@ Numeric: FLOAT opt_float
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType($2);
|
||||
$$->typmod = -1;
|
||||
}
|
||||
| DECIMAL opt_decimal
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType("integer");
|
||||
$$->typmod = -1;
|
||||
}
|
||||
| NUMERIC opt_numeric
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType("integer");
|
||||
$$->typmod = -1;
|
||||
}
|
||||
;
|
||||
|
||||
@ -2779,6 +2785,7 @@ Character: character '(' Iconst ')'
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType($1);
|
||||
$$->typmod = -1;
|
||||
}
|
||||
;
|
||||
|
||||
@ -2824,22 +2831,26 @@ Datetime: datetime
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType($1);
|
||||
$$->typmod = -1;
|
||||
}
|
||||
| TIMESTAMP opt_timezone
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType("timestamp");
|
||||
$$->timezone = $2;
|
||||
$$->typmod = -1;
|
||||
}
|
||||
| TIME
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType("time");
|
||||
$$->typmod = -1;
|
||||
}
|
||||
| INTERVAL opt_interval
|
||||
{
|
||||
$$ = makeNode(TypeName);
|
||||
$$->name = xlateSqlType("interval");
|
||||
$$->typmod = -1;
|
||||
}
|
||||
;
|
||||
|
||||
@ -3327,7 +3338,8 @@ a_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("date");
|
||||
t->setof = FALSE;
|
||||
|
||||
t->typmod = -1;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| CURRENT_TIME
|
||||
@ -3341,6 +3353,7 @@ a_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("time");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
@ -3359,6 +3372,7 @@ a_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("time");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
if ($3 != 0)
|
||||
elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
|
||||
@ -3376,6 +3390,7 @@ a_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("timestamp");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
@ -3394,6 +3409,7 @@ a_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("timestamp");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
if ($3 != 0)
|
||||
elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
|
||||
@ -3487,6 +3503,7 @@ a_expr: attr opt_indirection
|
||||
n->val.val.str = "t";
|
||||
n->typename = makeNode(TypeName);
|
||||
n->typename->name = xlateSqlType("bool");
|
||||
n->typename->typmod = -1;
|
||||
$$ = makeA_Expr(OP, "=", $1,(Node *)n);
|
||||
}
|
||||
| a_expr IS NOT FALSE_P
|
||||
@ -3496,6 +3513,7 @@ a_expr: attr opt_indirection
|
||||
n->val.val.str = "t";
|
||||
n->typename = makeNode(TypeName);
|
||||
n->typename->name = xlateSqlType("bool");
|
||||
n->typename->typmod = -1;
|
||||
$$ = makeA_Expr(OP, "=", $1,(Node *)n);
|
||||
}
|
||||
| a_expr IS FALSE_P
|
||||
@ -3505,6 +3523,7 @@ a_expr: attr opt_indirection
|
||||
n->val.val.str = "f";
|
||||
n->typename = makeNode(TypeName);
|
||||
n->typename->name = xlateSqlType("bool");
|
||||
n->typename->typmod = -1;
|
||||
$$ = makeA_Expr(OP, "=", $1,(Node *)n);
|
||||
}
|
||||
| a_expr IS NOT TRUE_P
|
||||
@ -3514,6 +3533,7 @@ a_expr: attr opt_indirection
|
||||
n->val.val.str = "f";
|
||||
n->typename = makeNode(TypeName);
|
||||
n->typename->name = xlateSqlType("bool");
|
||||
n->typename->typmod = -1;
|
||||
$$ = makeA_Expr(OP, "=", $1,(Node *)n);
|
||||
}
|
||||
| a_expr BETWEEN b_expr AND b_expr
|
||||
@ -3906,6 +3926,7 @@ b_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("date");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
@ -3920,6 +3941,7 @@ b_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("time");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
@ -3938,6 +3960,7 @@ b_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("time");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
if ($3 != 0)
|
||||
elog(NOTICE,"CURRENT_TIME(%d) precision not implemented; zero used instead",$3);
|
||||
@ -3955,6 +3978,7 @@ b_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("timestamp");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
@ -3973,6 +3997,7 @@ b_expr: attr opt_indirection
|
||||
|
||||
t->name = xlateSqlType("timestamp");
|
||||
t->setof = FALSE;
|
||||
t->typmod = -1;
|
||||
|
||||
if ($3 != 0)
|
||||
elog(NOTICE,"CURRENT_TIMESTAMP(%d) precision not implemented; zero used instead",$3);
|
||||
@ -4478,6 +4503,7 @@ AexprConst: Iconst
|
||||
n->val.val.str = "t";
|
||||
n->typename = makeNode(TypeName);
|
||||
n->typename->name = xlateSqlType("bool");
|
||||
n->typename->typmod = -1;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| FALSE_P
|
||||
@ -4487,6 +4513,7 @@ AexprConst: Iconst
|
||||
n->val.val.str = "f";
|
||||
n->typename = makeNode(TypeName);
|
||||
n->typename->name = xlateSqlType("bool");
|
||||
n->typename->typmod = -1;
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.12 1998/02/05 04:08:42 scrappy Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.13 1998/02/10 04:01:52 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -192,13 +192,10 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
*/
|
||||
if (get_attnum(relid, funcname) != InvalidAttrNumber)
|
||||
{
|
||||
Oid dummyTypeId;
|
||||
|
||||
return ((Node *) make_var(pstate,
|
||||
return (Node *) make_var(pstate,
|
||||
relid,
|
||||
refname,
|
||||
funcname,
|
||||
&dummyTypeId));
|
||||
funcname);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -311,7 +308,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
|
||||
toid = typeTypeId(typenameType(relname));
|
||||
/* replace it in the arg list */
|
||||
lfirst(fargs) =
|
||||
makeVar(vnum, 0, toid, 0, vnum, 0);
|
||||
makeVar(vnum, 0, toid, -1, 0, vnum, 0);
|
||||
}
|
||||
else if (!attisset)
|
||||
{ /* set functions don't have parameters */
|
||||
@ -1059,6 +1056,7 @@ setup_tlist(char *attname, Oid relid)
|
||||
Resdom *resnode;
|
||||
Var *varnode;
|
||||
Oid typeid;
|
||||
int type_mod;
|
||||
int attno;
|
||||
|
||||
attno = get_attnum(relid, attname);
|
||||
@ -1066,14 +1064,16 @@ setup_tlist(char *attname, Oid relid)
|
||||
elog(ERROR, "cannot reference attribute '%s' of tuple params/return values for functions", attname);
|
||||
|
||||
typeid = get_atttype(relid, attno);
|
||||
type_mod = get_atttypmod(relid, attno);
|
||||
|
||||
resnode = makeResdom(1,
|
||||
typeid,
|
||||
typeLen(typeidType(typeid)),
|
||||
type_mod,
|
||||
get_attname(relid, attno),
|
||||
0,
|
||||
(Oid) 0,
|
||||
0);
|
||||
varnode = makeVar(-1, attno, typeid, 0, -1, attno);
|
||||
varnode = makeVar(-1, attno, typeid, type_mod, 0, -1, attno);
|
||||
|
||||
tle = makeNode(TargetEntry);
|
||||
tle->resdom = resnode;
|
||||
@ -1095,12 +1095,12 @@ setup_base_tlist(Oid typeid)
|
||||
|
||||
resnode = makeResdom(1,
|
||||
typeid,
|
||||
typeLen(typeidType(typeid)),
|
||||
-1,
|
||||
"<noname>",
|
||||
0,
|
||||
(Oid) 0,
|
||||
0);
|
||||
varnode = makeVar(-1, 1, typeid, 0, -1, 1);
|
||||
varnode = makeVar(-1, 1, typeid, -1, 0, -1, 1);
|
||||
tle = makeNode(TargetEntry);
|
||||
tle->resdom = resnode;
|
||||
tle->expr = (Node *) varnode;
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.10 1998/01/20 22:11:57 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_node.c,v 1.11 1998/02/10 04:01:55 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -240,12 +240,13 @@ make_op(char *opname, Node *ltree, Node *rtree)
|
||||
|
||||
Var *
|
||||
make_var(ParseState *pstate, Oid relid, char *refname,
|
||||
char *attrname, Oid *type_id)
|
||||
char *attrname)
|
||||
{
|
||||
Var *varnode;
|
||||
int vnum,
|
||||
attid;
|
||||
Oid vartypeid;
|
||||
int type_mod;
|
||||
int sublevels_up;
|
||||
|
||||
vnum = refnameRangeTablePosn(pstate, refname, &sublevels_up);
|
||||
@ -255,9 +256,10 @@ make_var(ParseState *pstate, Oid relid, char *refname,
|
||||
elog(ERROR, "Relation %s does not have attribute %s",
|
||||
refname, attrname);
|
||||
vartypeid = get_atttype(relid, attid);
|
||||
type_mod = get_atttypmod(relid, attid);
|
||||
|
||||
varnode = makeVar(vnum, attid, vartypeid, sublevels_up, vnum, attid);
|
||||
*type_id = vartypeid;
|
||||
varnode = makeVar(vnum, attid, vartypeid, type_mod,
|
||||
sublevels_up, vnum, attid);
|
||||
|
||||
return varnode;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.9 1998/02/05 22:48:44 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_relation.c,v 1.10 1998/02/10 04:01:56 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -234,8 +234,6 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
|
||||
Var *varnode;
|
||||
int varattno,
|
||||
maxattrs;
|
||||
Oid type_id;
|
||||
int type_len;
|
||||
RangeTblEntry *rte;
|
||||
|
||||
rte = refnameRangeTableEntry(pstate, refname);
|
||||
@ -257,9 +255,7 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
|
||||
TargetEntry *te = makeNode(TargetEntry);
|
||||
|
||||
attrname = pstrdup((rdesc->rd_att->attrs[varattno]->attname).data);
|
||||
varnode = (Var *) make_var(pstate, rte->relid, refname,
|
||||
attrname, &type_id);
|
||||
type_len = (int) typeLen(typeidType(type_id));
|
||||
varnode = (Var *) make_var(pstate, rte->relid, refname, attrname);
|
||||
|
||||
handleTargetColname(pstate, &resname, refname, attrname);
|
||||
if (resname != NULL)
|
||||
@ -271,8 +267,8 @@ expandAll(ParseState *pstate, char *relname, char *refname, int *this_resno)
|
||||
*/
|
||||
|
||||
te->resdom = makeResdom((AttrNumber) (*this_resno)++,
|
||||
type_id,
|
||||
(Size) type_len,
|
||||
varnode->vartype,
|
||||
varnode->vartypmod,
|
||||
attrname,
|
||||
(Index) 0,
|
||||
(Oid) 0,
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.7 1998/01/20 05:04:26 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/parser/parse_target.c,v 1.8 1998/02/10 04:01:57 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -25,6 +25,7 @@
|
||||
#include "parser/parse_relation.h"
|
||||
#include "parser/parse_target.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/lsyscache.h"
|
||||
|
||||
static List *expandAllTables(ParseState *pstate);
|
||||
static char *figureColname(Node *expr, Node *resval);
|
||||
@ -54,7 +55,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
{
|
||||
Node *expr;
|
||||
Oid type_id;
|
||||
int type_len;
|
||||
int type_mod;
|
||||
char *identname;
|
||||
char *resname;
|
||||
|
||||
@ -67,11 +68,14 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
*/
|
||||
expr = transformIdent(pstate, (Node *) res->val, EXPR_COLUMN_FIRST);
|
||||
type_id = exprType(expr);
|
||||
type_len = typeLen(typeidType(type_id));
|
||||
if (nodeTag(expr) == T_Var)
|
||||
type_mod = ((Var *)expr)->vartypmod;
|
||||
else
|
||||
type_mod = -1;
|
||||
resname = (res->name) ? res->name : identname;
|
||||
tent->resdom = makeResdom((AttrNumber) pstate->p_last_resno++,
|
||||
(Oid) type_id,
|
||||
(Size) type_len,
|
||||
type_mod,
|
||||
resname,
|
||||
(Index) 0,
|
||||
(Oid) 0,
|
||||
@ -190,7 +194,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
case T_Attr:
|
||||
{
|
||||
Oid type_id;
|
||||
int type_len;
|
||||
int type_mod;
|
||||
Attr *att = (Attr *) res->val;
|
||||
Node *result;
|
||||
char *attrname;
|
||||
@ -253,8 +257,7 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
|
||||
|
||||
/*
|
||||
* Target item is fully specified: ie.
|
||||
* relation.attribute
|
||||
* Target item is fully specified: ie. relation.attribute
|
||||
*/
|
||||
result = ParseNestedFuncOrColumn(pstate, att, &pstate->p_last_resno,EXPR_COLUMN_FIRST);
|
||||
handleTargetColname(pstate, &res->name, att->relname, attrname);
|
||||
@ -273,14 +276,17 @@ transformTargetList(ParseState *pstate, List *targetlist)
|
||||
result = (Node *) make_array_ref(result, att->indirection);
|
||||
}
|
||||
type_id = exprType(result);
|
||||
type_len = typeLen(typeidType(type_id));
|
||||
if (nodeTag(result) == T_Var)
|
||||
type_mod = ((Var *)result)->vartypmod;
|
||||
else
|
||||
type_mod = -1;
|
||||
/* move to last entry */
|
||||
while (lnext(attrs) != NIL)
|
||||
attrs = lnext(attrs);
|
||||
resname = (res->name) ? res->name : strVal(lfirst(attrs));
|
||||
resnode = makeResdom((AttrNumber) pstate->p_last_resno++,
|
||||
(Oid) type_id,
|
||||
(Size) type_len,
|
||||
type_mod,
|
||||
resname,
|
||||
(Index) 0,
|
||||
(Oid) 0,
|
||||
@ -326,8 +332,7 @@ make_targetlist_expr(ParseState *pstate,
|
||||
{
|
||||
Oid type_id,
|
||||
attrtype;
|
||||
int type_len,
|
||||
attrlen,
|
||||
int type_mod,
|
||||
attrtypmod;
|
||||
int resdomno;
|
||||
Relation rd;
|
||||
@ -339,12 +344,10 @@ make_targetlist_expr(ParseState *pstate,
|
||||
elog(ERROR, "make_targetlist_expr: invalid use of NULL expression");
|
||||
|
||||
type_id = exprType(expr);
|
||||
if (type_id == InvalidOid)
|
||||
{
|
||||
type_len = 0;
|
||||
}
|
||||
if (nodeTag(expr) == T_Var)
|
||||
type_mod = ((Var *)expr)->vartypmod;
|
||||
else
|
||||
type_len = typeLen(typeidType(type_id));
|
||||
type_mod = -1;
|
||||
|
||||
/* Processes target columns that will be receiving results */
|
||||
if (pstate->p_is_insert || pstate->p_is_update)
|
||||
@ -361,7 +364,6 @@ make_targetlist_expr(ParseState *pstate,
|
||||
attrtype = attnumTypeId(rd, resdomno);
|
||||
if ((arrayRef != NIL) && (lfirst(arrayRef) == NIL))
|
||||
attrtype = GetArrayElementType(attrtype);
|
||||
attrlen = typeLen(typeidType(attrtype));
|
||||
attrtypmod = rd->rd_att->attrs[resdomno - 1]->atttypmod;
|
||||
#if 0
|
||||
if (Input_is_string && Typecast_ok)
|
||||
@ -438,7 +440,7 @@ make_targetlist_expr(ParseState *pstate,
|
||||
else
|
||||
expr = (Node *) parser_typecast2(expr,
|
||||
type_id,
|
||||
typeidType(attrtype),
|
||||
typeidType(attrtype),
|
||||
attrtypmod);
|
||||
}
|
||||
else
|
||||
@ -486,20 +488,20 @@ make_targetlist_expr(ParseState *pstate,
|
||||
lowerIndexpr,
|
||||
(Expr *) expr);
|
||||
attrtype = attnumTypeId(rd, resdomno);
|
||||
attrlen = typeLen(typeidType(attrtype));
|
||||
attrtypmod = get_atttypmod(rd->rd_id, resdomno);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
resdomno = pstate->p_last_resno++;
|
||||
attrtype = type_id;
|
||||
attrlen = type_len;
|
||||
attrtypmod = type_mod;
|
||||
}
|
||||
tent = makeNode(TargetEntry);
|
||||
|
||||
resnode = makeResdom((AttrNumber) resdomno,
|
||||
(Oid) attrtype,
|
||||
(Size) attrlen,
|
||||
attrtypmod,
|
||||
colname,
|
||||
(Index) 0,
|
||||
(Oid) 0,
|
||||
|
Reference in New Issue
Block a user