Coding help

Started by Christopher Kings-Lynneabout 22 years ago9 messages
#1Christopher Kings-Lynne
chriskl@familyhealth.com.au

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

#2Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Christopher Kings-Lynne (#1)
Re: Coding help

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, Pennsylvania 19073
#3Christopher Kings-Lynne
chriskl@familyhealth.com.au
In reply to: Bruce Momjian (#2)
Re: Coding help

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

#4Bruce Momjian
pgman@candle.pha.pa.us
In reply to: Christopher Kings-Lynne (#3)
Re: Coding help

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, Pennsylvania 19073
#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Christopher Kings-Lynne (#3)
Re: Coding help

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

#6Christopher Kings-Lynne
chriskl@familyhealth.com.au
In reply to: Tom Lane (#5)
Re: Coding help

| 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 whatever it's called. (Which
I had working before).

Chris

#7Tom Lane
tgl@sss.pgh.pa.us
In reply to: Christopher Kings-Lynne (#6)
Re: Coding help

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

#8Christopher Kings-Lynne
chriskl@familyhealth.com.au
In reply to: Tom Lane (#7)
Re: Coding help

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

#9Tom Lane
tgl@sss.pgh.pa.us
In reply to: Christopher Kings-Lynne (#8)
Re: Coding help

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