Thread: Coding help

Coding help

From
Christopher Kings-Lynne
Date:
Hi guys,

I've asked this of a few people now, but I haven't managed to get a 
straightforward solution.

I'm working on COMMENT ON LARGE OBJECT.

If you could help me with this one, it would be really cool.  Other than
this, comment on language, conversion, cast and operator class are all done.

This is my grammar snippet.  NumericOnly seems to be the one to use -
that's what CREATE SEQUENCE uses for its large number support, and I
have to support large OIDs I presume.  I could also use IntegerOnly 
perhaps, I don't know:

| COMMENT ON LARGE OBJECT NumericOnly IS comment_text     {         CommentStmt *n = makeNode(CommentStmt);
n->objtype= OBJECT_LARGEOBJECT;         n->objname = makeList1(makeAConst($5));         n->objargs = NIL;
n->comment= $7;         $$ = (Node *) n;     }
 

This is my comment function:

static void
CommentLargeObject(List *qualname, char *comment)
{     /* This is what I cannot figure out - how do I change the Node 
which is the first element in the qualname to an actual Oid type??? */     Oid    loid =
somehow_get_oid_from(lfirst(qualname));    Oid    classoid;
 
     /* check that the large object exists */     if (!LargeObjectExists(loid))         ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),        errmsg("large object %u does not exist", loid)));
 
     classoid = get_system_catalog_relid(LargeObjectRelationName);
     CreateComments(loid, classoid, 0, comment);
}

The problem is extracting the oid from the qualname list.  I just can't
figure it out. I've searched the codebase but there doesn't seem to be
anywhere else that actually does this, like this.

I've tried all sorts of things, but I can't figure it out...

Thanks for any help,

Chris




Re: Coding help

From
Bruce Momjian
Date:
I guess you are asking how to get the NumericOnly converted to an oid,
and I see from the code that there are very few places where we allow
oid's to be supplied directly.  Most oid's come in as part of our
numberic conversion code.

The only idea I have is to call oidin() to do the conversion from string
to oid.  I see this in copy.c:
                   loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin,
CStringGetDatum(string)));                   if (loaded_oid == InvalidOid)                       ereport(ERROR,
                     (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),                                errmsg("invalid OID in COPY
data")));

I would give that a try.

---------------------------------------------------------------------------

Christopher Kings-Lynne wrote:
> Hi guys,
> 
> I've asked this of a few people now, but I haven't managed to get a 
> straightforward solution.
> 
> I'm working on COMMENT ON LARGE OBJECT.
> 
> If you could help me with this one, it would be really cool.  Other than
> this, comment on language, conversion, cast and operator class are all done.
> 
> This is my grammar snippet.  NumericOnly seems to be the one to use -
> that's what CREATE SEQUENCE uses for its large number support, and I
> have to support large OIDs I presume.  I could also use IntegerOnly 
> perhaps, I don't know:
> 
> | COMMENT ON LARGE OBJECT NumericOnly IS comment_text
>       {
>           CommentStmt *n = makeNode(CommentStmt);
>           n->objtype = OBJECT_LARGEOBJECT;
>           n->objname = makeList1(makeAConst($5));
>           n->objargs = NIL;
>           n->comment = $7;
>           $$ = (Node *) n;
>       }
> 
> This is my comment function:
> 
> static void
> CommentLargeObject(List *qualname, char *comment)
> {
>       /* This is what I cannot figure out - how do I change the Node 
> which is the first element in the qualname to an actual Oid type??? */
>       Oid    loid = somehow_get_oid_from(lfirst(qualname));
>       Oid    classoid;
> 
>       /* check that the large object exists */
>       if (!LargeObjectExists(loid))
>           ereport(ERROR,
>           (errcode(ERRCODE_UNDEFINED_OBJECT),
>           errmsg("large object %u does not exist", loid)));
> 
>       classoid = get_system_catalog_relid(LargeObjectRelationName);
> 
>       CreateComments(loid, classoid, 0, comment);
> }
> 
> The problem is extracting the oid from the qualname list.  I just can't
> figure it out. I've searched the codebase but there doesn't seem to be
> anywhere else that actually does this, like this.
> 
> I've tried all sorts of things, but I can't figure it out...
> 
> Thanks for any help,
> 
> Chris
> 
> 
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster
> 

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
359-1001+  If your life is a hard drive,     |  13 Roberts Road +  Christ can be your backup.        |  Newtown Square,
Pennsylvania19073
 


Re: Coding help

From
Christopher Kings-Lynne
Date:
> The only idea I have is to call oidin() to do the conversion from string
> to oid.  I see this in copy.c:
> 
>                     loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin,
>                                                CStringGetDatum(string)));
>                     if (loaded_oid == InvalidOid)
>                         ereport(ERROR,
>                                 (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
>                                  errmsg("invalid OID in COPY data")));
> 
> I would give that a try.

Yes but in this case, the Node is parsed like this:

| COMMENT ON LARGE OBJECT NumericOnly IS comment_text
{
 ...

 n->objname = makeList1(makeAConst($5));
 ...
 $$ = (Node *) n;
}

So there is no CString to convert to a Datum...

Chris





Re: Coding help

From
Bruce Momjian
Date:
Christopher Kings-Lynne wrote:
> 
> > The only idea I have is to call oidin() to do the conversion from string
> > to oid.  I see this in copy.c:
> > 
> >                     loaded_oid = DatumGetObjectId(DirectFunctionCall1(oidin,
> >                                                CStringGetDatum(string)));
> >                     if (loaded_oid == InvalidOid)
> >                         ereport(ERROR,
> >                                 (errcode(ERRCODE_BAD_COPY_FILE_FORMAT),
> >                                  errmsg("invalid OID in COPY data")));
> > 
> > I would give that a try.
> 
> Yes but in this case, the Node is parsed like this:
> 
> | COMMENT ON LARGE OBJECT NumericOnly IS comment_text
> {
> 
>   ...
> 
> 
>   n->objname = makeList1(makeAConst($5));
> 
>   ...
> 
>   $$ = (Node *) n;
> }
> 
> So there is no CString to convert to a Datum...

But I see makeAConst as:static Node *makeAConst(Value *v){    Node *n;    switch (v->type)    {        case T_Float:
       n = makeFloatConst(v->val.str);            break;        case T_Integer:            n =
makeIntConst(v->val.ival);           break;        case T_String:        default:            n =
makeStringConst(v->val.str,NULL);            break;    }    return n;}
 

which uses makeStringConst().

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
359-1001+  If your life is a hard drive,     |  13 Roberts Road +  Christ can be your backup.        |  Newtown Square,
Pennsylvania19073
 


Re: Coding help

From
Tom Lane
Date:
Christopher Kings-Lynne <chriskl@familyhealth.com.au> writes:
> | COMMENT ON LARGE OBJECT NumericOnly IS comment_text
>   n->objname = makeList1(makeAConst($5));

Forget the makeAConst step --- it's just wasted cycles.  In the
execution routine, you can use code comparable to define.c's defGetInt64()
to convert the Value node into a numeric OID, ie, either do intVal() or
a call of oidin().
        regards, tom lane


Re: Coding help

From
Christopher Kings-Lynne
Date:
>>| COMMENT ON LARGE OBJECT NumericOnly IS comment_text
>>  n->objname = makeList1(makeAConst($5));
> 
> 
> Forget the makeAConst step --- it's just wasted cycles.  In the
> execution routine, you can use code comparable to define.c's defGetInt64()
> to convert the Value node into a numeric OID, ie, either do intVal() or
> a call of oidin().

I thought the whole problem here is that OIDs are unsigned ints, hence 
intVal() won't allow the highest OIDs?  If that's not the case, then the  easy solution is to just use an IConst or
whateverit's called. (Which 
 
I had working before).

Chris



Re: Coding help

From
Tom Lane
Date:
Christopher Kings-Lynne <chriskl@familyhealth.com.au> writes:
>> ... you can use code comparable to define.c's defGetInt64()
>> to convert the Value node into a numeric OID, ie, either do intVal() or
>> a call of oidin().

> I thought the whole problem here is that OIDs are unsigned ints, hence 
> intVal() won't allow the highest OIDs?

Exactly.  That's why you need to handle T_Float too.  See the int8
example, which has just the same problem.
        regards, tom lane


Re: Coding help

From
Christopher Kings-Lynne
Date:
>>I thought the whole problem here is that OIDs are unsigned ints, hence 
>>intVal() won't allow the highest OIDs?
> 
> 
> Exactly.  That's why you need to handle T_Float too.  See the int8
> example, which has just the same problem.

It occurs to me then that I could just then use FloatOnly in the grammar 
and   then just attempt to coerce that to an Oid using oidin?  Floats 
are stored as strings, so that'd be OK, and the oidin function would 
barf if it was an illegal uint?

Chris





Re: Coding help

From
Tom Lane
Date:
Christopher Kings-Lynne <chriskl@familyhealth.com.au> writes:
> It occurs to me then that I could just then use FloatOnly in the grammar 

I don't think so, unless you are proposing something very odd in the
lexer to force it to treat an integer literal as a float in this one
context.

What is the problem with following the lead of the existing code?
        regards, tom lane