Thread: CommitFest 2009-09, two weeks on

CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
It's now been two weeks since we started this CommitFest, so it seems
like a good time to review where we are.  Here are my thoughts, for
what that's worth.

Our overall rate of progress is significantly slower than it was last
time around.  At a similar point in the July CommitFest, 19 patches
had been committed (not counting 3 that were committed before the
start of the CommitFest), 11 had been returned with feedback (again,
not counting 2 from before the start of the CommitFest), and 3 had
been rejected.  The corresponding numbers for this CommitFest are 8,
7, and 3, which means that the rate of returning patches with feedback
and/or rejecting them is only modestly lower, but the rate of
committing is much lower.  I'm not sure whether this is because the
patches are more complex, because the committers have been busy with
other issues, or some other reason.

We also have fewer patches than we did last time around.  I believe we
started the last CommitFest with a bit more than 75 patches (there are
fewer now, as some were moved to this CommitFest) and we started this
one with just 48.  This somewhat balances out the slower rate of
grinding through the patch queue, but I'm still a bit worried about
the rate at which we're making progress.  It would be nice to be done
on time, and I'm not sure we're going to make it.

With respect to individual patches:

- There are three ECPG patches for which it's been difficult to find a
reviewer.  It seems we don't have any reviewers familiar with ECPG.
If anyone is able to help review these, it would be much appreciated.
- There is one dblink pach left over from last CommitFest.  Joe Conway
was going to review it the weekend of July 18th-19th, but that didn't
end up happening and so that patch is still waiting.  We might be able
to find someone else to review it, but I'm not sure whether that will
help unless there is a committer other than Joe with bandwidth to do
the final review and commit.
- Hot Standby and Streaming Replication are both huge new features in
this CommitFest, and there seems to be a fair amount of activity
around both patches.  Heikki previously expressed optimism about
getting Hot Standby done this CommitFest, but I am not sure whether he
is still feeling optimistic, or what his feelings are about Streaming
Replication, which is currently waiting on Fujii Masao for a new
version.

On the whole, it seems like patch authors have done a better job than
last time of responding to feedback in a timely fashion - very little
is falling out due to submitter inattention.  That is good, although
it also means that the percentage of patches that will require
substantive action (rather than, say, summary rejection for
non-communication) is apt to be higher.  I am also generally under the
impression that we have a larger number of complex patches this time
around.  Some of that may be because much good feedback was given in
the last CommitFest, and previously half-baked ideas are coming back a
little more well done.

...Robert


Re: CommitFest 2009-09, two weeks on

From
Heikki Linnakangas
Date:
Robert Haas wrote:
> - Hot Standby and Streaming Replication are both huge new features in
> this CommitFest, and there seems to be a fair amount of activity
> around both patches.  Heikki previously expressed optimism about
> getting Hot Standby done this CommitFest, but I am not sure whether he
> is still feeling optimistic,

There's a lot of small things that need fixing, but nothing major. I'm
not so much optimistic, but I think we should spend the extra effort
required on hot standby to force it in in this commitfest. It's a big
feature and it really could use some alpha-testing earlier rather than
later. It would also leave time for any extra features or tweaks to be
made in the later commitfests.

OTOH, I'd hate to hold the commitfest hostage for that. Perhaps it
should be returned to author at this point, I should move on to other
patches to get the commitfest closed ASAP, and continue reviewing and
polishing that right after the commitfest.

> or what his feelings are about Streaming
> Replication, which is currently waiting on Fujii Masao for a new
> version.

I'm undecided on whether walreceiver should be a subprocess of the
startup process, or of postmaster as it was submitted. I'd appreciate if
others would take a look into that too and give opinions. And then
there's the small list of things I asked Fujii-san to work on.

--  Heikki Linnakangas EnterpriseDB   http://www.enterprisedb.com


Re: CommitFest 2009-09, two weeks on

From
Tom Lane
Date:
Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> writes:
> OTOH, I'd hate to hold the commitfest hostage for that. Perhaps it
> should be returned to author at this point, I should move on to other
> patches to get the commitfest closed ASAP, and continue reviewing and
> polishing that right after the commitfest.

FWIW, I'd rather you kept focusing on those two patches while other
committers work on the rest.  From what I've seen you're finding a
whole lot of broken or at least questionable stuff, and even if they're
individually minor issues, that adds up to a lot of instability.

I agree that these patches need special attention and should not be
treated exactly the same as we'd treat smaller patches.
        regards, tom lane


Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
On Wed, Sep 30, 2009 at 11:36 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> writes:
>> OTOH, I'd hate to hold the commitfest hostage for that. Perhaps it
>> should be returned to author at this point, I should move on to other
>> patches to get the commitfest closed ASAP, and continue reviewing and
>> polishing that right after the commitfest.
>
> FWIW, I'd rather you kept focusing on those two patches while other
> committers work on the rest.  From what I've seen you're finding a
> whole lot of broken or at least questionable stuff, and even if they're
> individually minor issues, that adds up to a lot of instability.
>
> I agree that these patches need special attention and should not be
> treated exactly the same as we'd treat smaller patches.

I tend to agree.  I think it's reasonable for you (meaning Heikki) to
devote far more time and effort to those patches than you would to
other patches implementing more run-of-the-mill features, and it seems
like there is no shortage of things to find and fix.  I don't think
that having you take a break to work on other patches is going to be
to the overall benefit of the project (and many of the more
significant remaining patches look like they are right up Tom's alley
anyway).

That having been said, if Hot Standby is still closer to commit than
Streaming Replication, it might make sense to push Streaming
Replication off until November, or at least post-CommitFest.  Do you
have any sense of how soon you'll feel confident to commit either
patch?

...Robert


Re: CommitFest 2009-09, two weeks on

From
Joe Conway
Date:
Robert Haas wrote:
> - There is one dblink pach left over from last CommitFest.  Joe Conway
> was going to review it the weekend of July 18th-19th, but that didn't
> end up happening and so that patch is still waiting.  We might be able
> to find someone else to review it, but I'm not sure whether that will
> help unless there is a committer other than Joe with bandwidth to do
> the final review and commit.

I will get to it before the end of this commitfest, but I have to admit
I'm not all that excited about this patch in the first place. I don't
know that I agree with the need.

Joe


Re: CommitFest 2009-09, two weeks on

From
Heikki Linnakangas
Date:
Robert Haas wrote:
> On Wed, Sep 30, 2009 at 11:36 AM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Heikki Linnakangas <heikki.linnakangas@enterprisedb.com> writes:
>>> OTOH, I'd hate to hold the commitfest hostage for that. Perhaps it
>>> should be returned to author at this point, I should move on to other
>>> patches to get the commitfest closed ASAP, and continue reviewing and
>>> polishing that right after the commitfest.
>> FWIW, I'd rather you kept focusing on those two patches while other
>> committers work on the rest.  From what I've seen you're finding a
>> whole lot of broken or at least questionable stuff, and even if they're
>> individually minor issues, that adds up to a lot of instability.
>>
>> I agree that these patches need special attention and should not be
>> treated exactly the same as we'd treat smaller patches.
> 
> I tend to agree.  I think it's reasonable for you (meaning Heikki) to
> devote far more time and effort to those patches than you would to
> other patches implementing more run-of-the-mill features, and it seems
> like there is no shortage of things to find and fix.  I don't think
> that having you take a break to work on other patches is going to be
> to the overall benefit of the project (and many of the more
> significant remaining patches look like they are right up Tom's alley
> anyway).

Ok, good, I'm more than happy to continue fine-combing hot standby.

> That having been said, if Hot Standby is still closer to commit than
> Streaming Replication, it might make sense to push Streaming
> Replication off until November, or at least post-CommitFest.

Commitfest or no-commitfest, I'm planning to continue working on the
streaming replication patch in any case until it's committed.

>  Do you
> have any sense of how soon you'll feel confident to commit either
> patch?

I'm bad at estimating. Not this week for sure, and next week I'm
traveling and won't be able to spend as much time on it as I am right
now. If no new major issues are found, and all the outstanding issues
are resolved by me or Simon by then, maybe the week after that.

--  Heikki Linnakangas EnterpriseDB   http://www.enterprisedb.com


Re: CommitFest 2009-09, two weeks on

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> Robert Haas wrote:
>> - There is one dblink pach left over from last CommitFest.  Joe Conway
>> was going to review it the weekend of July 18th-19th, but that didn't
>> end up happening and so that patch is still waiting.  We might be able
>> to find someone else to review it, but I'm not sure whether that will
>> help unless there is a committer other than Joe with bandwidth to do
>> the final review and commit.

> I will get to it before the end of this commitfest, but I have to admit
> I'm not all that excited about this patch in the first place. I don't
> know that I agree with the need.

Well, you're the dblink expert.  If you think it should be rejected
I doubt many of us will argue with you.
        regards, tom lane


Re: CommitFest 2009-09, two weeks on

From
Tom Lane
Date:
Robert Haas <robertmhaas@gmail.com> writes:
> ... (and many of the more
> significant remaining patches look like they are right up Tom's alley
> anyway).

FWIW, if left to my own devices I will eventually get to everything
except the dblink, ecpg, and encoding/win32 patches.  I don't intend
to touch any of those because there are other committers better
qualified to review them.  (I don't actually think we have anybody
except Michael who's really familiar with ecpg.)

However, if no other committers are working on it it's going to be
a long commitfest ...

The other problem is that most of the patches are not Ready for
Committer anyway.
        regards, tom lane


Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
On Wed, Sep 30, 2009 at 12:27 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Joe Conway <mail@joeconway.com> writes:
>> Robert Haas wrote:
>>> - There is one dblink pach left over from last CommitFest.  Joe Conway
>>> was going to review it the weekend of July 18th-19th, but that didn't
>>> end up happening and so that patch is still waiting.  We might be able
>>> to find someone else to review it, but I'm not sure whether that will
>>> help unless there is a committer other than Joe with bandwidth to do
>>> the final review and commit.
>
>> I will get to it before the end of this commitfest, but I have to admit
>> I'm not all that excited about this patch in the first place. I don't
>> know that I agree with the need.
>
> Well, you're the dblink expert.  If you think it should be rejected
> I doubt many of us will argue with you.

Yep.  CommitFest doesn't mean "commit it"; it means "decide whether to
commit it".  Things being rejected or returned with feedback for
further improvement is fine; we're just trying to avoid long periods
with no response at all.

...Robert


Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
On Wed, Sep 30, 2009 at 12:34 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
>> ... (and many of the more
>> significant remaining patches look like they are right up Tom's alley
>> anyway).
>
> FWIW, if left to my own devices I will eventually get to everything
> except the dblink, ecpg, and encoding/win32 patches.  I don't intend
> to touch any of those because there are other committers better
> qualified to review them.  (I don't actually think we have anybody
> except Michael who's really familiar with ecpg.)

Thanks, I think that's helpful information.

> However, if no other committers are working on it it's going to be
> a long commitfest ...

That is my concern as well.

> The other problem is that most of the patches are not Ready for
> Committer anyway.

I (and hopefully the people who agreed to help with patch-chasing) can
work on this, but given that there are 5 that are Ready for Committer
and probably as many more that are close, and further given that in
the past 7 days exactly 1 patch from the CommitFest has been
committed, I'm not sure there's a real problem here.  If you
commit/bounce all 5 of those afternoon I will spend the evening making
sure you have a few more to tackle tomorrow.

...Robert


Re: CommitFest 2009-09, two weeks on

From
Andrew Dunstan
Date:

Robert Haas wrote:
> On Wed, Sep 30, 2009 at 12:34 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>   
>> Robert Haas <robertmhaas@gmail.com> writes:
>>     
>>> ... (and many of the more
>>> significant remaining patches look like they are right up Tom's alley
>>> anyway).
>>>       
>> FWIW, if left to my own devices I will eventually get to everything
>> except the dblink, ecpg, and encoding/win32 patches.  I don't intend
>> to touch any of those because there are other committers better
>> qualified to review them.  (I don't actually think we have anybody
>> except Michael who's really familiar with ecpg.)
>>     
>
> Thanks, I think that's helpful information.
>
>   
>> However, if no other committers are working on it it's going to be
>> a long commitfest ...
>>     
>
> That is my concern as well.
>
>   

I have been (and still am somewhat) slammed, but I can probably make 
space to work on "Encoding issues in console and eventlog on win32 
<https://commitfest.postgresql.org/action/patch_view?id=148>" some time 
in the next day or three. After that, if I still have time and nobody 
else has grabbed it, I'll move on to "CREATE LIKE INCLUDING COMMENTS and 
STORAGE <https://commitfest.postgresql.org/action/patch_view?id=172>".

cheers

andrew


Re: CommitFest 2009-09, two weeks on

From
Joe Conway
Date:
Robert Haas wrote:
> On Wed, Sep 30, 2009 at 12:27 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Joe Conway <mail@joeconway.com> writes:
>>> Robert Haas wrote:
>>>> - There is one dblink pach left over from last CommitFest.  Joe Conway
>>>> was going to review it the weekend of July 18th-19th, but that didn't
>>>> end up happening and so that patch is still waiting.  We might be able
>>>> to find someone else to review it, but I'm not sure whether that will
>>>> help unless there is a committer other than Joe with bandwidth to do
>>>> the final review and commit.
>>> I will get to it before the end of this commitfest, but I have to admit
>>> I'm not all that excited about this patch in the first place. I don't
>>> know that I agree with the need.
>> Well, you're the dblink expert.  If you think it should be rejected
>> I doubt many of us will argue with you.
>
> Yep.  CommitFest doesn't mean "commit it"; it means "decide whether to
> commit it".  Things being rejected or returned with feedback for
> further improvement is fine; we're just trying to avoid long periods
> with no response at all.

The issue is not so much technical as it is philosophical.

The patch basically forces all use of libpq by dblink to be asynchronous
(internally) so that a cancel can be sensed and passed down to the
remote side and everything cleaned up. Possibly the right thing to do,
but dblink already allows the use of async queries, and the current
synchronous method uses standard libpq calls. If all of this is really
necessary, doesn't every libpq client have the same issue? If so why
have the synchronous libpq functions at all?

So while I can vet the patch technically, and spend more time
understanding the use case, and maybe explaining it better, I think
other people should weigh in on the change as it is significant and
points to other potential issues.

Joe


Re: CommitFest 2009-09, two weeks on

From
Magnus Hagander
Date:
On Wed, Sep 30, 2009 at 18:34, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Robert Haas <robertmhaas@gmail.com> writes:
>> ... (and many of the more
>> significant remaining patches look like they are right up Tom's alley
>> anyway).
>
> FWIW, if left to my own devices I will eventually get to everything
> except the dblink, ecpg, and encoding/win32 patches.  I don't intend
> to touch any of those because there are other committers better
> qualified to review them.  (I don't actually think we have anybody
> except Michael who's really familiar with ecpg.)

I can certainly review the win32 encoding patch, but I was rather
hoping for some comments from others on if we're interested in a win32
only solution, or if we want something more generic. Should we just go
with the win32-only one for now?

-- Magnus HaganderMe: http://www.hagander.net/Work: http://www.redpill-linpro.com/


Re: CommitFest 2009-09, two weeks on

From
Alvaro Herrera
Date:
Magnus Hagander escribió:
> On Wed, Sep 30, 2009 at 18:34, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> > Robert Haas <robertmhaas@gmail.com> writes:
> >> ... (and many of the more
> >> significant remaining patches look like they are right up Tom's alley
> >> anyway).
> >
> > FWIW, if left to my own devices I will eventually get to everything
> > except the dblink, ecpg, and encoding/win32 patches.  I don't intend
> > to touch any of those because there are other committers better
> > qualified to review them.  (I don't actually think we have anybody
> > except Michael who's really familiar with ecpg.)
> 
> I can certainly review the win32 encoding patch, but I was rather
> hoping for some comments from others on if we're interested in a win32
> only solution, or if we want something more generic. Should we just go
> with the win32-only one for now?

Just a couple of days ago a question came on the spanish list because
someone was getting mixed UTF8 and Latin1 output in a log file.  This
was in Fedora IIRC, so maybe we do want something more general.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support


Re: CommitFest 2009-09, two weeks on

From
Tom Lane
Date:
Magnus Hagander <magnus@hagander.net> writes:
> I can certainly review the win32 encoding patch, but I was rather
> hoping for some comments from others on if we're interested in a win32
> only solution, or if we want something more generic. Should we just go
> with the win32-only one for now?

That was actually the only substantive comment I had about it.  I don't
see why it's a win32-only problem or why a win32-only solution is a good
approach.
        regards, tom lane


Re: CommitFest 2009-09, two weeks on

From
Magnus Hagander
Date:
On Wed, Sep 30, 2009 at 21:38, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Magnus Hagander <magnus@hagander.net> writes:
>> I can certainly review the win32 encoding patch, but I was rather
>> hoping for some comments from others on if we're interested in a win32
>> only solution, or if we want something more generic. Should we just go
>> with the win32-only one for now?
>
> That was actually the only substantive comment I had about it.  I don't
> see why it's a win32-only problem or why a win32-only solution is a good
> approach.

Yeah, that's my thought as well.

If we want a complete one, we should reject this patch and ask for one
that does that.

If we are fine with a win32 only one, I can review this one and get it in.

I'm leaning towards us wanting a general one, but I'm unsure how much
work that will take.


-- Magnus HaganderMe: http://www.hagander.net/Work: http://www.redpill-linpro.com/


Re: CommitFest 2009-09, two weeks on

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> The issue is not so much technical as it is philosophical.

> The patch basically forces all use of libpq by dblink to be asynchronous
> (internally) so that a cancel can be sensed and passed down to the
> remote side and everything cleaned up. Possibly the right thing to do,
> but dblink already allows the use of async queries, and the current
> synchronous method uses standard libpq calls. If all of this is really
> necessary, doesn't every libpq client have the same issue?

Well, only the ones that want to implement cancel and don't have access
to the app's own signal handling functions.  (Which suggests that a
possible answer is to allow dblink to hook into the SIGINT catcher,
but frankly hooks in that location scare me ...)

I would argue that it's not necessarily a good idea at all: one of the
typical uses for dblink is to fake "autonomous transactions", and in
that application I don't think you *want* a cancel to propagate to the
other session.  If we did put this behavior into all dblink operations,
we'd need a way to turn it off.

Since dblink_cancel_query is already available, people who do want
cancels to propagate have the ability to do that.  I'm inclined to
think that this is complexity we don't need.
        regards, tom lane


Re: CommitFest 2009-09, two weeks on

From
Itagaki Takahiro
Date:
Joe Conway <mail@joeconway.com> wrote:

> The patch basically forces all use of libpq by dblink to be asynchronous
> (internally) so that a cancel can be sensed and passed down to the
> remote side and everything cleaned up. Possibly the right thing to do,
> but dblink already allows the use of async queries, and the current
> synchronous method uses standard libpq calls.

The point is *memory leak* in dblink when a query is canceled or
become time-out. I think it is a bug, and my patch could fix it.

Regards,
---
ITAGAKI Takahiro
NTT Open Source Software Center




Re: CommitFest 2009-09, two weeks on

From
Itagaki Takahiro
Date:
Magnus Hagander <magnus@hagander.net> wrote:

> I can certainly review the win32 encoding patch, but I was rather
> hoping for some comments from others on if we're interested in a win32
> only solution, or if we want something more generic. Should we just go
> with the win32-only one for now?

Yes, because Windows is only platform that supports UTF-16 encoding natively.
I believe my patch is the best solution for Windows even if we have another
approach for other platforms.

Regards,
---
ITAGAKI Takahiro
NTT Open Source Software Center




Re: CommitFest 2009-09, two weeks on

From
Magnus Hagander
Date:
On Thu, Oct 1, 2009 at 04:11, Itagaki Takahiro
<itagaki.takahiro@oss.ntt.co.jp> wrote:
>
> Magnus Hagander <magnus@hagander.net> wrote:
>
>> I can certainly review the win32 encoding patch, but I was rather
>> hoping for some comments from others on if we're interested in a win32
>> only solution, or if we want something more generic. Should we just go
>> with the win32-only one for now?
>
> Yes, because Windows is only platform that supports UTF-16 encoding natively.
> I believe my patch is the best solution for Windows even if we have another
> approach for other platforms.

Actually, I think a better argument is that since Windows will *never*
accept UTF8 logging, and that's what most databases will be in, much
of this patch will be required anyway. So I should probably review and
get this part in while we think about other solutions *as well* for
other platforms.

-- Magnus HaganderMe: http://www.hagander.net/Work: http://www.redpill-linpro.com/


Re: CommitFest 2009-09, two weeks on

From
Michael Meskes
Date:
On Wed, Sep 30, 2009 at 12:34:23PM -0400, Tom Lane wrote:
> qualified to review them.  (I don't actually think we have anybody
> except Michael who's really familiar with ecpg.)

I'm afraid I'm simply not able to spend much time on this in the near future as
I'm simply too busy atm. I spend some time on these the last time, but wasn't
even able to see how Zoltan changed the points we mentioned back then, but I'm
sure he has.

As already noted the patches stack on each other. There doesn't seem to be a
technical reason for this at least not for some of those dependencies. With the
first patch changing the grammar file and thus taking quite some reviewing
effort this slows things down even more because one needs more effort to review
for instance the sqlda addition, although that one seems to be quite easy to
review.

All of this is written from the top of my head, so please bear with me if I
missed any changes in the patches.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
Go VfL Borussia! Go SF 49ers! Use Debian GNU/Linux! Use PostgreSQL!


Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Wed, Sep 30, 2009 at 12:34:23PM -0400, Tom Lane wrote:
>   
>> qualified to review them.  (I don't actually think we have anybody
>> except Michael who's really familiar with ecpg.)
>>     
>
> I'm afraid I'm simply not able to spend much time on this in the near future as
> I'm simply too busy atm. I spend some time on these the last time, but wasn't
> even able to see how Zoltan changed the points we mentioned back then, but I'm
> sure he has.
>
> As already noted the patches stack on each other. There doesn't seem to be a
> technical reason for this at least not for some of those dependencies. With the
> first patch changing the grammar file and thus taking quite some reviewing
> effort this slows things down even more because one needs more effort to review
> for instance the sqlda addition, although that one seems to be quite easy to
> review.
>   

You're not being fair with me. The dependencies are quite
technical.

First, Tom Lane suggested to unify core and ecpg FETCH
syntaxes so both will accept optional FROM/IN, which I did.
SQLDA support adds new FETCH forms (Informix-specific
ones) so naturally these patches clash. There's no simple way
to make they separately applicable. With the first version,
the same technical dependency were also there, because of
the (already explained) grammar problem, I got 2 shift/reduce
problems in the FETCH/MOVE stmts unless I de-factorized
FORWARD and BACKWARD out of fetch_direction.
The new FETCH forms with SQLDA touched the same areas
in ecpg.addon.

Second, DESCRIBE support and SQLDA support also overlap,
because SQLDA is a new descriptor form, and DESCRIBE has to
support both SQL descriptors and SQLDA. Well, I can split the
DESCRIBE patch in half, so it will be usable on SQL descriptors
but the other part would depend on both SQLDA and basic
DESCRIBE support. Technical dependency again.

What non-technical dependencies are you talking about?
Please explain, so I may fix them. Saying it vaguely doesn't help.

When I first posted the split patchset, you didn't tell me that
the split is no good. I tried everything help I could to explain
why I did what.

Also, the current reviewer (Dan Colish) haven't contacted me despite
I offered help privately. I can't review my own patches, that's clear.
But I can't do anything else to speed review up but to offer my help
and wait for the help/explanation request that didn't arrive.

Also, I have sent some independent very small patches, that don't
even need much review. One of them (the typo in pgc.l) was already
applied and I thank you Michael, but the memory leak fix for two
improperly freed numerics is still behind. Please, look at that patch,
it should be really obvious.

> All of this is written from the top of my head, so please bear with me if I
> missed any changes in the patches.
>
> Michael
>   

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: CommitFest 2009-09, two weeks on

From
Alvaro Herrera
Date:
Boszormenyi Zoltan escribió:

> First, Tom Lane suggested to unify core and ecpg FETCH
> syntaxes so both will accept optional FROM/IN, which I did.
> SQLDA support adds new FETCH forms (Informix-specific
> ones) so naturally these patches clash. There's no simple way
> to make they separately applicable. With the first version,
> the same technical dependency were also there, because of
> the (already explained) grammar problem, I got 2 shift/reduce
> problems in the FETCH/MOVE stmts unless I de-factorized
> FORWARD and BACKWARD out of fetch_direction.
> The new FETCH forms with SQLDA touched the same areas
> in ecpg.addon.

Probably the parts that touch the core grammar can be reviewed and
applied separately.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.


Re: CommitFest 2009-09, two weeks on

From
Michael Meskes
Date:
On Thu, Oct 01, 2009 at 03:47:07PM +0200, Boszormenyi Zoltan wrote:
> You're not being fair with me. The dependencies are quite
> technical.

I'm sorry that you interpreted my email this way, it wasn't at all meant to
offend you.

> First, Tom Lane suggested to unify core and ecpg FETCH
> syntaxes so both will accept optional FROM/IN, which I did.
> SQLDA support adds new FETCH forms (Informix-specific

This is actually one I was talking about. Adding SQLDA *only* seems like an
easy one, as soon as it also hits the parser it becomes more complicated. This
is not to say that it is not doable, but it wasn't for me with my time
constraints. I was just explaining why I didn't delve into these any more so
far.

> When I first posted the split patchset, you didn't tell me that
> the split is no good. I tried everything help I could to explain
> why I did what.

Well actually I did, but that's not the problem here. I have no idea why you
are ranting like this just because of me excusing myself for a lack of time.

> Also, the current reviewer (Dan Colish) haven't contacted me despite
> I offered help privately. I can't review my own patches, that's clear.
> But I can't do anything else to speed review up but to offer my help
> and wait for the help/explanation request that didn't arrive.

Okay, so it's all my fault. Do you feel better now? 

> Also, I have sent some independent very small patches, that don't
> even need much review. One of them (the typo in pgc.l) was already
> applied and I thank you Michael, but the memory leak fix for two
> improperly freed numerics is still behind. Please, look at that patch,
> it should be really obvious.

My last commit was one of your patches, obviously I didn't do anything on ecpg
since. I'm not sure what you are trying to tell me, you might want to explain
the last two sentences. But keep in mind you are *not* the one to decide how I
spend my spare time.

Michael

-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
Go VfL Borussia! Go SF 49ers! Use Debian GNU/Linux! Use PostgreSQL!


Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Thu, Oct 01, 2009 at 03:47:07PM +0200, Boszormenyi Zoltan wrote:
>   
>> You're not being fair with me. The dependencies are quite
>> technical.
>>     
>
> I'm sorry that you interpreted my email this way, it wasn't at all meant to
> offend you.
>   

Please, accept my apologies, I only tried to express my
frustration, this is not a good situation for either of us.
You were busy with your job and other occupations.
We have a serious project going on that depend on
ECPG being more compatible to Informix.

>> First, Tom Lane suggested to unify core and ecpg FETCH
>> syntaxes so both will accept optional FROM/IN, which I did.
>> SQLDA support adds new FETCH forms (Informix-specific
>>     
>
> This is actually one I was talking about. Adding SQLDA *only* seems like an
> easy one, as soon as it also hits the parser it becomes more complicated. This
> is not to say that it is not doable, but it wasn't for me with my time
> constraints. I was just explaining why I didn't delve into these any more so
> far.
>   

This is now clear, I will separate that part out and post it.
But this means that the same core grammar parts will be touched
twice because two basic things are done there:
- optional FROM/IN in core grammar, ECPG grammar updated
- "name" -> "cursor_name" transition in cursor-related statements in the core grammar and the dynamic cursorname patch
So, technically dependant patches again, but maybe easier on the reviewer.
Would this be accepted this way? Or the two modification washed into one?

>> When I first posted the split patchset, you didn't tell me that
>> the split is no good. I tried everything help I could to explain
>> why I did what.
>>     
>
> Well actually I did, but that's not the problem here. I have no idea why you
> are ranting like this just because of me excusing myself for a lack of time.
>   

I am very sorry, under stress sometimes I get like a steam
engine overloaded. Not a good behaviour at 37, I know.
I am very sorry.

>> Also, the current reviewer (Dan Colish) haven't contacted me despite
>> I offered help privately. I can't review my own patches, that's clear.
>> But I can't do anything else to speed review up but to offer my help
>> and wait for the help/explanation request that didn't arrive.
>>     
>
> Okay, so it's all my fault. Do you feel better now? 
>   

It's not your fault at all, it's a difficult situation and I had to
express it somehow. My tone was not proper.

BTW, thanks for adding my small collected knowledge
about the ECPG grammar as official documentation.

>> Also, I have sent some independent very small patches, that don't
>> even need much review. One of them (the typo in pgc.l) was already
>> applied and I thank you Michael, but the memory leak fix for two
>> improperly freed numerics is still behind. Please, look at that patch,
>> it should be really obvious.
>>     
>
> My last commit was one of your patches,

Yes, the pgc.l one-liner. Thanks again for committing that.

>  obviously I didn't do anything on ecpg
> since. I'm not sure what you are trying to tell me, you might want to explain
> the last two sentences.

I thought you forgot that patch, the "please, look at that patch"
was an (I thought) polite request, it's really two one-liners.

>  But keep in mind you are *not* the one to decide how I
> spend my spare time.
>   

Obviously. Please, accept my apologies.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: CommitFest 2009-09, two weeks on

From
Michael Meskes
Date:
On Thu, Oct 01, 2009 at 07:21:54PM +0200, Boszormenyi Zoltan wrote:
> Please, accept my apologies, I only tried to express my
> frustration, this is not a good situation for either of us.

Apologies accepted, email is a difficult means of communication anyway. It
leads to misunderstanding IMO.

> You were busy with your job and other occupations.
> We have a serious project going on that depend on
> ECPG being more compatible to Informix.

Please keep in mind that the needs of your business project cannot and will not
influence the way PostgreSQL as on OSS project will work.

> Would this be accepted this way? Or the two modification washed into one?

It is accepted either way. I was just pointing out that it might be easier to
review/commit at least parts of your patches if they can be applied seperately.

> I thought you forgot that patch, the "please, look at that patch"
> was an (I thought) polite request, it's really two one-liners.

Well, this is true as the patch was buried in the long thread containing all
the other ones. And yes, now that you brought it into my memory again, I
already committed it. Sorry for missing it.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
Go VfL Borussia! Go SF 49ers! Use Debian GNU/Linux! Use PostgreSQL!


Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Thu, Oct 01, 2009 at 07:21:54PM +0200, Boszormenyi Zoltan wrote:
>   
>> Please, accept my apologies, I only tried to express my
>> frustration, this is not a good situation for either of us.
>>     
>
> Apologies accepted, email is a difficult means of communication anyway. It
> leads to misunderstanding IMO.
>
>   
>> You were busy with your job and other occupations.
>> We have a serious project going on that depend on
>> ECPG being more compatible to Informix.
>>     
>
> Please keep in mind that the needs of your business project cannot and will not
> influence the way PostgreSQL as on OSS project will work.
>   

Yes, but technical problems and solutions do. ECPG claims
to be ESQL/C compatible, but at places it's only half compatible.
For our project to succeed, we need more compatibility in ECPG.
It's easier to solve these problems in ECPG than to code around it
in literally thousands of little programs.

BTW, a thought about the comment in ecpg.header about adjust_informix():
       /* Informix accepts DECLARE with variables that are out of scope
when OPEN is called.        * for instance you can declare variables in a function, and
then subsequently use them        * {        *      declare_vars();        *      exec sql ... which uses vars declared
inthe above function        *        * This breaks standard and leads to some very dangerous
 
programming.

This comment is misleading and reflects quite a narrow POV.
Not only OPEN and DECLARE may be out of scope,
but FETCH and CLOSE as well. The reason why ESQL/C
allows this construct is that this ultimately allows using
embedded SQL in event-driven code in a straightforward way.
For this purpose, native ECPG code is not usable currently,
or you need programming tricks, like tracking whether the
cursor is open and protecting DECLARE and OPEN under
some conditional branch to avoid double open, etc. A straight
DECLARE, OPEN, FETCH(s) and CLOSE series in
the same function is only good for batch programming.

>> Would this be accepted this way? Or the two modification washed into one?
>>     
>
> It is accepted either way. I was just pointing out that it might be easier to
> review/commit at least parts of your patches if they can be applied seperately.
>   

Okay, I will split the remaining patches into more little pieces
that can reviewed more easily. Some patches will still build
on earlier ones in the series, that's unavoidable.

>> I thought you forgot that patch, the "please, look at that patch"
>> was an (I thought) polite request, it's really two one-liners.
>>     
>
> Well, this is true as the patch was buried in the long thread containing all
> the other ones. And yes, now that you brought it into my memory again, I
> already committed it. Sorry for missing it.
>   

Thank you very much for committing it.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: CommitFest 2009-09, two weeks on

From
Michael Meskes
Date:
On Thu, Oct 01, 2009 at 09:05:55PM +0200, Boszormenyi Zoltan wrote:
> Yes, but technical problems and solutions do. ECPG claims
> to be ESQL/C compatible, but at places it's only half compatible.

Where does it claim to be fully compatible?

> This comment is misleading and reflects quite a narrow POV.
> Not only OPEN and DECLARE may be out of scope,
> but FETCH and CLOSE as well. The reason why ESQL/C
> allows this construct is that this ultimately allows using
> embedded SQL in event-driven code in a straightforward way.
> For this purpose, native ECPG code is not usable currently,
> or you need programming tricks, like tracking whether the
> cursor is open and protecting DECLARE and OPEN under
> some conditional branch to avoid double open, etc. A straight
> DECLARE, OPEN, FETCH(s) and CLOSE series in
> the same function is only good for batch programming.

Examples?

Michael

-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
Go VfL Borussia! Go SF 49ers! Use Debian GNU/Linux! Use PostgreSQL!


Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Thu, Oct 01, 2009 at 09:05:55PM +0200, Boszormenyi Zoltan wrote:
>
>> Yes, but technical problems and solutions do. ECPG claims
>> to be ESQL/C compatible, but at places it's only half compatible.
>>
>
> Where does it claim to be fully compatible?
>

I didn't say it claims to be fully compatible, but it's
a "hint" that "ecpg -C INFORMIX[_SE]" exists. :-)

>> This comment is misleading and reflects quite a narrow POV.
>> Not only OPEN and DECLARE may be out of scope,
>> but FETCH and CLOSE as well. The reason why ESQL/C
>> allows this construct is that this ultimately allows using
>> embedded SQL in event-driven code in a straightforward way.
>> For this purpose, native ECPG code is not usable currently,
>> or you need programming tricks, like tracking whether the
>> cursor is open and protecting DECLARE and OPEN under
>> some conditional branch to avoid double open, etc. A straight
>> DECLARE, OPEN, FETCH(s) and CLOSE series in
>> the same function is only good for batch programming.
>>
>
> Examples?
>

I took my outofscope.pgc example from our "out of
scope" patch and shortened it. Compare the ecpg-native and
compat outputs and the esql output of the same file. The ecpg
outputs are generated with 8.4.1 plus out patches added, the
native output differs only from 8.3.7's ecpg in the amount of
whitespaces emitted between literals. The get_record1()
function can be called from a button-handler, e.g. when pressing
PgDn, or similar... No tricks needed, straightforward code.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

exec sql begin declare section;
exec sql include struct.h;
exec sql end declare section;

exec sql whenever sqlerror stop;

static void
get_var1(MYTYPE **myvar0, MYNULLTYPE **mynullvar0)
{
    exec sql begin declare section;
    MYTYPE        *myvar = malloc(sizeof(MYTYPE));
    MYNULLTYPE    *mynullvar = malloc(sizeof(MYNULLTYPE));
    exec sql end declare section;

    /* Test DECLARE ... SELECT ... INTO with pointers */

    exec sql declare mycur cursor for select * INTO :myvar :mynullvar from a1;

    if (sqlca.sqlcode != 0)
        exit(1);

    *myvar0 = myvar;
    *mynullvar0 = mynullvar;
}

static void
open_cur1(void)
{
    exec sql open mycur;

    if (sqlca.sqlcode != 0)
        exit(1);
}

static void
get_record1(void)
{
    exec sql fetch mycur;

    if (sqlca.sqlcode != 0 && sqlca.sqlcode != SQLNOTFOUND)
        exit(1);
}

static void
close_cur1(void)
{
    exec sql close mycur;

    if (sqlca.sqlcode != 0)
        exit(1);
}

int
main (void)
{
    MYTYPE        *myvar;
    MYNULLTYPE    *mynullvar;

    char msg[128];

    ECPGdebug(1, stderr);

    exec sql connect to "test";


    exec sql create table a1(id serial primary key, t text, d1 numeric, d2 float8, c character(10));

    exec sql insert into a1(id, t, d1, d2, c) values (default, 'a', 1.0, 2, 'a');
    exec sql insert into a1(id, t, d1, d2, c) values (default, null, null, null, null);
    exec sql insert into a1(id, t, d1, d2, c) values (default, '"a"', -1.0, 'nan'::float8, 'a');
    exec sql insert into a1(id, t, d1, d2, c) values (default, 'b', 2.0, 3, 'b');

    exec sql commit;

    /* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */

    get_var1(&myvar, &mynullvar);
    open_cur1();

    while (1)
    {
        memset(myvar, 0, sizeof(MYTYPE));
        get_record1();
        if (sqlca.sqlcode == SQLNOTFOUND)
            break;
        printf("id=%d%s t='%s'%s d1=%lf%s d2=%lf%s c = '%s'%s\n",
            myvar->id, mynullvar->id ? " (NULL)" : "",
            myvar->t, mynullvar->t ? " (NULL)" : "",
            myvar->d1, mynullvar->d1 ? " (NULL)" : "",
            myvar->d2, mynullvar->d2 ? " (NULL)" : "",
            myvar->c, mynullvar->c ? " (NULL)" : "");
    }

    close_cur1();

    exec sql drop table a1;

    exec sql commit;

    exec sql disconnect all;

    return (0);
}

struct mytype {
    int    id;
    char    t[64];
    double    d1; /* dec_t */
    double    d2;
    char    c[30];
};
typedef struct mytype MYTYPE;

struct mynulltype {
    int    id;
    int    t;
    int    d1;
    int    d2;
    int    c;
};
typedef struct mynulltype MYNULLTYPE;
/* Processed by ecpg (4.5.0) */
/* These include files are added by the preprocessor */
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
/* End of automatic include section */

#line 1 "outofscope.ec"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

/* exec sql begin declare section */

#line 1 "./struct.h"




         /* dec_t */



   typedef struct mytype  MYTYPE ;

#line 9 "./struct.h"









   typedef struct mynulltype  MYNULLTYPE ;

#line 18 "./struct.h"


#line 7 "outofscope.ec"

struct mytype {
#line 3 "./struct.h"
 int id ;

#line 4 "./struct.h"
 char t [ 64 ] ;

#line 5 "./struct.h"
 double d1 ;

#line 6 "./struct.h"
 double d2 ;

#line 7 "./struct.h"
 char c [ 30 ] ;
 } ; struct mynulltype {
#line 12 "./struct.h"
 int id ;

#line 13 "./struct.h"
 int t ;

#line 14 "./struct.h"
 int d1 ;

#line 15 "./struct.h"
 int d2 ;

#line 16 "./struct.h"
 int c ;
 } ;/* exec sql end declare section */
#line 8 "outofscope.ec"


/* exec sql whenever sqlerror  stop ; */
#line 10 "outofscope.ec"


static void
get_var1(MYTYPE **myvar0, MYNULLTYPE **mynullvar0)
{
    /* exec sql begin declare section */



#line 16 "outofscope.ec"
 MYTYPE * myvar = malloc ( sizeof ( MYTYPE ) ) ;

#line 17 "outofscope.ec"
 MYNULLTYPE * mynullvar = malloc ( sizeof ( MYNULLTYPE ) ) ;
/* exec sql end declare section */
#line 18 "outofscope.ec"


    /* Test DECLARE ... SELECT ... INTO with pointers */

    /* declare mycur cursor for select * from a1 */
#line 22 "outofscope.ec"


    if (sqlca.sqlcode != 0)
        exit(1);

    *myvar0 = myvar;
    *mynullvar0 = mynullvar;
}

static void
open_cur1(void)
{
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare mycur cursor for select * from a1", ECPGt_EOIT,
ECPGt_EORT);
#line 34 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 34 "outofscope.ec"


    if (sqlca.sqlcode != 0)
        exit(1);
}

static void
get_record1(void)
{
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch mycur", ECPGt_EOIT, ECPGt_EORT);
#line 43 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 43 "outofscope.ec"


    if (sqlca.sqlcode != 0 && sqlca.sqlcode != SQLNOTFOUND)
        exit(1);
}

static void
close_cur1(void)
{
    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close mycur", ECPGt_EOIT, ECPGt_EORT);
#line 52 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 52 "outofscope.ec"


    if (sqlca.sqlcode != 0)
        exit(1);
}

int
main (void)
{
    MYTYPE        *myvar;
    MYNULLTYPE    *mynullvar;

    char msg[128];

    ECPGdebug(1, stderr);

    { ECPGconnect(__LINE__, 0, "test" , NULL, NULL , NULL, 0);
#line 68 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 68 "outofscope.ec"



    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table a1 ( id serial primary key , t text , d1 numeric ,
d2float8 , c character ( 10 ) )", ECPGt_EOIT, ECPGt_EORT); 
#line 71 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 71 "outofscope.ec"


    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'a' ,
1.0, 2 , 'a' )", ECPGt_EOIT, ECPGt_EORT); 
#line 73 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 73 "outofscope.ec"

    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , null ,
null, null , null )", ECPGt_EOIT, ECPGt_EORT); 
#line 74 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 74 "outofscope.ec"

    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default ,
'\"a\"', - 1.0 , 'nan' :: float8 , 'a' )", ECPGt_EOIT, ECPGt_EORT); 
#line 75 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 75 "outofscope.ec"

    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' ,
2.0, 3 , 'b' )", ECPGt_EOIT, ECPGt_EORT); 
#line 76 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 76 "outofscope.ec"


    { ECPGtrans(__LINE__, NULL, "commit");
#line 78 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 78 "outofscope.ec"


    /* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */

    get_var1(&myvar, &mynullvar);
    open_cur1();

    while (1)
    {
        memset(myvar, 0, sizeof(MYTYPE));
        get_record1();
        if (sqlca.sqlcode == SQLNOTFOUND)
            break;
        printf("id=%d%s t='%s'%s d1=%lf%s d2=%lf%s c = '%s'%s\n",
            myvar->id, mynullvar->id ? " (NULL)" : "",
            myvar->t, mynullvar->t ? " (NULL)" : "",
            myvar->d1, mynullvar->d1 ? " (NULL)" : "",
            myvar->d2, mynullvar->d2 ? " (NULL)" : "",
            myvar->c, mynullvar->c ? " (NULL)" : "");
    }

    close_cur1();

    { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table a1", ECPGt_EOIT, ECPGt_EORT);
#line 101 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 101 "outofscope.ec"


    { ECPGtrans(__LINE__, NULL, "commit");
#line 103 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 103 "outofscope.ec"


    { ECPGdisconnect(__LINE__, "ALL");
#line 105 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 105 "outofscope.ec"


    return (0);
}
/* Processed by ecpg (4.5.0) */
/* These include files are added by the preprocessor */
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
/* Needed for informix compatibility */
#include <ecpg_informix.h>
/* End of automatic include section */

#line 1 "outofscope.ec"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

/* exec sql begin declare section */

#line 1 "./struct.h"




         /* dec_t */



   typedef struct mytype  MYTYPE ;

#line 9 "./struct.h"









   typedef struct mynulltype  MYNULLTYPE ;

#line 18 "./struct.h"


#line 7 "outofscope.ec"

struct mytype {
#line 3 "./struct.h"
 int id ;

#line 4 "./struct.h"
 char t [ 64 ] ;

#line 5 "./struct.h"
 double d1 ;

#line 6 "./struct.h"
 double d2 ;

#line 7 "./struct.h"
 char c [ 30 ] ;
 } ; struct mynulltype {
#line 12 "./struct.h"
 int id ;

#line 13 "./struct.h"
 int t ;

#line 14 "./struct.h"
 int d1 ;

#line 15 "./struct.h"
 int d2 ;

#line 16 "./struct.h"
 int c ;
 } ;/* exec sql end declare section */
#line 8 "outofscope.ec"


/* exec sql whenever sqlerror  stop ; */
#line 10 "outofscope.ec"


static void
get_var1(MYTYPE **myvar0, MYNULLTYPE **mynullvar0)
{
    /* exec sql begin declare section */



#line 16 "outofscope.ec"
 MYTYPE * myvar = malloc ( sizeof ( MYTYPE ) ) ;

#line 17 "outofscope.ec"
 MYNULLTYPE * mynullvar = malloc ( sizeof ( MYNULLTYPE ) ) ;
/* exec sql end declare section */
#line 18 "outofscope.ec"


    /* Test DECLARE ... SELECT ... INTO with pointers */

    ECPG_informix_set_var( 0, ( myvar ), __LINE__);\
 ECPG_informix_set_var( 1, ( mynullvar ), __LINE__);\
 ECPG_informix_reset_sqlca(); /* declare mycur cursor for select * from a1 */
#line 22 "outofscope.ec"


    if (sqlca.sqlcode != 0)
        exit(1);

    *myvar0 = myvar;
    *mynullvar0 = mynullvar;
}

static void
open_cur1(void)
{
    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare mycur cursor for select * from a1", ECPGt_EOIT,
    ECPGt_int,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).id),(long)1,(long)1,sizeof(int),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).id),(long)1,(long)1,sizeof(int),
    ECPGt_char,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).t),(long)64,(long)1,(64)*sizeof(char),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).t),(long)1,(long)1,sizeof(int),
    ECPGt_double,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).d1),(long)1,(long)1,sizeof(double),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).d1),(long)1,(long)1,sizeof(int),
    ECPGt_double,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).d2),(long)1,(long)1,sizeof(double),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).d2),(long)1,(long)1,sizeof(int),
    ECPGt_char,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).c),(long)30,(long)1,(30)*sizeof(char),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).c),(long)1,(long)1,sizeof(int), ECPGt_EORT);
#line 34 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 34 "outofscope.ec"


    if (sqlca.sqlcode != 0)
        exit(1);
}

static void
get_record1(void)
{
    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch mycur", ECPGt_EOIT,
    ECPGt_int,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).id),(long)1,(long)1,sizeof(int),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).id),(long)1,(long)1,sizeof(int),
    ECPGt_char,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).t),(long)64,(long)1,(64)*sizeof(char),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).t),(long)1,(long)1,sizeof(int),
    ECPGt_double,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).d1),(long)1,(long)1,sizeof(double),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).d1),(long)1,(long)1,sizeof(int),
    ECPGt_double,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).d2),(long)1,(long)1,sizeof(double),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).d2),(long)1,(long)1,sizeof(int),
    ECPGt_char,&((*( MYTYPE  *)(ECPG_informix_get_var( 0))).c),(long)30,(long)1,(30)*sizeof(char),
    ECPGt_int,&((*( MYNULLTYPE  *)(ECPG_informix_get_var( 1))).c),(long)1,(long)1,sizeof(int), ECPGt_EORT);
#line 43 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 43 "outofscope.ec"


    if (sqlca.sqlcode != 0 && sqlca.sqlcode != SQLNOTFOUND)
        exit(1);
}

static void
close_cur1(void)
{
    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "close mycur", ECPGt_EOIT, ECPGt_EORT);
#line 52 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 52 "outofscope.ec"


    if (sqlca.sqlcode != 0)
        exit(1);
}

int
main (void)
{
    MYTYPE        *myvar;
    MYNULLTYPE    *mynullvar;

    char msg[128];

    ECPGdebug(1, stderr);

    { ECPGconnect(__LINE__, 1, "test" , NULL, NULL , NULL, 0);
#line 68 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 68 "outofscope.ec"



    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "create table a1 ( id serial primary key , t text , d1 numeric ,
d2float8 , c character ( 10 ) )", ECPGt_EOIT, ECPGt_EORT); 
#line 71 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 71 "outofscope.ec"


    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'a' ,
1.0, 2 , 'a' )", ECPGt_EOIT, ECPGt_EORT); 
#line 73 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 73 "outofscope.ec"

    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , null ,
null, null , null )", ECPGt_EOIT, ECPGt_EORT); 
#line 74 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 74 "outofscope.ec"

    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default ,
'\"a\"', - 1.0 , 'nan' :: float8 , 'a' )", ECPGt_EOIT, ECPGt_EORT); 
#line 75 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 75 "outofscope.ec"

    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' ,
2.0, 3 , 'b' )", ECPGt_EOIT, ECPGt_EORT); 
#line 76 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 76 "outofscope.ec"


    { ECPGtrans(__LINE__, NULL, "commit");
#line 78 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 78 "outofscope.ec"


    /* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */

    get_var1(&myvar, &mynullvar);
    open_cur1();

    while (1)
    {
        memset(myvar, 0, sizeof(MYTYPE));
        get_record1();
        if (sqlca.sqlcode == SQLNOTFOUND)
            break;
        printf("id=%d%s t='%s'%s d1=%lf%s d2=%lf%s c = '%s'%s\n",
            myvar->id, mynullvar->id ? " (NULL)" : "",
            myvar->t, mynullvar->t ? " (NULL)" : "",
            myvar->d1, mynullvar->d1 ? " (NULL)" : "",
            myvar->d2, mynullvar->d2 ? " (NULL)" : "",
            myvar->c, mynullvar->c ? " (NULL)" : "");
    }

    close_cur1();

    { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "drop table a1", ECPGt_EOIT, ECPGt_EORT);
#line 101 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 101 "outofscope.ec"


    { ECPGtrans(__LINE__, NULL, "commit");
#line 103 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 103 "outofscope.ec"


    { ECPGdisconnect(__LINE__, "ALL");
#line 105 "outofscope.ec"

if (sqlca.sqlcode < 0) exit (1);}
#line 105 "outofscope.ec"


    return (0);
}
#include <stdlib.h>
#include <sqlhdr.h>
#include <sqliapi.h>
static const char _Cn1[] = "mycur";
#line 1 "outofscope.ec"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

/*
 * exec sql begin declare section;
 */
#line 6 "outofscope.ec"
/*
 * exec sql include struct.h;
 */
#line 7 "outofscope.ec"

#line 7 "outofscope.ec"
#line 127 "struct.h"
#line 1 "outofscope.ec"
struct mytype
  {
    int id;
      char t[64];
    double d1;
    double d2;
      char c[30];
  } ;
typedef struct mytype MYTYPE;
struct mynulltype
  {
    int id;
    int t;
    int d1;
    int d2;
    int c;
  } ;
typedef struct mynulltype MYNULLTYPE;
/*
 * exec sql end declare section;
 */
#line 8 "outofscope.ec"

#line 9 "outofscope.ec"

/*
 * exec sql whenever sqlerror stop;
 */
#line 10 "outofscope.ec"

static void
get_var1(MYTYPE **myvar0, MYNULLTYPE **mynullvar0)
{
/*
 *     exec sql begin declare section;
 */
#line 15 "outofscope.ec"
#line 16 "outofscope.ec"
MYTYPE *myvar = malloc(sizeof(MYTYPE));
MYNULLTYPE *mynullvar = malloc(sizeof(MYNULLTYPE));
/*
 *     exec sql end declare section;
 */
#line 18 "outofscope.ec"


    /* Test DECLARE ... SELECT ... INTO with pointers */

/*
 *     exec sql declare mycur cursor for select * INTO :myvar :mynullvar from a1;
 */
#line 22 "outofscope.ec"
  {
#line 22 "outofscope.ec"
  static const char *sqlcmdtxt[] =
#line 22 "outofscope.ec"
    {
#line 22 "outofscope.ec"
    "select * from a1",
    0
    };
#line 22 "outofscope.ec"
  static ifx_sqlvar_t _sqobind[] =
    {
      { 102, sizeof((myvar)->id), 0, 0, 0, 0, 102, sizeof((mynullvar)->id), 0, 0, 0, 0, 0, 0, 0, 0 },
      { 100, 64, 0, 0, 0, 0, 102, sizeof((mynullvar)->t), 0, 0, 0, 0, 0, 0, 0, 0 },
      { 105, sizeof((myvar)->d1), 0, 0, 0, 0, 102, sizeof((mynullvar)->d1), 0, 0, 0, 0, 0, 0, 0, 0 },
      { 105, sizeof((myvar)->d2), 0, 0, 0, 0, 102, sizeof((mynullvar)->d2), 0, 0, 0, 0, 0, 0, 0, 0 },
      { 100, 30, 0, 0, 0, 0, 102, sizeof((mynullvar)->c), 0, 0, 0, 0, 0, 0, 0, 0 },
#line 22 "outofscope.ec"
    };
  static ifx_sqlda_t _SD0 = { 5, _sqobind, {0}, 5, 0 };
#line 22 "outofscope.ec"
  _sqobind[0].sqldata = (char *) &(myvar)->id;
_sqobind[0].sqlidata = (char *) &(mynullvar)->id;
#line 22 "outofscope.ec"
  _sqobind[1].sqldata = (myvar)->t;
_sqobind[1].sqlidata = (char *) &(mynullvar)->t;
#line 22 "outofscope.ec"
  _sqobind[2].sqldata = (char *) &(myvar)->d1;
_sqobind[2].sqlidata = (char *) &(mynullvar)->d1;
#line 22 "outofscope.ec"
  _sqobind[3].sqldata = (char *) &(myvar)->d2;
_sqobind[3].sqlidata = (char *) &(mynullvar)->d2;
#line 22 "outofscope.ec"
  _sqobind[4].sqldata = (myvar)->c;
_sqobind[4].sqlidata = (char *) &(mynullvar)->c;
#line 22 "outofscope.ec"
sqli_curs_decl_stat(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 512), _Cn1, sqlcmdtxt, (ifx_sqlda_t *)0,
&_SD0,0, (ifx_literal_t *)0, (ifx_namelist_t *)0, 2, 0, 0); 
#line 22 "outofscope.ec"
  { if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 22 "outofscope.ec"
}

    if (sqlca.sqlcode != 0)
        exit(1);

    *myvar0 = myvar;
    *mynullvar0 = mynullvar;
}

static void
open_cur1(void)
{
/*
 *     exec sql open mycur;
 */
#line 34 "outofscope.ec"
{
#line 34 "outofscope.ec"
sqli_curs_open(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 768), (ifx_sqlda_t *)0, (char *)0, (struct value
*)0,0, 0); 
#line 34 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 34 "outofscope.ec"
}

    if (sqlca.sqlcode != 0)
        exit(1);
}

static void
get_record1(void)
{
/*
 *     exec sql fetch mycur;
 */
#line 43 "outofscope.ec"
{
#line 43 "outofscope.ec"
static _FetchSpec _FS0 = { 0, 1, 0 };
sqli_curs_fetch(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 768), (ifx_sqlda_t *)0, (ifx_sqlda_t *)0, (char
*)0,&_FS0); 
#line 43 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 43 "outofscope.ec"
}

    if (sqlca.sqlcode != 0 && sqlca.sqlcode != SQLNOTFOUND)
        exit(1);
}

static void
close_cur1(void)
{
/*
 *     exec sql close mycur;
 */
#line 52 "outofscope.ec"
{
#line 52 "outofscope.ec"
sqli_curs_close(ESQLINTVERSION, sqli_curs_locate(ESQLINTVERSION, _Cn1, 768));
#line 52 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 52 "outofscope.ec"
}

    if (sqlca.sqlcode != 0)
        exit(1);
}

int
main (void)
{
    MYTYPE        *myvar;
    MYNULLTYPE    *mynullvar;

    char msg[128];

    ECPGdebug(1, stderr);

/*
 *     exec sql connect to "test";
 */
#line 68 "outofscope.ec"
{
#line 68 "outofscope.ec"
sqli_connect_open(ESQLINTVERSION, 0, "test", (char *)0, (ifx_conn_t *)0, 0);
#line 68 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 68 "outofscope.ec"
}


/*
 *     exec sql create table a1(id serial primary key, t text, d1 numeric, d2 float8, c character(10));
 */
#line 71 "outofscope.ec"
{
#line 71 "outofscope.ec"
static const char *sqlcmdtxt[] =
#line 71 "outofscope.ec"
{
#line 71 "outofscope.ec"
"create table a1 ( id serial primary key , t text , d1 numeric , d2 float8 , c character ( 10 ) )",
0
};
#line 71 "outofscope.ec"
static ifx_statement_t _SQ0 = {0};
#line 71 "outofscope.ec"
sqli_stmt(ESQLINTVERSION, &_SQ0, sqlcmdtxt, 0, (ifx_sqlvar_t *)0, (struct value *)0, (ifx_literal_t *)0,
(ifx_namelist_t*)0, (ifx_cursor_t *)0, -1, 0, 0); 
#line 71 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 71 "outofscope.ec"
}

/*
 *     exec sql insert into a1(id, t, d1, d2, c) values (default, 'a', 1.0, 2, 'a');
 */
#line 73 "outofscope.ec"
{
#line 73 "outofscope.ec"
static const char *sqlcmdtxt[] =
#line 73 "outofscope.ec"
{
#line 73 "outofscope.ec"
"insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'a' , 1.0 , 2 , 'a' )",
0
};
#line 73 "outofscope.ec"
static ifx_statement_t _SQ0 = {0};
#line 73 "outofscope.ec"
sqli_stmt(ESQLINTVERSION, &_SQ0, sqlcmdtxt, 0, (ifx_sqlvar_t *)0, (struct value *)0, (ifx_literal_t *)0,
(ifx_namelist_t*)0, (ifx_cursor_t *)0, 6, 0, 0); 
#line 73 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 73 "outofscope.ec"
}
/*
 *     exec sql insert into a1(id, t, d1, d2, c) values (default, null, null, null, null);
 */
#line 74 "outofscope.ec"
{
#line 74 "outofscope.ec"
static const char *sqlcmdtxt[] =
#line 74 "outofscope.ec"
{
#line 74 "outofscope.ec"
"insert into a1 ( id , t , d1 , d2 , c ) values ( default , null , null , null , null )",
0
};
#line 74 "outofscope.ec"
static ifx_statement_t _SQ0 = {0};
#line 74 "outofscope.ec"
sqli_stmt(ESQLINTVERSION, &_SQ0, sqlcmdtxt, 0, (ifx_sqlvar_t *)0, (struct value *)0, (ifx_literal_t *)0,
(ifx_namelist_t*)0, (ifx_cursor_t *)0, 6, 0, 0); 
#line 74 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 74 "outofscope.ec"
}
/*
 *     exec sql insert into a1(id, t, d1, d2, c) values (default, '"a"', -1.0, 'nan'::float8, 'a');
 */
#line 75 "outofscope.ec"
{
#line 75 "outofscope.ec"
static const char *sqlcmdtxt[] =
#line 75 "outofscope.ec"
{
#line 75 "outofscope.ec"
"insert into a1 ( id , t , d1 , d2 , c ) values ( default , '"a"' , - 1.0 , 'nan' :: float8 , 'a' )",
0
};
#line 75 "outofscope.ec"
static ifx_statement_t _SQ0 = {0};
#line 75 "outofscope.ec"
sqli_stmt(ESQLINTVERSION, &_SQ0, sqlcmdtxt, 0, (ifx_sqlvar_t *)0, (struct value *)0, (ifx_literal_t *)0,
(ifx_namelist_t*)0, (ifx_cursor_t *)0, 6, 0, 0); 
#line 75 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 75 "outofscope.ec"
}
/*
 *     exec sql insert into a1(id, t, d1, d2, c) values (default, 'b', 2.0, 3, 'b');
 */
#line 76 "outofscope.ec"
{
#line 76 "outofscope.ec"
static const char *sqlcmdtxt[] =
#line 76 "outofscope.ec"
{
#line 76 "outofscope.ec"
"insert into a1 ( id , t , d1 , d2 , c ) values ( default , 'b' , 2.0 , 3 , 'b' )",
0
};
#line 76 "outofscope.ec"
static ifx_statement_t _SQ0 = {0};
#line 76 "outofscope.ec"
sqli_stmt(ESQLINTVERSION, &_SQ0, sqlcmdtxt, 0, (ifx_sqlvar_t *)0, (struct value *)0, (ifx_literal_t *)0,
(ifx_namelist_t*)0, (ifx_cursor_t *)0, 6, 0, 0); 
#line 76 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 76 "outofscope.ec"
}

/*
 *     exec sql commit;
 */
#line 78 "outofscope.ec"
{
#line 78 "outofscope.ec"
sqli_trans_commit();
#line 78 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 78 "outofscope.ec"
}

    /* Test out-of-scope DECLARE/OPEN/FETCH/CLOSE */

    get_var1(&myvar, &mynullvar);
    open_cur1();

    while (1)
    {
        memset(myvar, 0, sizeof(MYTYPE));
        get_record1();
        if (sqlca.sqlcode == SQLNOTFOUND)
            break;
        printf("id=%d%s t='%s'%s d1=%lf%s d2=%lf%s c = '%s'%s\n",
            myvar->id, mynullvar->id ? " (NULL)" : "",
            myvar->t, mynullvar->t ? " (NULL)" : "",
            myvar->d1, mynullvar->d1 ? " (NULL)" : "",
            myvar->d2, mynullvar->d2 ? " (NULL)" : "",
            myvar->c, mynullvar->c ? " (NULL)" : "");
    }

    close_cur1();

/*
 *     exec sql drop table a1;
 */
#line 101 "outofscope.ec"
{
#line 101 "outofscope.ec"
static const char *sqlcmdtxt[] =
#line 101 "outofscope.ec"
{
#line 101 "outofscope.ec"
"drop table a1",
0
};
#line 101 "outofscope.ec"
static ifx_statement_t _SQ0 = {0};
#line 101 "outofscope.ec"
sqli_stmt(ESQLINTVERSION, &_SQ0, sqlcmdtxt, 0, (ifx_sqlvar_t *)0, (struct value *)0, (ifx_literal_t *)0,
(ifx_namelist_t*)0, (ifx_cursor_t *)0, -1, 0, 0); 
#line 101 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 101 "outofscope.ec"
}

/*
 *     exec sql commit;
 */
#line 103 "outofscope.ec"
{
#line 103 "outofscope.ec"
sqli_trans_commit();
#line 103 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 103 "outofscope.ec"
}

/*
 *     exec sql disconnect all;
 */
#line 105 "outofscope.ec"
{
#line 105 "outofscope.ec"
sqli_connect_close(2, (char *)0, 0, 0);
#line 105 "outofscope.ec"
{ if (SQLCODE < 0) { sqli_stop_whenever(); exit(1);} }
#line 105 "outofscope.ec"
}

    return (0);
}

#line 108 "outofscope.ec"

Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Hi,

Michael Meskes írta:
> It is accepted either way. I was just pointing out that it might be easier to
> review/commit at least parts of your patches if they can be applied seperately.
>

I have split up (and cleaned up a little) the dynamic
cursorname patch into smaller logical, easier-to-review
pieces. Descriptions below.

1) 1a-unified-optfromin-fetch-ctxdiff.patch

ecpg supports optional FROM/IN in FETCH and
MOVE statements (mainly because it's required by
Informix-compatibility). Unify core and ecpg grammar
as per Tom Lane's suggestion.

2) 1b-cursor_name-ctxdiff.patch

"name" -> "cursor_name" transition in core grammar
and ecpg grammar. Currently it does nothing, it's a
preparation phase. Depends on patch 1.

3) 1c-remove-var-from-list.patch

Introduce function remove_variable_from_list().
It is used by the dynamic cursor, SQLDA and DESCRIBE
patches for different reasons. Applicable separately.

4) 1d-dynamiccur-ctxdiff.patch

The real point of the whole series in this email.
Extend "cursor_name" in the ecpg grammar to actually
accept a character variable. The cursorname-as-variable
is replaced in the final SQL script with a $0 placeholder.
Doesn't compile as-is, requires patch 5 to get the
two shift/reduce conflicts fixed. Depends on patches
1, 2 and 3.

5) 1e-fix-shiftreduce-ctxdiff.patch

De-factorize "BACKWARD opt_from_in cursor_name"
and "FORWARD opt_from_in cursor_name" out of
fetch_args and pull them up into FetchStmt in the ecpg
grammar. Depends on patch 4.
One line in parse.pl is not clear for me:
    $replace_line{'fetch_args'} = 'ignore';
The genarated preproc.y is the same with or without
this line. But as the previous version had it with
"fetch_direction", I left it in.

6) 1f-cursorname-in-varchar-ctxdiff.patch

Allow that varchar can be used as cursorname as well.
Other character variable types were already supported.
Depends on patch 4.

7) 1g-regressiontests-ctxdiff.patch

Introduce cursor.pgc regression test for both native
and compat mode. Depends on all patches.

8) 1h-fix-parse.pl-ctxdiff.patch

Now useless patch, in the previous dynamic cursorname
patch the following scenario occured: the same rule
had both an "addon" and a "rule" extension. Without
this fix, the following code was generated in preproc.y:
    ruleA: <accepted syntax>
       {
             <addon code block>
       {
             <automatic code block>
       }
With the cleanup I did during this splitup, this scenario
doesn't happen, but this fix may be considered useful.
Applicable separately.

After every patch (except 4) both the core and ecpg
"make check" are successful.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/

diff -dcrpN pgsql.orig/src/backend/parser/gram.y pgsql.ufd-opt-fromin-fetch/src/backend/parser/gram.y
*** pgsql.orig/src/backend/parser/gram.y    2009-09-23 19:25:40.000000000 +0200
--- pgsql.ufd-opt-fromin-fetch/src/backend/parser/gram.y    2009-10-02 23:57:32.000000000 +0200
*************** static TypeName *TableFuncTypeName(List
*** 330,336 ****
  %type <ival>    opt_column event cursor_options opt_hold opt_set_data
  %type <objtype>    reindex_type drop_type comment_type

! %type <node>    fetch_direction limit_clause select_limit_value
                  offset_clause select_offset_value
                  select_offset_value2 opt_select_fetch_first_value
  %type <ival>    row_or_rows first_or_next
--- 330,336 ----
  %type <ival>    opt_column event cursor_options opt_hold opt_set_data
  %type <objtype>    reindex_type drop_type comment_type

! %type <node>    fetch_args limit_clause select_limit_value
                  offset_clause select_offset_value
                  select_offset_value2 opt_select_fetch_first_value
  %type <ival>    row_or_rows first_or_next
*************** comment_text:
*** 4137,4278 ****
   *
   *****************************************************************************/

! FetchStmt:    FETCH fetch_direction from_in name
                  {
                      FetchStmt *n = (FetchStmt *) $2;
-                     n->portalname = $4;
-                     n->ismove = FALSE;
-                     $$ = (Node *)n;
-                 }
-             | FETCH name
-                 {
-                     FetchStmt *n = makeNode(FetchStmt);
-                     n->direction = FETCH_FORWARD;
-                     n->howMany = 1;
-                     n->portalname = $2;
                      n->ismove = FALSE;
                      $$ = (Node *)n;
                  }
!             | MOVE fetch_direction from_in name
                  {
                      FetchStmt *n = (FetchStmt *) $2;
-                     n->portalname = $4;
                      n->ismove = TRUE;
                      $$ = (Node *)n;
                  }
!             | MOVE name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_FORWARD;
                      n->howMany = 1;
-                     n->portalname = $2;
-                     n->ismove = TRUE;
                      $$ = (Node *)n;
                  }
!         ;
!
! fetch_direction:
!             /*EMPTY*/
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_FORWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | NEXT
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_FORWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | PRIOR
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_BACKWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | FIRST_P
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_ABSOLUTE;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | LAST_P
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_ABSOLUTE;
                      n->howMany = -1;
                      $$ = (Node *)n;
                  }
!             | ABSOLUTE_P SignedIconst
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_ABSOLUTE;
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | RELATIVE_P SignedIconst
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_RELATIVE;
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | SignedIconst
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_FORWARD;
                      n->howMany = $1;
                      $$ = (Node *)n;
                  }
!             | ALL
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_FORWARD;
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
                  }
!             | FORWARD
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_FORWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | FORWARD SignedIconst
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_FORWARD;
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | FORWARD ALL
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_FORWARD;
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
                  }
!             | BACKWARD
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_BACKWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | BACKWARD SignedIconst
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_BACKWARD;
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | BACKWARD ALL
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->direction = FETCH_BACKWARD;
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
--- 4137,4280 ----
   *
   *****************************************************************************/

! FetchStmt:    FETCH fetch_args
                  {
                      FetchStmt *n = (FetchStmt *) $2;
                      n->ismove = FALSE;
                      $$ = (Node *)n;
                  }
!             | MOVE fetch_args
                  {
                      FetchStmt *n = (FetchStmt *) $2;
                      n->ismove = TRUE;
                      $$ = (Node *)n;
                  }
!         ;
!
! fetch_args:    name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $1;
                      n->direction = FETCH_FORWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $2;
                      n->direction = FETCH_FORWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | NEXT opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $3;
                      n->direction = FETCH_FORWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | PRIOR opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $3;
                      n->direction = FETCH_BACKWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | FIRST_P opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $3;
                      n->direction = FETCH_ABSOLUTE;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | LAST_P opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $3;
                      n->direction = FETCH_ABSOLUTE;
                      n->howMany = -1;
                      $$ = (Node *)n;
                  }
!             | ABSOLUTE_P SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $4;
                      n->direction = FETCH_ABSOLUTE;
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | RELATIVE_P SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $4;
                      n->direction = FETCH_RELATIVE;
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $3;
                      n->direction = FETCH_FORWARD;
                      n->howMany = $1;
                      $$ = (Node *)n;
                  }
!             | ALL opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $3;
                      n->direction = FETCH_FORWARD;
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
                  }
!             | FORWARD opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $3;
                      n->direction = FETCH_FORWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | FORWARD SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $4;
                      n->direction = FETCH_FORWARD;
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | FORWARD ALL opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $4;
                      n->direction = FETCH_FORWARD;
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
                  }
!             | BACKWARD opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $3;
                      n->direction = FETCH_BACKWARD;
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | BACKWARD SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $4;
                      n->direction = FETCH_BACKWARD;
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | BACKWARD ALL opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
+                     n->portalname = $4;
                      n->direction = FETCH_BACKWARD;
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
*************** from_in:    FROM                                    {}
*** 4283,4288 ****
--- 4285,4295 ----
              | IN_P                                    {}
          ;

+ opt_from_in:    FROM                                    {}
+             | IN_P                                    {}
+             | /* EMPTY */                                {}
+         ;
+

  /*****************************************************************************
   *
diff -dcrpN pgsql.orig/src/interfaces/ecpg/preproc/ecpg.addons
pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql.orig/src/interfaces/ecpg/preproc/ecpg.addons    2009-08-14 16:27:41.000000000 +0200
--- pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/preproc/ecpg.addons    2009-10-03 00:50:37.000000000 +0200
*************** ECPG: ConstraintAttributeSpecConstraintT
*** 206,221 ****
              if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
                  mmerror(PARSE_ERROR, ET_ERROR, "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
  ECPG: var_valueNumericOnly addon
- ECPG: fetch_directionSignedIconst addon
          if ($1[0] == '$')
          {
              free($1);
              $1 = make_str("$0");
          }
! ECPG: fetch_directionABSOLUTE_PSignedIconst addon
! ECPG: fetch_directionRELATIVE_PSignedIconst addon
! ECPG: fetch_directionFORWARDSignedIconst addon
! ECPG: fetch_directionBACKWARDSignedIconst addon
          if ($2[0] == '$')
          {
              free($2);
--- 206,241 ----
              if (strcmp($2, "deferrable") != 0 && strcmp($1, "initially deferrable") == 0 )
                  mmerror(PARSE_ERROR, ET_ERROR, "constraint declared INITIALLY DEFERRED must be DEFERRABLE");
  ECPG: var_valueNumericOnly addon
          if ($1[0] == '$')
          {
              free($1);
              $1 = make_str("$0");
          }
! ECPG: fetch_argsname addon
!         add_additional_variables($1, false);
! ECPG: fetch_argsfrom_inname addon
!         add_additional_variables($2, false);
! ECPG: fetch_argsNEXTopt_from_inname addon
! ECPG: fetch_argsPRIORopt_from_inname addon
! ECPG: fetch_argsFIRST_Popt_from_inname addon
! ECPG: fetch_argsLAST_Popt_from_inname addon
! ECPG: fetch_argsALLopt_from_inname addon
!         add_additional_variables($3, false);
! ECPG: fetch_argsSignedIconstopt_from_inname addon
!         add_additional_variables($3, false);
!         if ($1[0] == '$')
!         {
!             free($1);
!             $1 = make_str("$0");
!         }
! ECPG: fetch_argsFORWARDALLopt_from_inname addon
! ECPG: fetch_argsBACKWARDALLopt_from_inname addon
!         add_additional_variables($4, false);
! ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_inname addon
! ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_inname addon
! ECPG: fetch_argsFORWARDSignedIconstopt_from_inname addon
! ECPG: fetch_argsBACKWARDSignedIconstopt_from_inname addon
!         add_additional_variables($4, false);
          if ($2[0] == '$')
          {
              free($2);
*************** ECPG: VariableShowStmtSHOWALL block
*** 336,382 ****
          mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
          $$ = EMPTY;
      }
! ECPG: FetchStmtFETCHfetch_directionfrom_inname block
!     {
!         add_additional_variables($4, false);
!         $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
!     }
! ECPG: FetchStmtFETCHname block
      {
!         add_additional_variables($2, false);
!         $$ = cat_str(2, make_str("fetch"), $2);
      }
- ECPG: FetchStmtMOVEname rule
-     | FETCH fetch_direction from_in name ecpg_into
-         {
-             add_additional_variables($4, false);
-             $$ = cat_str(4, make_str("fetch"), $2, $3, $4);
-         }
-     | FETCH fetch_direction name ecpg_into
-         {
-             add_additional_variables($3, false);
-             $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
-         }
-     | FETCH from_in name ecpg_into
-         {
-             add_additional_variables($3, false);
-             $$ = cat_str(3, make_str("fetch"), $2, $3);
-         }
-     | FETCH name ecpg_into
-         {
-             add_additional_variables($2, false);
-             $$ = cat2_str(make_str("fetch"), $2);
-         }
-     | FETCH fetch_direction name
-         {
-             add_additional_variables($3, false);
-             $$ = cat_str(4, make_str("fetch"), $2, make_str("from"), $3);
-         }
-     | FETCH from_in name
-         {
-             add_additional_variables($3, false);
-             $$ = cat_str(3, make_str("fetch"), $2, $3);
-         }
  ECPG: SpecialRuleRelationOLD addon
          if (!QueryIsRule)
              mmerror(PARSE_ERROR, ET_ERROR, "OLD used in query that is not in a rule");
--- 356,366 ----
          mmerror(PARSE_ERROR, ET_ERROR, "SHOW ALL is not implemented");
          $$ = EMPTY;
      }
! ECPG: FetchStmtMOVEfetch_args rule
!     | FETCH fetch_args ecpg_into
      {
!         $$ = cat2_str(make_str("fetch"), $2);
      }
  ECPG: SpecialRuleRelationOLD addon
          if (!QueryIsRule)
              mmerror(PARSE_ERROR, ET_ERROR, "OLD used in query that is not in a rule");
diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c
pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c
*** pgsql.orig/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c    2009-08-14 16:27:41.000000000 +0200
--- pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/test/expected/compat_informix-test_informix.c    2009-10-03
00:33:14.000000000+0200 
*************** if (sqlca.sqlcode < 0) dosqlprint ( );}
*** 158,164 ****

      while (1)
      {
!         { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch forward from c", ECPGt_EOIT,
      ECPGt_int,&(i),(long)1,(long)1,sizeof(int),
      ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
      ECPGt_decimal,&(j),(long)1,(long)1,sizeof(decimal),
--- 158,164 ----

      while (1)
      {
!         { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch forward c", ECPGt_EOIT,
      ECPGt_int,&(i),(long)1,(long)1,sizeof(int),
      ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
      ECPGt_decimal,&(j),(long)1,(long)1,sizeof(decimal),
diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr
pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr
*** pgsql.orig/src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr    2009-08-14 16:27:41.000000000
+0200
--- pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/test/expected/compat_informix-test_informix.stderr    2009-10-03
00:33:15.000000000+0200 
*************** DETAIL:  Key (i)=(7) already exists.
*** 63,69 ****
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_execute on line 95: OK: DECLARE CURSOR
  [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 57: query: fetch forward from c; with 0 parameter(s) on connection regress1
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_execute on line 57: using PQexec
  [NO_PID]: sqlca: code: 0, state: 00000
--- 63,69 ----
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_execute on line 95: OK: DECLARE CURSOR
  [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 57: query: fetch forward c; with 0 parameter(s) on connection regress1
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_execute on line 57: using PQexec
  [NO_PID]: sqlca: code: 0, state: 00000
*************** DETAIL:  Key (i)=(7) already exists.
*** 75,81 ****
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_get_data on line 57: RESULT: test    offset: -1; array: yes
  [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 57: query: fetch forward from c; with 0 parameter(s) on connection regress1
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_execute on line 57: using PQexec
  [NO_PID]: sqlca: code: 0, state: 00000
--- 75,81 ----
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_get_data on line 57: RESULT: test    offset: -1; array: yes
  [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 57: query: fetch forward c; with 0 parameter(s) on connection regress1
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_execute on line 57: using PQexec
  [NO_PID]: sqlca: code: 0, state: 00000
*************** DETAIL:  Key (i)=(7) already exists.
*** 87,93 ****
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_get_data on line 57: RESULT: a       offset: -1; array: yes
  [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 57: query: fetch forward from c; with 0 parameter(s) on connection regress1
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_execute on line 57: using PQexec
  [NO_PID]: sqlca: code: 0, state: 00000
--- 87,93 ----
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_get_data on line 57: RESULT: a       offset: -1; array: yes
  [NO_PID]: sqlca: code: 0, state: 00000
! [NO_PID]: ecpg_execute on line 57: query: fetch forward c; with 0 parameter(s) on connection regress1
  [NO_PID]: sqlca: code: 0, state: 00000
  [NO_PID]: ecpg_execute on line 57: using PQexec
  [NO_PID]: sqlca: code: 0, state: 00000
diff -dcrpN pgsql.ufd-opt-fromin-fetch/src/backend/parser/gram.y pgsql.cursor_name/src/backend/parser/gram.y
*** pgsql.ufd-opt-fromin-fetch/src/backend/parser/gram.y    2009-10-02 23:57:32.000000000 +0200
--- pgsql.cursor_name/src/backend/parser/gram.y    2009-10-03 00:47:53.000000000 +0200
*************** static TypeName *TableFuncTypeName(List
*** 252,258 ****

  %type <str>        relation_name copy_file_name
                  database_name access_method_clause access_method attr_name
!                 index_name name file_name cluster_index_specification

  %type <list>    func_name handler_name qual_Op qual_all_Op subquery_Op
                  opt_class opt_inline_handler opt_validator validator_clause
--- 252,258 ----

  %type <str>        relation_name copy_file_name
                  database_name access_method_clause access_method attr_name
!                 index_name name cursor_name file_name cluster_index_specification

  %type <list>    func_name handler_name qual_Op qual_all_Op subquery_Op
                  opt_class opt_inline_handler opt_validator validator_clause
*************** reloption_elem:
*** 1920,1926 ****
   *****************************************************************************/

  ClosePortalStmt:
!             CLOSE name
                  {
                      ClosePortalStmt *n = makeNode(ClosePortalStmt);
                      n->portalname = $2;
--- 1920,1926 ----
   *****************************************************************************/

  ClosePortalStmt:
!             CLOSE cursor_name
                  {
                      ClosePortalStmt *n = makeNode(ClosePortalStmt);
                      n->portalname = $2;
*************** FetchStmt:    FETCH fetch_args
*** 4151,4157 ****
                  }
          ;

! fetch_args:    name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $1;
--- 4151,4157 ----
                  }
          ;

! fetch_args:    cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $1;
*************** fetch_args:    name
*** 4159,4165 ****
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $2;
--- 4159,4165 ----
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $2;
*************** fetch_args:    name
*** 4167,4173 ****
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | NEXT opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
--- 4167,4173 ----
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | NEXT opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
*************** fetch_args:    name
*** 4175,4181 ****
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | PRIOR opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
--- 4175,4181 ----
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | PRIOR opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
*************** fetch_args:    name
*** 4183,4189 ****
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | FIRST_P opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
--- 4183,4189 ----
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | FIRST_P opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
*************** fetch_args:    name
*** 4191,4197 ****
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | LAST_P opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
--- 4191,4197 ----
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | LAST_P opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
*************** fetch_args:    name
*** 4199,4205 ****
                      n->howMany = -1;
                      $$ = (Node *)n;
                  }
!             | ABSOLUTE_P SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
--- 4199,4205 ----
                      n->howMany = -1;
                      $$ = (Node *)n;
                  }
!             | ABSOLUTE_P SignedIconst opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
*************** fetch_args:    name
*** 4207,4213 ****
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | RELATIVE_P SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
--- 4207,4213 ----
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | RELATIVE_P SignedIconst opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
*************** fetch_args:    name
*** 4215,4221 ****
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
--- 4215,4221 ----
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | SignedIconst opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
*************** fetch_args:    name
*** 4223,4229 ****
                      n->howMany = $1;
                      $$ = (Node *)n;
                  }
!             | ALL opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
--- 4223,4229 ----
                      n->howMany = $1;
                      $$ = (Node *)n;
                  }
!             | ALL opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
*************** fetch_args:    name
*** 4231,4237 ****
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
                  }
!             | FORWARD opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
--- 4231,4237 ----
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
                  }
!             | FORWARD opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
*************** fetch_args:    name
*** 4239,4245 ****
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | FORWARD SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
--- 4239,4245 ----
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | FORWARD SignedIconst opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
*************** fetch_args:    name
*** 4247,4253 ****
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | FORWARD ALL opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
--- 4247,4253 ----
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | FORWARD ALL opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
*************** fetch_args:    name
*** 4255,4261 ****
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
                  }
!             | BACKWARD opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
--- 4255,4261 ----
                      n->howMany = FETCH_ALL;
                      $$ = (Node *)n;
                  }
!             | BACKWARD opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $3;
*************** fetch_args:    name
*** 4263,4269 ****
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | BACKWARD SignedIconst opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
--- 4263,4269 ----
                      n->howMany = 1;
                      $$ = (Node *)n;
                  }
!             | BACKWARD SignedIconst opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
*************** fetch_args:    name
*** 4271,4277 ****
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | BACKWARD ALL opt_from_in name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
--- 4271,4277 ----
                      n->howMany = $2;
                      $$ = (Node *)n;
                  }
!             | BACKWARD ALL opt_from_in cursor_name
                  {
                      FetchStmt *n = makeNode(FetchStmt);
                      n->portalname = $4;
*************** set_target_list:
*** 6941,6947 ****
   *                CURSOR STATEMENTS
   *
   *****************************************************************************/
! DeclareCursorStmt: DECLARE name cursor_options CURSOR opt_hold FOR SelectStmt
                  {
                      DeclareCursorStmt *n = makeNode(DeclareCursorStmt);
                      n->portalname = $2;
--- 6941,6947 ----
   *                CURSOR STATEMENTS
   *
   *****************************************************************************/
! DeclareCursorStmt: DECLARE cursor_name cursor_options CURSOR opt_hold FOR SelectStmt
                  {
                      DeclareCursorStmt *n = makeNode(DeclareCursorStmt);
                      n->portalname = $2;
*************** DeclareCursorStmt: DECLARE name cursor_o
*** 6952,6957 ****
--- 6952,6960 ----
                  }
          ;

+ cursor_name:    name                        { $$ = $1; }
+         ;
+
  cursor_options: /*EMPTY*/                    { $$ = 0; }
              | cursor_options NO SCROLL        { $$ = $1 | CURSOR_OPT_NO_SCROLL; }
              | cursor_options SCROLL            { $$ = $1 | CURSOR_OPT_SCROLL; }
diff -dcrpN pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/preproc/ecpg.addons
pgsql.cursor_name/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/preproc/ecpg.addons    2009-10-03 00:50:37.000000000 +0200
--- pgsql.cursor_name/src/interfaces/ecpg/preproc/ecpg.addons    2009-10-03 00:51:58.000000000 +0200
*************** ECPG: var_valueNumericOnly addon
*** 211,240 ****
              free($1);
              $1 = make_str("$0");
          }
! ECPG: fetch_argsname addon
          add_additional_variables($1, false);
! ECPG: fetch_argsfrom_inname addon
          add_additional_variables($2, false);
! ECPG: fetch_argsNEXTopt_from_inname addon
! ECPG: fetch_argsPRIORopt_from_inname addon
! ECPG: fetch_argsFIRST_Popt_from_inname addon
! ECPG: fetch_argsLAST_Popt_from_inname addon
! ECPG: fetch_argsALLopt_from_inname addon
          add_additional_variables($3, false);
! ECPG: fetch_argsSignedIconstopt_from_inname addon
          add_additional_variables($3, false);
          if ($1[0] == '$')
          {
              free($1);
              $1 = make_str("$0");
          }
! ECPG: fetch_argsFORWARDALLopt_from_inname addon
! ECPG: fetch_argsBACKWARDALLopt_from_inname addon
          add_additional_variables($4, false);
! ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_inname addon
! ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_inname addon
! ECPG: fetch_argsFORWARDSignedIconstopt_from_inname addon
! ECPG: fetch_argsBACKWARDSignedIconstopt_from_inname addon
          add_additional_variables($4, false);
          if ($2[0] == '$')
          {
--- 211,240 ----
              free($1);
              $1 = make_str("$0");
          }
! ECPG: fetch_argscursor_name addon
          add_additional_variables($1, false);
! ECPG: fetch_argsfrom_incursor_name addon
          add_additional_variables($2, false);
! ECPG: fetch_argsNEXTopt_from_incursor_name addon
! ECPG: fetch_argsPRIORopt_from_incursor_name addon
! ECPG: fetch_argsFIRST_Popt_from_incursor_name addon
! ECPG: fetch_argsLAST_Popt_from_incursor_name addon
! ECPG: fetch_argsALLopt_from_incursor_name addon
          add_additional_variables($3, false);
! ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
          add_additional_variables($3, false);
          if ($1[0] == '$')
          {
              free($1);
              $1 = make_str("$0");
          }
! ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon
! ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
          add_additional_variables($4, false);
! ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon
! ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
! ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon
! ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon
          add_additional_variables($4, false);
          if ($2[0] == '$')
          {
*************** ECPG: PrepareStmtPREPAREprepared_namepre
*** 255,261 ****
      }
  ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
      { $$ = $2; }
! ECPG: DeclareCursorStmtDECLAREnamecursor_optionsCURSORopt_holdFORSelectStmt block
      {
          struct cursor *ptr, *this;
          char *comment;
--- 255,261 ----
      }
  ECPG: ExecuteStmtEXECUTEprepared_nameexecute_param_clauseexecute_rest block
      { $$ = $2; }
! ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
      {
          struct cursor *ptr, *this;
          char *comment;
diff -dcrpN pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql.cursor_name/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql.ufd-opt-fromin-fetch/src/interfaces/ecpg/preproc/ecpg.trailer    2009-09-23 19:25:46.000000000 +0200
--- pgsql.cursor_name/src/interfaces/ecpg/preproc/ecpg.trailer    2009-10-03 00:55:00.000000000 +0200
*************** prepared_name: name             {
*** 285,291 ****
   * Declare a prepared cursor. The syntax is different from the standard
   * declare statement, so we create a new rule.
   */
! ECPGCursorStmt:  DECLARE name cursor_options CURSOR opt_hold FOR prepared_name
          {
              struct cursor *ptr, *this;
              struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
--- 285,291 ----
   * Declare a prepared cursor. The syntax is different from the standard
   * declare statement, so we create a new rule.
   */
! ECPGCursorStmt:  DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name
          {
              struct cursor *ptr, *this;
              struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
*************** ECPGFree:    SQL_FREE name    { $$ = $2; }
*** 957,963 ****
  /*
   * open is an open cursor, at the moment this has to be removed
   */
! ECPGOpen: SQL_OPEN name opt_ecpg_using { $$ = $2; };

  opt_ecpg_using: /*EMPTY*/    { $$ = EMPTY; }
          | ecpg_using        { $$ = $1; }
--- 957,963 ----
  /*
   * open is an open cursor, at the moment this has to be removed
   */
! ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using { $$ = $2; };

  opt_ecpg_using: /*EMPTY*/    { $$ = EMPTY; }
          | ecpg_using        { $$ = $1; }
diff -dcrpN pgsql.cursor_name/src/interfaces/ecpg/preproc/extern.h
pgsql.removevarlist/src/interfaces/ecpg/preproc/extern.h
*** pgsql.cursor_name/src/interfaces/ecpg/preproc/extern.h    2009-09-08 10:12:40.000000000 +0200
--- pgsql.removevarlist/src/interfaces/ecpg/preproc/extern.h    2009-10-03 01:07:54.000000000 +0200
*************** extern struct descriptor *lookup_descrip
*** 90,95 ****
--- 90,96 ----
  extern struct variable *descriptor_variable(const char *name, int input);
  extern void add_variable_to_head(struct arguments **, struct variable *, struct variable *);
  extern void add_variable_to_tail(struct arguments **, struct variable *, struct variable *);
+ extern void remove_variable_from_list(struct arguments ** list, struct variable * var);
  extern void dump_variables(struct arguments *, int);
  extern struct typedefs *get_typedef(char *);
  extern void adjust_array(enum ECPGttype, char **, char **, char *, char *, int, bool);
diff -dcrpN pgsql.cursor_name/src/interfaces/ecpg/preproc/variable.c
pgsql.removevarlist/src/interfaces/ecpg/preproc/variable.c
*** pgsql.cursor_name/src/interfaces/ecpg/preproc/variable.c    2009-08-07 13:06:28.000000000 +0200
--- pgsql.removevarlist/src/interfaces/ecpg/preproc/variable.c    2009-10-03 01:09:32.000000000 +0200
*************** add_variable_to_tail(struct arguments **
*** 401,406 ****
--- 401,430 ----
          *list = new;
  }

+ void
+ remove_variable_from_list(struct arguments ** list, struct variable * var)
+ {
+     struct arguments *p, *prev = NULL;
+     bool found = false;
+
+     for (p = *list; p; p = p->next)
+     {
+         if (p->variable == var)
+         {
+             found = true;
+             break;
+         }
+         prev = p;
+     }
+     if (found)
+     {
+         if (prev)
+             prev->next = p->next;
+         else
+             *list = p->next;
+     }
+ }
+
  /* Dump out a list of all the variable on this list.
     This is a recursive function that works from the end of the list and
     deletes the list as we go on.
diff -dcrpN pgsql.removevarlist/src/interfaces/ecpg/preproc/ecpg.addons
pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql.removevarlist/src/interfaces/ecpg/preproc/ecpg.addons    2009-10-03 00:51:58.000000000 +0200
--- pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.addons    2009-10-03 01:24:46.000000000 +0200
*************** ECPG: var_valueNumericOnly addon
*** 213,228 ****
--- 213,248 ----
          }
  ECPG: fetch_argscursor_name addon
          add_additional_variables($1, false);
+         if ($1[0] == ':')
+         {
+             free($1);
+             $1 = make_str("$0");
+         }
  ECPG: fetch_argsfrom_incursor_name addon
          add_additional_variables($2, false);
+         if ($2[0] == ':')
+         {
+             free($2);
+             $2 = make_str("$0");
+         }
  ECPG: fetch_argsNEXTopt_from_incursor_name addon
  ECPG: fetch_argsPRIORopt_from_incursor_name addon
  ECPG: fetch_argsFIRST_Popt_from_incursor_name addon
  ECPG: fetch_argsLAST_Popt_from_incursor_name addon
  ECPG: fetch_argsALLopt_from_incursor_name addon
          add_additional_variables($3, false);
+         if ($3[0] == ':')
+         {
+             free($3);
+             $3 = make_str("$0");
+         }
  ECPG: fetch_argsSignedIconstopt_from_incursor_name addon
          add_additional_variables($3, false);
+         if ($3[0] == ':')
+         {
+             free($3);
+             $3 = make_str("$0");
+         }
          if ($1[0] == '$')
          {
              free($1);
*************** ECPG: fetch_argsSignedIconstopt_from_inc
*** 231,246 ****
--- 251,285 ----
  ECPG: fetch_argsFORWARDALLopt_from_incursor_name addon
  ECPG: fetch_argsBACKWARDALLopt_from_incursor_name addon
          add_additional_variables($4, false);
+         if ($4[0] == ':')
+         {
+             free($4);
+             $4 = make_str("$0");
+         }
  ECPG: fetch_argsABSOLUTE_PSignedIconstopt_from_incursor_name addon
  ECPG: fetch_argsRELATIVE_PSignedIconstopt_from_incursor_name addon
  ECPG: fetch_argsFORWARDSignedIconstopt_from_incursor_name addon
  ECPG: fetch_argsBACKWARDSignedIconstopt_from_incursor_name addon
          add_additional_variables($4, false);
+         if ($4[0] == ':')
+         {
+             free($4);
+             $4 = make_str("$0");
+         }
          if ($2[0] == '$')
          {
              free($2);
              $2 = make_str("$0");
          }
+ ECPG: cursor_namename rule
+     | char_civar
+         {
+             char *curname = mm_alloc(strlen($1) + 2);
+             sprintf(curname, ":%s", $1);
+             free($1);
+             $1 = curname;
+             $$ = $1;
+         }
  ECPG: PrepareStmtPREPAREprepared_nameprep_type_clauseASPreparableStmt block
      {
          $$.name = $2;
*************** ECPG: ExecuteStmtEXECUTEprepared_nameexe
*** 258,263 ****
--- 297,303 ----
  ECPG: DeclareCursorStmtDECLAREcursor_namecursor_optionsCURSORopt_holdFORSelectStmt block
      {
          struct cursor *ptr, *this;
+         char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
          char *comment;

          for (ptr = cur; ptr != NULL; ptr = ptr->next)
*************** ECPG: DeclareCursorStmtDECLAREcursor_nam
*** 272,278 ****
          this->name = $2;
          this->connection = connection;
          this->opened = false;
!         this->command =  cat_str(7, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for"),
$7);
          this->argsinsert = argsinsert;
          this->argsresult = argsresult;
          argsinsert = argsresult = NULL;
--- 312,318 ----
          this->name = $2;
          this->connection = connection;
          this->opened = false;
!         this->command =  cat_str(7, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for"),
$7);
          this->argsinsert = argsinsert;
          this->argsresult = argsresult;
          argsinsert = argsresult = NULL;
*************** ECPG: DeclareCursorStmtDECLAREcursor_nam
*** 292,297 ****
--- 332,342 ----
          else
              $$ = comment;
      }
+ ECPG: ClosePortalStmtCLOSEcursor_name block
+     {
+         char *cursor_marker = $2[0] == ':' ? make_str("$0") : $2;
+         $$ = cat2_str(make_str("close"), cursor_marker);
+     }
  ECPG: opt_hold block
      {
          if (compat == ECPG_COMPAT_INFORMIX_SE && autocommit == true)
diff -dcrpN pgsql.removevarlist/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql.removevarlist/src/interfaces/ecpg/preproc/ecpg.trailer    2009-10-03 00:55:00.000000000 +0200
--- pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.trailer    2009-10-03 01:36:36.000000000 +0200
*************** prepared_name: name             {
*** 288,293 ****
--- 288,294 ----
  ECPGCursorStmt:  DECLARE cursor_name cursor_options CURSOR opt_hold FOR prepared_name
          {
              struct cursor *ptr, *this;
+             char *cursor_marker = $2[0] == ':' ? make_str("$0") : mm_strdup($2);
              struct variable *thisquery = (struct variable *)mm_alloc(sizeof(struct variable));
              const char *con = connection ? connection : "NULL";

*************** ECPGCursorStmt:  DECLARE cursor_name cur
*** 304,310 ****
              this->next = cur;
              this->name = $2;
              this->connection = connection;
!             this->command =  cat_str(6, make_str("declare"), mm_strdup($2), $3, make_str("cursor"), $5, make_str("for
$1"));
              this->argsresult = NULL;

              thisquery->type = &ecpg_query;
--- 305,311 ----
              this->next = cur;
              this->name = $2;
              this->connection = connection;
!             this->command =  cat_str(6, make_str("declare"), cursor_marker, $3, make_str("cursor"), $5, make_str("for
$1"));
              this->argsresult = NULL;

              thisquery->type = &ecpg_query;
*************** ECPGCursorStmt:  DECLARE cursor_name cur
*** 314,319 ****
--- 315,326 ----
              sprintf(thisquery->name, "ECPGprepared_statement(%s, %s, __LINE__)", con, $7);

              this->argsinsert = NULL;
+             if ($2[0] == ':')
+             {
+                 struct variable *var = find_variable($2 + 1);
+                 remove_variable_from_list(&argsinsert, var);
+                 add_variable_to_head(&(this->argsinsert), var, &no_indicator);
+             }
              add_variable_to_head(&(this->argsinsert), thisquery, &no_indicator);

              cur = this;
*************** ECPGFree:    SQL_FREE name    { $$ = $2; }
*** 957,963 ****
  /*
   * open is an open cursor, at the moment this has to be removed
   */
! ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using { $$ = $2; };

  opt_ecpg_using: /*EMPTY*/    { $$ = EMPTY; }
          | ecpg_using        { $$ = $1; }
--- 964,979 ----
  /*
   * open is an open cursor, at the moment this has to be removed
   */
! ECPGOpen: SQL_OPEN cursor_name opt_ecpg_using
!         {
!             if ($2[0] == ':')
!             {
!                 struct variable *var = find_variable($2 + 1);
!                 remove_variable_from_list(&argsinsert, var);
!             }
!             $$ = $2;
!         }
!         ;

  opt_ecpg_using: /*EMPTY*/    { $$ = EMPTY; }
          | ecpg_using        { $$ = $1; }
*************** civarind: cvariable indicator
*** 1782,1787 ****
--- 1798,1810 ----
          }
          ;

+ char_civar: char_variable
+         {
+             add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
+             $$ = $1;
+         }
+         ;
+
  civar: cvariable
          {
              add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
diff -dcrpN pgsql.removevarlist/src/interfaces/ecpg/preproc/ecpg.type
pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.type
*** pgsql.removevarlist/src/interfaces/ecpg/preproc/ecpg.type    2008-11-14 11:03:33.000000000 +0100
--- pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.type    2009-10-03 01:36:11.000000000 +0200
***************
*** 43,48 ****
--- 43,49 ----
  %type <str> c_term
  %type <str> c_thing
  %type <str> char_variable
+ %type <str> char_civar
  %type <str> civar
  %type <str> civarind
  %type <str> ColLabel
diff -dcrpN pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.addons
pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.addons
*** pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.addons    2009-10-03 01:24:46.000000000 +0200
--- pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.addons    2009-10-03 01:54:43.000000000 +0200
*************** ECPG: FetchStmtMOVEfetch_args rule
*** 406,411 ****
--- 406,459 ----
      {
          $$ = cat2_str(make_str("fetch"), $2);
      }
+     | FETCH FORWARD cursor_name opt_ecpg_into
+     {
+         char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
+         add_additional_variables($3, false);
+         $$ = cat_str(2, make_str("fetch forward"), cursor_marker);
+     }
+     | FETCH FORWARD from_in cursor_name opt_ecpg_into
+     {
+         char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+         add_additional_variables($4, false);
+         $$ = cat_str(2, make_str("fetch forward from"), cursor_marker);
+     }
+     | FETCH BACKWARD cursor_name opt_ecpg_into
+     {
+         char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
+         add_additional_variables($3, false);
+         $$ = cat_str(2, make_str("fetch backward"), cursor_marker);
+     }
+     | FETCH BACKWARD from_in cursor_name opt_ecpg_into
+     {
+         char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+         add_additional_variables($4, false);
+         $$ = cat_str(2, make_str("fetch backward from"), cursor_marker);
+     }
+     | MOVE FORWARD cursor_name
+     {
+         char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
+         add_additional_variables($3, false);
+         $$ = cat_str(2, make_str("move forward"), cursor_marker);
+     }
+     | MOVE FORWARD from_in cursor_name
+     {
+         char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+         add_additional_variables($4, false);
+         $$ = cat_str(2, make_str("move forward from"), cursor_marker);
+     }
+     | MOVE BACKWARD cursor_name
+     {
+         char *cursor_marker = $3[0] == ':' ? make_str("$0") : $3;
+         add_additional_variables($3, false);
+         $$ = cat_str(2, make_str("move backward"), cursor_marker);
+     }
+     | MOVE BACKWARD from_in cursor_name
+     {
+         char *cursor_marker = $4[0] == ':' ? make_str("$0") : $4;
+         add_additional_variables($4, false);
+         $$ = cat_str(2, make_str("move backward from"), cursor_marker);
+     }
  ECPG: SpecialRuleRelationOLD addon
          if (!QueryIsRule)
              mmerror(PARSE_ERROR, ET_ERROR, "OLD used in query that is not in a rule");
diff -dcrpN pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.trailer    2009-10-03 01:36:36.000000000 +0200
--- pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.trailer    2009-10-03 01:42:17.000000000 +0200
*************** ecpg_into: INTO into_list    { $$ = EMPTY;
*** 2020,2025 ****
--- 2020,2029 ----
          | into_descriptor    { $$ = $1; }
      ;

+ opt_ecpg_into:    /* EMPTY */    { $$ = EMPTY; }
+     | ecpg_into        { $$ = $1; }
+     ;
+
  %%

  void base_yyerror(const char *error)
diff -dcrpN pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.type pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.type
*** pgsql.dynamiccur/src/interfaces/ecpg/preproc/ecpg.type    2009-10-03 01:36:11.000000000 +0200
--- pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.type    2009-10-03 01:41:51.000000000 +0200
***************
*** 76,81 ****
--- 76,82 ----
  %type <str> opt_bit_field
  %type <str> opt_connection_name
  %type <str> opt_database_name
+ %type <str> opt_ecpg_into
  %type <str> opt_ecpg_using
  %type <str> opt_initializer
  %type <str> opt_options
diff -dcrpN pgsql.dynamiccur/src/interfaces/ecpg/preproc/parse.pl pgsql.fixshred/src/interfaces/ecpg/preproc/parse.pl
*** pgsql.dynamiccur/src/interfaces/ecpg/preproc/parse.pl    2009-01-30 17:28:46.000000000 +0100
--- pgsql.fixshred/src/interfaces/ecpg/preproc/parse.pl    2009-10-03 01:54:56.000000000 +0200
*************** $replace_types{'unreserved_keyword'} = '
*** 57,63 ****
  $replace_types{'Sconst'} = 'ignore';

  # some production rules have to be ignored or replaced
! $replace_line{'fetch_direction'} = 'ignore';
  $replace_line{"opt_array_boundsopt_array_bounds'['Iconst']'"} = 'ignore';
  $replace_line{'col_name_keywordCHAR_P'} = 'ignore';
  $replace_line{'col_name_keywordINT_P'} = 'ignore';
--- 57,65 ----
  $replace_types{'Sconst'} = 'ignore';

  # some production rules have to be ignored or replaced
! $replace_line{'fetch_args'} = 'ignore';
! $replace_line{'fetch_argsFORWARDopt_from_incursor_name'} = 'ignore';
! $replace_line{'fetch_argsBACKWARDopt_from_incursor_name'} = 'ignore';
  $replace_line{"opt_array_boundsopt_array_bounds'['Iconst']'"} = 'ignore';
  $replace_line{'col_name_keywordCHAR_P'} = 'ignore';
  $replace_line{'col_name_keywordINT_P'} = 'ignore';
diff -dcrpN pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.trailer
pgsql.cname_in_varchar/src/interfaces/ecpg/preproc/ecpg.trailer
*** pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.trailer    2009-10-03 01:42:17.000000000 +0200
--- pgsql.cname_in_varchar/src/interfaces/ecpg/preproc/ecpg.trailer    2009-10-03 02:05:58.000000000 +0200
*************** char_variable: cvariable
*** 228,233 ****
--- 228,265 ----
          }
          ;

+ cursor_char_variable: cvariable
+         {
+             /* check if we have a string variable */
+             struct variable *p = find_variable($1);
+             enum ECPGttype type = p->type->type;
+
+             /* If we have just one character this is not a string */
+             if (atol(p->type->size) == 1)
+                     mmerror(PARSE_ERROR, ET_ERROR, "invalid data type");
+             else
+             {
+                 /* if array see what's inside */
+                 if (type == ECPGt_array)
+                     type = p->type->u.element->type;
+
+                 switch (type)
+                 {
+                     case ECPGt_char:
+                     case ECPGt_unsigned_char:
+                     case ECPGt_string:
+                     case ECPGt_varchar:
+                         $$ = $1;
+                         break;
+                     default:
+                         mmerror(PARSE_ERROR, ET_ERROR, "invalid data type");
+                         $$ = $1;
+                         break;
+                 }
+             }
+         }
+         ;
+
  opt_options: Op connect_options
          {
              if (strlen($1) == 0)
*************** civarind: cvariable indicator
*** 1798,1804 ****
          }
          ;

! char_civar: char_variable
          {
              add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
              $$ = $1;
--- 1830,1836 ----
          }
          ;

! char_civar: cursor_char_variable
          {
              add_variable_to_head(&argsinsert, find_variable($1), &no_indicator);
              $$ = $1;
diff -dcrpN pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.type
pgsql.cname_in_varchar/src/interfaces/ecpg/preproc/ecpg.type
*** pgsql.fixshred/src/interfaces/ecpg/preproc/ecpg.type    2009-10-03 01:41:51.000000000 +0200
--- pgsql.cname_in_varchar/src/interfaces/ecpg/preproc/ecpg.type    2009-10-03 02:03:31.000000000 +0200
***************
*** 46,51 ****
--- 46,52 ----
  %type <str> char_civar
  %type <str> civar
  %type <str> civarind
+ %type <str> cursor_char_variable
  %type <str> ColLabel
  %type <str> connect_options
  %type <str> connection_object
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/compat_informix/cursor.pgc
pgsql.regressiontests/src/interfaces/ecpg/test/compat_informix/cursor.pgc
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/compat_informix/cursor.pgc    1970-01-01 01:00:00.000000000 +0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/compat_informix/cursor.pgc    2009-10-03 02:11:20.000000000 +0200
***************
*** 0 ****
--- 1,245 ----
+ #include <stdlib.h>
+ #include <string.h>
+
+ exec sql include ../regression;
+
+ exec sql whenever sqlerror stop;
+
+ exec sql type c is char reference;
+ typedef char* c;
+
+ exec sql type ind is union { int integer; short smallint; };
+ typedef union { int integer; short smallint; } ind;
+
+ #define BUFFERSIZ 8
+ exec sql type str is varchar[BUFFERSIZ];
+
+ #define CURNAME "mycur"
+
+ int
+ main (void)
+ {
+ exec sql begin declare section;
+     char    *stmt1 = "SELECT id, t FROM t1";
+     char    *curname1 = CURNAME;
+     char    *curname2 = CURNAME;
+     char    *curname3 = CURNAME;
+     varchar    curname4[50];
+     int    count;
+     int    id;
+     char    t[64];
+ exec sql end declare section;
+
+     char msg[128];
+
+     ECPGdebug(1, stderr);
+
+     strcpy(msg, "connect");
+     exec sql connect to REGRESSDB1;
+
+     strcpy(msg, "set");
+     exec sql set datestyle to iso;
+
+     strcpy(msg, "create");
+     exec sql create table t1(id serial primary key, t text);
+
+     strcpy(msg, "insert");
+     exec sql insert into t1(id, t) values (default, 'a');
+     exec sql insert into t1(id, t) values (default, 'b');
+     exec sql insert into t1(id, t) values (default, 'c');
+     exec sql insert into t1(id, t) values (default, 'd');
+
+     strcpy(msg, "commit");
+     exec sql commit;
+
+     /* Dynamic cursorname test with INTO list in FETCH stmts */
+
+     strcpy(msg, "declare");
+     exec sql declare :curname1 cursor for
+         select id, t from t1;
+
+     strcpy(msg, "open");
+     exec sql open :curname1;
+
+     strcpy(msg, "fetch from");
+     exec sql fetch from :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     exec sql fetch :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     exec sql fetch 1 from :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     exec sql fetch :count from :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move in");
+     exec sql move absolute 0 in :curname1;
+
+     strcpy(msg, "fetch 1");
+     exec sql fetch 1 :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     exec sql fetch :count :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     exec sql close :curname1;
+
+     /* Dynamic cursorname test with INTO list in DECLARE stmt */
+
+     strcpy(msg, "declare");
+     exec sql declare :curname2 cursor for
+         select id, t into :id, :t from t1;
+
+     strcpy(msg, "open");
+     exec sql open :curname2;
+
+     strcpy(msg, "fetch from");
+     exec sql fetch from :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     exec sql fetch :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     exec sql fetch 1 from :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     exec sql fetch :count from :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     exec sql move absolute 0 :curname2;
+
+     strcpy(msg, "fetch 1");
+     exec sql fetch 1 :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     exec sql fetch :count :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     exec sql close :curname2;
+
+     /* Dynamic cursorname test with PREPARED stmt */
+
+     strcpy(msg, "prepare");
+     exec sql prepare st_id1 from :stmt1;
+
+     strcpy(msg, "declare");
+     exec sql declare :curname3 cursor for st_id1;
+
+     strcpy(msg, "open");
+     exec sql open :curname3;
+
+     strcpy(msg, "fetch from");
+     exec sql fetch from :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     exec sql fetch :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     exec sql fetch 1 from :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     exec sql fetch :count from :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     exec sql move absolute 0 :curname3;
+
+     strcpy(msg, "fetch 1");
+     exec sql fetch 1 :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     exec sql fetch :count :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     exec sql close :curname3;
+
+     strcpy(msg, "deallocate prepare");
+     exec sql deallocate prepare st_id1;
+
+     /* Dynamic cursorname test with PREPARED stmt,
+        cursor name in varchar */
+
+     curname4.len = strlen(CURNAME);
+     strcpy(curname4.arr, CURNAME);
+
+     strcpy(msg, "prepare");
+     exec sql prepare st_id2 from :stmt1;
+
+     strcpy(msg, "declare");
+     exec sql declare :curname4 cursor for st_id2;
+
+     strcpy(msg, "open");
+     exec sql open :curname4;
+
+     strcpy(msg, "fetch from");
+     exec sql fetch from :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     exec sql fetch :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     exec sql fetch 1 from :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     exec sql fetch :count from :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     exec sql move absolute 0 :curname4;
+
+     strcpy(msg, "fetch 1");
+     exec sql fetch 1 :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     exec sql fetch :count :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     exec sql close :curname4;
+
+     strcpy(msg, "deallocate prepare");
+     exec sql deallocate prepare st_id2;
+
+     /* End test */
+
+     strcpy(msg, "drop");
+     exec sql drop table t1;
+
+     strcpy(msg, "commit");
+     exec sql commit;
+
+     strcpy(msg, "disconnect");
+     exec sql disconnect;
+
+     return (0);
+ }
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/compat_informix/Makefile
pgsql.regressiontests/src/interfaces/ecpg/test/compat_informix/Makefile
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/compat_informix/Makefile    2006-09-19 17:36:08.000000000 +0200
--- pgsql.regressiontests/src/interfaces/ecpg/test/compat_informix/Makefile    2009-10-03 02:11:20.000000000 +0200
*************** override LIBS := -lecpg_compat $(LIBS)
*** 12,17 ****
--- 12,18 ----

  TESTS = test_informix test_informix.c \
          test_informix2 test_informix2.c \
+         cursor cursor.c \
          dec_test dec_test.c \
          rfmtdate rfmtdate.c \
          rfmtlong rfmtlong.c \
*************** test_informix.c: test_informix.pgc ../re
*** 26,31 ****
--- 27,35 ----
  test_informix2.c: test_informix2.pgc ../regression.h
      $(ECPG) -o $@ -I$(srcdir) $<

+ cursor.c: cursor.pgc ../regression.h
+     $(ECPG) -o $@ -I$(srcdir) $<
+
  dec_test.c: dec_test.pgc ../regression.h
      $(ECPG) -o $@ -I$(srcdir) $<

diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/ecpg_schedule
pgsql.regressiontests/src/interfaces/ecpg/test/ecpg_schedule
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/ecpg_schedule    2008-10-29 11:40:29.000000000 +0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/ecpg_schedule    2009-10-03 02:11:20.000000000 +0200
*************** test: compat_informix/charfuncs
*** 3,8 ****
--- 3,9 ----
  test: compat_informix/rfmtdate
  test: compat_informix/rfmtlong
  test: compat_informix/rnull
+ test: compat_informix/cursor
  test: compat_informix/test_informix
  test: compat_informix/test_informix2
  test: connect/test2
*************** test: pgtypeslib/num_test2
*** 16,21 ****
--- 17,23 ----
  test: preproc/array_of_struct
  test: preproc/autoprep
  test: preproc/comment
+ test: preproc/cursor
  test: preproc/define
  test: preproc/init
  test: preproc/strings
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/ecpg_schedule_tcp
pgsql.regressiontests/src/interfaces/ecpg/test/ecpg_schedule_tcp
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/ecpg_schedule_tcp    2008-10-29 11:40:29.000000000 +0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/ecpg_schedule_tcp    2009-10-03 02:11:20.000000000 +0200
*************** test: compat_informix/charfuncs
*** 3,8 ****
--- 3,9 ----
  test: compat_informix/rfmtdate
  test: compat_informix/rfmtlong
  test: compat_informix/rnull
+ test: compat_informix/cursor
  test: compat_informix/test_informix
  test: compat_informix/test_informix2
  test: connect/test2
*************** test: pgtypeslib/num_test2
*** 16,21 ****
--- 17,23 ----
  test: preproc/array_of_struct
  test: preproc/autoprep
  test: preproc/comment
+ test: preproc/cursor
  test: preproc/define
  test: preproc/init
  test: preproc/strings
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/compat_informix-cursor.c
pgsql.regressiontests/src/interfaces/ecpg/test/expected/compat_informix-cursor.c
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/compat_informix-cursor.c    1970-01-01 01:00:00.000000000
+0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/expected/compat_informix-cursor.c    2009-10-03 02:11:20.000000000
+0200
***************
*** 0 ****
--- 1,766 ----
+ /* Processed by ecpg (regression mode) */
+ /* These include files are added by the preprocessor */
+ #include <ecpglib.h>
+ #include <ecpgerrno.h>
+ #include <sqlca.h>
+ /* Needed for informix compatibility */
+ #include <ecpg_informix.h>
+ /* End of automatic include section */
+ #define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+
+ #line 1 "cursor.pgc"
+ #include <stdlib.h>
+ #include <string.h>
+
+
+ #line 1 "regression.h"
+
+
+
+
+
+
+ #line 4 "cursor.pgc"
+
+
+ /* exec sql whenever sqlerror  stop ; */
+ #line 6 "cursor.pgc"
+
+
+ /* exec sql type c is char reference */
+ #line 8 "cursor.pgc"
+
+ typedef char* c;
+
+ /* exec sql type ind is union {
+ #line 11 "cursor.pgc"
+  int integer ;
+
+ #line 11 "cursor.pgc"
+  short smallint ;
+  } */
+ #line 11 "cursor.pgc"
+
+ typedef union { int integer; short smallint; } ind;
+
+ #define BUFFERSIZ 8
+ /* exec sql type str is [ BUFFERSIZ ] */
+ #line 15 "cursor.pgc"
+
+
+ #define CURNAME "mycur"
+
+ int
+ main (void)
+ {
+ /* exec sql begin declare section */
+
+
+
+
+
+
+
+
+
+ #line 23 "cursor.pgc"
+  char * stmt1 = "SELECT id, t FROM t1" ;
+
+ #line 24 "cursor.pgc"
+  char * curname1 = CURNAME ;
+
+ #line 25 "cursor.pgc"
+  char * curname2 = CURNAME ;
+
+ #line 26 "cursor.pgc"
+  char * curname3 = CURNAME ;
+
+ #line 27 "cursor.pgc"
+   struct varchar_curname4_27  { int len; char arr[ 50 ]; }  curname4 ;
+
+ #line 28 "cursor.pgc"
+  int count ;
+
+ #line 29 "cursor.pgc"
+  int id ;
+
+ #line 30 "cursor.pgc"
+  char t [ 64 ] ;
+ /* exec sql end declare section */
+ #line 31 "cursor.pgc"
+
+
+     char msg[128];
+
+     ECPGdebug(1, stderr);
+
+     strcpy(msg, "connect");
+     { ECPGconnect(__LINE__, 1, "regress1" , NULL, NULL , NULL, 0);
+ #line 38 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 38 "cursor.pgc"
+
+
+     strcpy(msg, "set");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "set datestyle to iso", ECPGt_EOIT, ECPGt_EORT);
+ #line 41 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 41 "cursor.pgc"
+
+
+     strcpy(msg, "create");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "create table t1 ( id serial primary key , t text )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 44 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 44 "cursor.pgc"
+
+
+     strcpy(msg, "insert");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into t1 ( id , t ) values ( default , 'a' )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 47 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 47 "cursor.pgc"
+
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into t1 ( id , t ) values ( default , 'b' )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 48 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 48 "cursor.pgc"
+
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into t1 ( id , t ) values ( default , 'c' )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 49 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 49 "cursor.pgc"
+
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "insert into t1 ( id , t ) values ( default , 'd' )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 50 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 50 "cursor.pgc"
+
+
+     strcpy(msg, "commit");
+     { ECPGtrans(__LINE__, NULL, "commit");
+ #line 53 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 53 "cursor.pgc"
+
+
+     /* Dynamic cursorname test with INTO list in FETCH stmts */
+
+     strcpy(msg, "declare");
+     ECPG_informix_set_var( 0, &( curname1 ), __LINE__);\
+  ECPG_informix_reset_sqlca(); /* declare $0 cursor for select id , t from t1 */
+ #line 59 "cursor.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare $0 cursor for select id , t from t1",
+     ECPGt_char,&(*( char  *)(ECPG_informix_get_var( 0))),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 62 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 62 "cursor.pgc"
+
+
+     strcpy(msg, "fetch from");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch from $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 65 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 65 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 69 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 69 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 from $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 73 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 73 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0 from $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 78 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 78 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move in");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "move absolute 0 in $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 82 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 82 "cursor.pgc"
+
+
+     strcpy(msg, "fetch 1");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 85 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 85 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0 $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 90 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 90 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "close $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 94 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 94 "cursor.pgc"
+
+
+     /* Dynamic cursorname test with INTO list in DECLARE stmt */
+
+     strcpy(msg, "declare");
+     ECPG_informix_set_var( 3, &( curname2 ), __LINE__);\
+  ECPG_informix_set_var( 1, ( t ), __LINE__);\
+  ECPG_informix_set_var( 2, &( id ), __LINE__);\
+  ECPG_informix_reset_sqlca(); /* declare $0 cursor for select id , t from t1 */
+ #line 100 "cursor.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare $0 cursor for select id , t from t1",
+     ECPGt_char,&(*( char  *)(ECPG_informix_get_var( 3))),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(*( int  *)(ECPG_informix_get_var( 2))),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(( char  *)(ECPG_informix_get_var( 1))),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 103 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 103 "cursor.pgc"
+
+
+     strcpy(msg, "fetch from");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch from $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(*( int  *)(ECPG_informix_get_var( 2))),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(( char  *)(ECPG_informix_get_var( 1))),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 106 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 106 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(*( int  *)(ECPG_informix_get_var( 2))),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(( char  *)(ECPG_informix_get_var( 1))),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 110 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 110 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 from $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(*( int  *)(ECPG_informix_get_var( 2))),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(( char  *)(ECPG_informix_get_var( 1))),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 114 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 114 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0 from $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(*( int  *)(ECPG_informix_get_var( 2))),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(( char  *)(ECPG_informix_get_var( 1))),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 119 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 119 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "move absolute 0 $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(*( int  *)(ECPG_informix_get_var( 2))),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(( char  *)(ECPG_informix_get_var( 1))),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 123 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 123 "cursor.pgc"
+
+
+     strcpy(msg, "fetch 1");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(*( int  *)(ECPG_informix_get_var( 2))),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(( char  *)(ECPG_informix_get_var( 1))),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 126 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 126 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0 $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(*( int  *)(ECPG_informix_get_var( 2))),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(( char  *)(ECPG_informix_get_var( 1))),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 131 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 131 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "close $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 135 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 135 "cursor.pgc"
+
+
+     /* Dynamic cursorname test with PREPARED stmt */
+
+     strcpy(msg, "prepare");
+     { ECPGprepare(__LINE__, NULL, 0, "st_id1", stmt1);
+ #line 140 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 140 "cursor.pgc"
+
+
+     strcpy(msg, "declare");
+     ECPG_informix_reset_sqlca(); /* declare $0 cursor for $1 */
+ #line 143 "cursor.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare $0 cursor for $1",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id1", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 146 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 146 "cursor.pgc"
+
+
+     strcpy(msg, "fetch from");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch from $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 149 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 149 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 153 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 153 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 from $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 157 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 157 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0 from $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 162 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 162 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "move absolute 0 $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 166 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 166 "cursor.pgc"
+
+
+     strcpy(msg, "fetch 1");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 169 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 169 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0 $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 174 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 174 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "close $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 178 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 178 "cursor.pgc"
+
+
+     strcpy(msg, "deallocate prepare");
+     { ECPGdeallocate(__LINE__, 1, NULL, "st_id1");
+ #line 181 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 181 "cursor.pgc"
+
+
+     /* Dynamic cursorname test with PREPARED stmt,
+        cursor name in varchar */
+
+     curname4.len = strlen(CURNAME);
+     strcpy(curname4.arr, CURNAME);
+
+     strcpy(msg, "prepare");
+     { ECPGprepare(__LINE__, NULL, 0, "st_id2", stmt1);
+ #line 190 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 190 "cursor.pgc"
+
+
+     strcpy(msg, "declare");
+     ECPG_informix_reset_sqlca(); /* declare $0 cursor for $1 */
+ #line 193 "cursor.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare $0 cursor for $1",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id2", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 196 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 196 "cursor.pgc"
+
+
+     strcpy(msg, "fetch from");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch from $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 199 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 199 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 203 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 203 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 from $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 207 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 207 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0 from $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 212 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 212 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "move absolute 0 $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 216 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 216 "cursor.pgc"
+
+
+     strcpy(msg, "fetch 1");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch 1 $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 219 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 219 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "fetch $0 $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 224 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 224 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "close $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 228 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 228 "cursor.pgc"
+
+
+     strcpy(msg, "deallocate prepare");
+     { ECPGdeallocate(__LINE__, 1, NULL, "st_id2");
+ #line 231 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 231 "cursor.pgc"
+
+
+     /* End test */
+
+     strcpy(msg, "drop");
+     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "drop table t1", ECPGt_EOIT, ECPGt_EORT);
+ #line 236 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 236 "cursor.pgc"
+
+
+     strcpy(msg, "commit");
+     { ECPGtrans(__LINE__, NULL, "commit");
+ #line 239 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 239 "cursor.pgc"
+
+
+     strcpy(msg, "disconnect");
+     { ECPGdisconnect(__LINE__, "CURRENT");
+ #line 242 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 242 "cursor.pgc"
+
+
+     return (0);
+ }
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/compat_informix-cursor.stderr
pgsql.regressiontests/src/interfaces/ecpg/test/expected/compat_informix-cursor.stderr
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/compat_informix-cursor.stderr    1970-01-01
01:00:00.000000000+0100 
--- pgsql.regressiontests/src/interfaces/ecpg/test/expected/compat_informix-cursor.stderr    2009-10-03
02:11:20.000000000+0200 
***************
*** 0 ****
--- 1,372 ----
+ [NO_PID]: ECPGdebug: set to 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGconnect: opening database regress1 on <DEFAULT> port <DEFAULT>
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 41: query: set datestyle to iso; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 41: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 41: OK: SET
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 44: query: create table t1 ( id serial primary key , t text ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 44: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 44: OK: CREATE TABLE
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 47: query: insert into t1 ( id , t ) values ( default , 'a' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 47: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 47: OK: INSERT 0 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 48: query: insert into t1 ( id , t ) values ( default , 'b' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 48: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 48: OK: INSERT 0 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 49: query: insert into t1 ( id , t ) values ( default , 'c' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 49: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 49: OK: INSERT 0 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 50: query: insert into t1 ( id , t ) values ( default , 'd' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 50: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 50: OK: INSERT 0 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGtrans on line 53: action "commit"; connection "regress1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 62: query: declare mycur cursor for select id , t from t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 62: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 62: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 65: query: fetch from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 65: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 65: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 65: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 65: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 69: query: fetch mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 69: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 69: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 69: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 69: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 73: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 73: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 73: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 73: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 73: RESULT: c offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 78: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 78: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 78: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 78: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 78: RESULT: d offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 82: query: move absolute 0 in mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 82: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 82: OK: MOVE 0
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 85: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 85: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 85: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 85: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 85: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 90: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 90: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 90: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 90: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 90: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 94: query: close mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 94: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 94: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: query: declare mycur cursor for select id , t from t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 106: query: fetch from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 106: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 106: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 106: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 106: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 110: query: fetch mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 110: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 110: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 110: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 110: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 114: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 114: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 114: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 114: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 114: RESULT: c offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 119: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 119: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 119: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 119: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 119: RESULT: d offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 123: query: move absolute 0 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 123: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 123: OK: MOVE 0
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 126: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 126: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 126: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 126: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 126: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 131: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 131: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 131: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 131: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 131: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 135: query: close mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 135: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 135: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGprepare on line 140: name st_id1; query: "SELECT id, t FROM t1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 146: query: declare mycur cursor for SELECT id, t FROM t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 146: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 146: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 149: query: fetch from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 149: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 149: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 149: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 149: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 153: query: fetch mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 153: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 153: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 153: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 153: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 157: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 157: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 157: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 157: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 157: RESULT: c offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 162: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 162: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 162: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 162: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 162: RESULT: d offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 166: query: move absolute 0 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 166: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 166: OK: MOVE 0
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 169: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 169: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 169: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 169: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 169: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 174: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 174: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 174: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 174: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 174: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 178: query: close mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 178: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 178: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGdeallocate on line 181: name st_id1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGprepare on line 190: name st_id2; query: "SELECT id, t FROM t1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 196: query: declare mycur cursor for SELECT id, t FROM t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 196: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 196: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 199: query: fetch from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 199: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 199: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 199: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 199: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 203: query: fetch mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 203: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 203: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 203: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 203: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 207: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 207: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 207: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 207: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 207: RESULT: c offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 212: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 212: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 212: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 212: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 212: RESULT: d offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 216: query: move absolute 0 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 216: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 216: OK: MOVE 0
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 219: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 219: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 219: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 219: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 219: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 224: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 224: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 224: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 224: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 224: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 228: query: close mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 228: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 228: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGdeallocate on line 231: name st_id2
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 236: query: drop table t1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 236: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 236: OK: DROP TABLE
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGtrans on line 239: action "commit"; connection "regress1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_finish: connection regress1 closed
+ [NO_PID]: sqlca: code: 0, state: 00000
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/compat_informix-cursor.stdout
pgsql.regressiontests/src/interfaces/ecpg/test/expected/compat_informix-cursor.stdout
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/compat_informix-cursor.stdout    1970-01-01
01:00:00.000000000+0100 
--- pgsql.regressiontests/src/interfaces/ecpg/test/expected/compat_informix-cursor.stdout    2009-10-03
02:11:20.000000000+0200 
***************
*** 0 ****
--- 1,24 ----
+ 1 a
+ 2 b
+ 3 c
+ 4 d
+ 1 a
+ 2 b
+ 1 a
+ 2 b
+ 3 c
+ 4 d
+ 1 a
+ 2 b
+ 1 a
+ 2 b
+ 3 c
+ 4 d
+ 1 a
+ 2 b
+ 1 a
+ 2 b
+ 3 c
+ 4 d
+ 1 a
+ 2 b
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/preproc-cursor.c
pgsql.regressiontests/src/interfaces/ecpg/test/expected/preproc-cursor.c
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/preproc-cursor.c    1970-01-01 01:00:00.000000000 +0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/expected/preproc-cursor.c    2009-10-03 02:11:20.000000000 +0200
***************
*** 0 ****
--- 1,760 ----
+ /* Processed by ecpg (regression mode) */
+ /* These include files are added by the preprocessor */
+ #include <ecpglib.h>
+ #include <ecpgerrno.h>
+ #include <sqlca.h>
+ /* End of automatic include section */
+ #define ECPGdebug(X,Y) ECPGdebug((X)+100,(Y))
+
+ #line 1 "cursor.pgc"
+ #include <stdlib.h>
+ #include <string.h>
+
+
+ #line 1 "regression.h"
+
+
+
+
+
+
+ #line 4 "cursor.pgc"
+
+
+ /* exec sql whenever sqlerror  stop ; */
+ #line 6 "cursor.pgc"
+
+
+ /* exec sql type c is char reference */
+ #line 8 "cursor.pgc"
+
+ typedef char* c;
+
+ /* exec sql type ind is union {
+ #line 11 "cursor.pgc"
+  int integer ;
+
+ #line 11 "cursor.pgc"
+  short smallint ;
+  } */
+ #line 11 "cursor.pgc"
+
+ typedef union { int integer; short smallint; } ind;
+
+ #define BUFFERSIZ 8
+ /* exec sql type str is [ BUFFERSIZ ] */
+ #line 15 "cursor.pgc"
+
+
+ #define CURNAME "mycur"
+
+ int
+ main (void)
+ {
+ /* exec sql begin declare section */
+
+
+
+
+
+
+
+
+
+ #line 23 "cursor.pgc"
+  char * stmt1 = "SELECT id, t FROM t1" ;
+
+ #line 24 "cursor.pgc"
+  char * curname1 = CURNAME ;
+
+ #line 25 "cursor.pgc"
+  char * curname2 = CURNAME ;
+
+ #line 26 "cursor.pgc"
+  char * curname3 = CURNAME ;
+
+ #line 27 "cursor.pgc"
+   struct varchar_curname4_27  { int len; char arr[ 50 ]; }  curname4 ;
+
+ #line 28 "cursor.pgc"
+  int count ;
+
+ #line 29 "cursor.pgc"
+  int id ;
+
+ #line 30 "cursor.pgc"
+  char t [ 64 ] ;
+ /* exec sql end declare section */
+ #line 31 "cursor.pgc"
+
+
+     char msg[128];
+
+     ECPGdebug(1, stderr);
+
+     strcpy(msg, "connect");
+     { ECPGconnect(__LINE__, 0, "regress1" , NULL, NULL , NULL, 0);
+ #line 38 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 38 "cursor.pgc"
+
+
+     strcpy(msg, "set");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "set datestyle to iso", ECPGt_EOIT, ECPGt_EORT);
+ #line 41 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 41 "cursor.pgc"
+
+
+     strcpy(msg, "create");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "create table t1 ( id serial primary key , t text )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 44 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 44 "cursor.pgc"
+
+
+     strcpy(msg, "insert");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 ( id , t ) values ( default , 'a' )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 47 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 47 "cursor.pgc"
+
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 ( id , t ) values ( default , 'b' )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 48 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 48 "cursor.pgc"
+
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 ( id , t ) values ( default , 'c' )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 49 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 49 "cursor.pgc"
+
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "insert into t1 ( id , t ) values ( default , 'd' )",
ECPGt_EOIT,ECPGt_EORT); 
+ #line 50 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 50 "cursor.pgc"
+
+
+     strcpy(msg, "commit");
+     { ECPGtrans(__LINE__, NULL, "commit");
+ #line 53 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 53 "cursor.pgc"
+
+
+     /* Dynamic cursorname test with INTO list in FETCH stmts */
+
+     strcpy(msg, "declare");
+     /* declare $0 cursor for select id , t from t1 */
+ #line 59 "cursor.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare $0 cursor for select id , t from t1",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 62 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 62 "cursor.pgc"
+
+
+     strcpy(msg, "fetch from");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch from $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 65 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 65 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 69 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 69 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 from $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 73 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 73 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 from $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 78 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 78 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move in");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "move absolute 0 in $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 82 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 82 "cursor.pgc"
+
+
+     strcpy(msg, "fetch 1");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 85 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 85 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 90 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 90 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close $0",
+     ECPGt_char,&(curname1),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 94 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 94 "cursor.pgc"
+
+
+     /* Dynamic cursorname test with INTO list in DECLARE stmt */
+
+     strcpy(msg, "declare");
+     /* declare $0 cursor for select id , t from t1 */
+ #line 100 "cursor.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare $0 cursor for select id , t from t1",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 103 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 103 "cursor.pgc"
+
+
+     strcpy(msg, "fetch from");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch from $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 106 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 106 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 110 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 110 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 from $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 114 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 114 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 from $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 119 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 119 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "move absolute 0 $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 123 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 123 "cursor.pgc"
+
+
+     strcpy(msg, "fetch 1");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 126 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 126 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 131 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 131 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close $0",
+     ECPGt_char,&(curname2),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 135 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 135 "cursor.pgc"
+
+
+     /* Dynamic cursorname test with PREPARED stmt */
+
+     strcpy(msg, "prepare");
+     { ECPGprepare(__LINE__, NULL, 0, "st_id1", stmt1);
+ #line 140 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 140 "cursor.pgc"
+
+
+     strcpy(msg, "declare");
+     /* declare $0 cursor for $1 */
+ #line 143 "cursor.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare $0 cursor for $1",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id1", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 146 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 146 "cursor.pgc"
+
+
+     strcpy(msg, "fetch from");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch from $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 149 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 149 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 153 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 153 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 from $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 157 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 157 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 from $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 162 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 162 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "move absolute 0 $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 166 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 166 "cursor.pgc"
+
+
+     strcpy(msg, "fetch 1");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 169 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 169 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 174 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 174 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close $0",
+     ECPGt_char,&(curname3),(long)0,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 178 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 178 "cursor.pgc"
+
+
+     strcpy(msg, "deallocate prepare");
+     { ECPGdeallocate(__LINE__, 0, NULL, "st_id1");
+ #line 181 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 181 "cursor.pgc"
+
+
+     /* Dynamic cursorname test with PREPARED stmt,
+        cursor name in varchar */
+
+     curname4.len = strlen(CURNAME);
+     strcpy(curname4.arr, CURNAME);
+
+     strcpy(msg, "prepare");
+     { ECPGprepare(__LINE__, NULL, 0, "st_id2", stmt1);
+ #line 190 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 190 "cursor.pgc"
+
+
+     strcpy(msg, "declare");
+     /* declare $0 cursor for $1 */
+ #line 193 "cursor.pgc"
+
+
+     strcpy(msg, "open");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "declare $0 cursor for $1",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char_variable,(ECPGprepared_statement(NULL, "st_id2", __LINE__)),(long)1,(long)1,(1)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 196 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 196 "cursor.pgc"
+
+
+     strcpy(msg, "fetch from");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch from $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 199 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 199 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 203 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 203 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 from $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 207 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 207 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 from $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 212 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 212 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "move absolute 0 $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 216 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 216 "cursor.pgc"
+
+
+     strcpy(msg, "fetch 1");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch 1 $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 219 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 219 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "fetch $0 $0",
+     ECPGt_int,&(count),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
+     ECPGt_int,&(id),(long)1,(long)1,sizeof(int),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L,
+     ECPGt_char,(t),(long)64,(long)1,(64)*sizeof(char),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
+ #line 224 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 224 "cursor.pgc"
+
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "close $0",
+     ECPGt_varchar,&(curname4),(long)50,(long)1,sizeof(struct varchar_curname4_27),
+     ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT, ECPGt_EORT);
+ #line 228 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 228 "cursor.pgc"
+
+
+     strcpy(msg, "deallocate prepare");
+     { ECPGdeallocate(__LINE__, 0, NULL, "st_id2");
+ #line 231 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 231 "cursor.pgc"
+
+
+     /* End test */
+
+     strcpy(msg, "drop");
+     { ECPGdo(__LINE__, 0, 1, NULL, 0, ECPGst_normal, "drop table t1", ECPGt_EOIT, ECPGt_EORT);
+ #line 236 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 236 "cursor.pgc"
+
+
+     strcpy(msg, "commit");
+     { ECPGtrans(__LINE__, NULL, "commit");
+ #line 239 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 239 "cursor.pgc"
+
+
+     strcpy(msg, "disconnect");
+     { ECPGdisconnect(__LINE__, "CURRENT");
+ #line 242 "cursor.pgc"
+
+ if (sqlca.sqlcode < 0) exit (1);}
+ #line 242 "cursor.pgc"
+
+
+     return (0);
+ }
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/preproc-cursor.stderr
pgsql.regressiontests/src/interfaces/ecpg/test/expected/preproc-cursor.stderr
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/preproc-cursor.stderr    1970-01-01 01:00:00.000000000
+0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/expected/preproc-cursor.stderr    2009-10-03 02:11:20.000000000
+0200
***************
*** 0 ****
--- 1,372 ----
+ [NO_PID]: ECPGdebug: set to 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGconnect: opening database regress1 on <DEFAULT> port <DEFAULT>
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 41: query: set datestyle to iso; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 41: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 41: OK: SET
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 44: query: create table t1 ( id serial primary key , t text ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 44: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 44: OK: CREATE TABLE
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 47: query: insert into t1 ( id , t ) values ( default , 'a' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 47: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 47: OK: INSERT 0 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 48: query: insert into t1 ( id , t ) values ( default , 'b' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 48: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 48: OK: INSERT 0 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 49: query: insert into t1 ( id , t ) values ( default , 'c' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 49: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 49: OK: INSERT 0 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 50: query: insert into t1 ( id , t ) values ( default , 'd' ); with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 50: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 50: OK: INSERT 0 1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGtrans on line 53: action "commit"; connection "regress1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 62: query: declare mycur cursor for select id , t from t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 62: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 62: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 65: query: fetch from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 65: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 65: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 65: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 65: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 69: query: fetch mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 69: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 69: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 69: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 69: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 73: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 73: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 73: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 73: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 73: RESULT: c offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 78: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 78: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 78: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 78: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 78: RESULT: d offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 82: query: move absolute 0 in mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 82: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 82: OK: MOVE 0
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 85: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 85: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 85: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 85: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 85: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 90: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 90: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 90: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 90: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 90: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 94: query: close mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 94: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 94: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: query: declare mycur cursor for select id , t from t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 103: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 106: query: fetch from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 106: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 106: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 106: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 106: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 110: query: fetch mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 110: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 110: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 110: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 110: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 114: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 114: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 114: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 114: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 114: RESULT: c offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 119: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 119: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 119: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 119: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 119: RESULT: d offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 123: query: move absolute 0 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 123: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 123: OK: MOVE 0
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 126: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 126: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 126: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 126: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 126: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 131: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 131: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 131: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 131: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 131: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 135: query: close mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 135: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 135: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGprepare on line 140: name st_id1; query: "SELECT id, t FROM t1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 146: query: declare mycur cursor for SELECT id, t FROM t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 146: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 146: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 149: query: fetch from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 149: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 149: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 149: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 149: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 153: query: fetch mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 153: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 153: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 153: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 153: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 157: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 157: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 157: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 157: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 157: RESULT: c offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 162: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 162: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 162: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 162: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 162: RESULT: d offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 166: query: move absolute 0 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 166: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 166: OK: MOVE 0
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 169: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 169: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 169: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 169: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 169: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 174: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 174: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 174: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 174: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 174: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 178: query: close mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 178: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 178: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGdeallocate on line 181: name st_id1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGprepare on line 190: name st_id2; query: "SELECT id, t FROM t1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 196: query: declare mycur cursor for SELECT id, t FROM t1; with 0 parameter(s) on
connectionregress1 
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 196: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 196: OK: DECLARE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 199: query: fetch from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 199: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 199: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 199: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 199: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 203: query: fetch mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 203: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 203: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 203: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 203: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 207: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 207: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 207: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 207: RESULT: 3 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 207: RESULT: c offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 212: query: fetch 1 from mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 212: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 212: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 212: RESULT: 4 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 212: RESULT: d offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 216: query: move absolute 0 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 216: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 216: OK: MOVE 0
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 219: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 219: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 219: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 219: RESULT: 1 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 219: RESULT: a offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 224: query: fetch 1 mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 224: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 224: correctly got 1 tuples with 2 fields
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 224: RESULT: 2 offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_get_data on line 224: RESULT: b offset: -1; array: yes
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 228: query: close mycur; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 228: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 228: OK: CLOSE CURSOR
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGdeallocate on line 231: name st_id2
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 236: query: drop table t1; with 0 parameter(s) on connection regress1
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 236: using PQexec
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_execute on line 236: OK: DROP TABLE
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ECPGtrans on line 239: action "commit"; connection "regress1"
+ [NO_PID]: sqlca: code: 0, state: 00000
+ [NO_PID]: ecpg_finish: connection regress1 closed
+ [NO_PID]: sqlca: code: 0, state: 00000
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/preproc-cursor.stdout
pgsql.regressiontests/src/interfaces/ecpg/test/expected/preproc-cursor.stdout
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/expected/preproc-cursor.stdout    1970-01-01 01:00:00.000000000
+0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/expected/preproc-cursor.stdout    2009-10-03 02:11:20.000000000
+0200
***************
*** 0 ****
--- 1,24 ----
+ 1 a
+ 2 b
+ 3 c
+ 4 d
+ 1 a
+ 2 b
+ 1 a
+ 2 b
+ 3 c
+ 4 d
+ 1 a
+ 2 b
+ 1 a
+ 2 b
+ 3 c
+ 4 d
+ 1 a
+ 2 b
+ 1 a
+ 2 b
+ 3 c
+ 4 d
+ 1 a
+ 2 b
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/preproc/cursor.pgc
pgsql.regressiontests/src/interfaces/ecpg/test/preproc/cursor.pgc
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/preproc/cursor.pgc    1970-01-01 01:00:00.000000000 +0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/preproc/cursor.pgc    2009-10-03 02:11:20.000000000 +0200
***************
*** 0 ****
--- 1,245 ----
+ #include <stdlib.h>
+ #include <string.h>
+
+ exec sql include ../regression;
+
+ exec sql whenever sqlerror stop;
+
+ exec sql type c is char reference;
+ typedef char* c;
+
+ exec sql type ind is union { int integer; short smallint; };
+ typedef union { int integer; short smallint; } ind;
+
+ #define BUFFERSIZ 8
+ exec sql type str is varchar[BUFFERSIZ];
+
+ #define CURNAME "mycur"
+
+ int
+ main (void)
+ {
+ exec sql begin declare section;
+     char    *stmt1 = "SELECT id, t FROM t1";
+     char    *curname1 = CURNAME;
+     char    *curname2 = CURNAME;
+     char    *curname3 = CURNAME;
+     varchar    curname4[50];
+     int    count;
+     int    id;
+     char    t[64];
+ exec sql end declare section;
+
+     char msg[128];
+
+     ECPGdebug(1, stderr);
+
+     strcpy(msg, "connect");
+     exec sql connect to REGRESSDB1;
+
+     strcpy(msg, "set");
+     exec sql set datestyle to iso;
+
+     strcpy(msg, "create");
+     exec sql create table t1(id serial primary key, t text);
+
+     strcpy(msg, "insert");
+     exec sql insert into t1(id, t) values (default, 'a');
+     exec sql insert into t1(id, t) values (default, 'b');
+     exec sql insert into t1(id, t) values (default, 'c');
+     exec sql insert into t1(id, t) values (default, 'd');
+
+     strcpy(msg, "commit");
+     exec sql commit;
+
+     /* Dynamic cursorname test with INTO list in FETCH stmts */
+
+     strcpy(msg, "declare");
+     exec sql declare :curname1 cursor for
+         select id, t from t1;
+
+     strcpy(msg, "open");
+     exec sql open :curname1;
+
+     strcpy(msg, "fetch from");
+     exec sql fetch from :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     exec sql fetch :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     exec sql fetch 1 from :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     exec sql fetch :count from :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move in");
+     exec sql move absolute 0 in :curname1;
+
+     strcpy(msg, "fetch 1");
+     exec sql fetch 1 :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     exec sql fetch :count :curname1 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     exec sql close :curname1;
+
+     /* Dynamic cursorname test with INTO list in DECLARE stmt */
+
+     strcpy(msg, "declare");
+     exec sql declare :curname2 cursor for
+         select id, t into :id, :t from t1;
+
+     strcpy(msg, "open");
+     exec sql open :curname2;
+
+     strcpy(msg, "fetch from");
+     exec sql fetch from :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     exec sql fetch :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     exec sql fetch 1 from :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     exec sql fetch :count from :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     exec sql move absolute 0 :curname2;
+
+     strcpy(msg, "fetch 1");
+     exec sql fetch 1 :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     exec sql fetch :count :curname2;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     exec sql close :curname2;
+
+     /* Dynamic cursorname test with PREPARED stmt */
+
+     strcpy(msg, "prepare");
+     exec sql prepare st_id1 from :stmt1;
+
+     strcpy(msg, "declare");
+     exec sql declare :curname3 cursor for st_id1;
+
+     strcpy(msg, "open");
+     exec sql open :curname3;
+
+     strcpy(msg, "fetch from");
+     exec sql fetch from :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     exec sql fetch :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     exec sql fetch 1 from :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     exec sql fetch :count from :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     exec sql move absolute 0 :curname3;
+
+     strcpy(msg, "fetch 1");
+     exec sql fetch 1 :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     exec sql fetch :count :curname3 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     exec sql close :curname3;
+
+     strcpy(msg, "deallocate prepare");
+     exec sql deallocate prepare st_id1;
+
+     /* Dynamic cursorname test with PREPARED stmt,
+        cursor name in varchar */
+
+     curname4.len = strlen(CURNAME);
+     strcpy(curname4.arr, CURNAME);
+
+     strcpy(msg, "prepare");
+     exec sql prepare st_id2 from :stmt1;
+
+     strcpy(msg, "declare");
+     exec sql declare :curname4 cursor for st_id2;
+
+     strcpy(msg, "open");
+     exec sql open :curname4;
+
+     strcpy(msg, "fetch from");
+     exec sql fetch from :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch");
+     exec sql fetch :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch 1 from");
+     exec sql fetch 1 from :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count from");
+     count = 1;
+     exec sql fetch :count from :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "move");
+     exec sql move absolute 0 :curname4;
+
+     strcpy(msg, "fetch 1");
+     exec sql fetch 1 :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "fetch :count");
+     count = 1;
+     exec sql fetch :count :curname4 into :id, :t;
+     printf("%d %s\n", id, t);
+
+     strcpy(msg, "close");
+     exec sql close :curname4;
+
+     strcpy(msg, "deallocate prepare");
+     exec sql deallocate prepare st_id2;
+
+     /* End test */
+
+     strcpy(msg, "drop");
+     exec sql drop table t1;
+
+     strcpy(msg, "commit");
+     exec sql commit;
+
+     strcpy(msg, "disconnect");
+     exec sql disconnect;
+
+     return (0);
+ }
diff -dcrpN pgsql.cname_in_varchar/src/interfaces/ecpg/test/preproc/Makefile
pgsql.regressiontests/src/interfaces/ecpg/test/preproc/Makefile
*** pgsql.cname_in_varchar/src/interfaces/ecpg/test/preproc/Makefile    2008-10-29 11:40:29.000000000 +0100
--- pgsql.regressiontests/src/interfaces/ecpg/test/preproc/Makefile    2009-10-03 02:11:20.000000000 +0200
*************** include $(top_srcdir)/$(subdir)/../Makef
*** 7,12 ****
--- 7,13 ----
  TESTS = array_of_struct array_of_struct.c \
      autoprep autoprep.c \
      comment comment.c \
+     cursor cursor.c \
      define define.c \
      init init.c \
      strings strings.c \
diff -dcrpN pgsql.regressiontests/src/interfaces/ecpg/preproc/parse.pl
pgsql.fixparsepl/src/interfaces/ecpg/preproc/parse.pl
*** pgsql.regressiontests/src/interfaces/ecpg/preproc/parse.pl    2009-10-03 01:54:56.000000000 +0200
--- pgsql.fixparsepl/src/interfaces/ecpg/preproc/parse.pl    2009-10-03 02:18:47.000000000 +0200
*************** sub include_stuff {
*** 313,318 ****
--- 313,319 ----
      local($includestream, $includefilename, $includeblock, $copy, $field_count) = @_;
      $copied = 0;
      $inblock = 0;
+     $have_addon = 0;
      $filename = $path . "/" . $includefilename;
      while (($_ = &Getline2($filename),$getline_ok)) {
      if ($includeblock ne '' && $Fld[1] eq 'ECPG:' && $inblock == 0) {
*************** sub include_stuff {
*** 321,329 ****
          $inblock = 1;
          $includetype = $Fld[3];
          if ($includetype eq 'rule') {
!             &dump_fields($stmt_mode, *fields, $field_count, ' { ');
          }
          elsif ($includetype eq 'addon') {
              &add_to_buffer('rules', ' { ');
          }
          }
--- 322,336 ----
          $inblock = 1;
          $includetype = $Fld[3];
          if ($includetype eq 'rule') {
!             if ($have_addon == 0) {
!             &dump_fields($stmt_mode, *fields, $field_count, ' { ');
!             }
!             else {
!             &dump_fields($stmt_mode, *fields, $field_count, '');
!             }
          }
          elsif ($includetype eq 'addon') {
+             $have_addon  = 1;
              &add_to_buffer('rules', ' { ');
          }
          }

Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
On Fri, Oct 2, 2009 at 9:01 PM, Boszormenyi Zoltan <zb@cybertec.at> wrote:
> Hi,
>
> Michael Meskes írta:
>> It is accepted either way. I was just pointing out that it might be easier to
>> review/commit at least parts of your patches if they can be applied seperately.
>>
>
> I have split up (and cleaned up a little) the dynamic
> cursorname patch into smaller logical, easier-to-review
> pieces. Descriptions below.
>
> 1) 1a-unified-optfromin-fetch-ctxdiff.patch
>
> ecpg supports optional FROM/IN in FETCH and
> MOVE statements (mainly because it's required by
> Informix-compatibility). Unify core and ecpg grammar
> as per Tom Lane's suggestion.
>
> 2) 1b-cursor_name-ctxdiff.patch
>
> "name" -> "cursor_name" transition in core grammar
> and ecpg grammar. Currently it does nothing, it's a
> preparation phase. Depends on patch 1.
>
> 3) 1c-remove-var-from-list.patch
>
> Introduce function remove_variable_from_list().
> It is used by the dynamic cursor, SQLDA and DESCRIBE
> patches for different reasons. Applicable separately.
>
> 4) 1d-dynamiccur-ctxdiff.patch
>
> The real point of the whole series in this email.
> Extend "cursor_name" in the ecpg grammar to actually
> accept a character variable. The cursorname-as-variable
> is replaced in the final SQL script with a $0 placeholder.
> Doesn't compile as-is, requires patch 5 to get the
> two shift/reduce conflicts fixed. Depends on patches
> 1, 2 and 3.
>
> 5) 1e-fix-shiftreduce-ctxdiff.patch
>
> De-factorize "BACKWARD opt_from_in cursor_name"
> and "FORWARD opt_from_in cursor_name" out of
> fetch_args and pull them up into FetchStmt in the ecpg
> grammar. Depends on patch 4.
> One line in parse.pl is not clear for me:
>    $replace_line{'fetch_args'} = 'ignore';
> The genarated preproc.y is the same with or without
> this line. But as the previous version had it with
> "fetch_direction", I left it in.
>
> 6) 1f-cursorname-in-varchar-ctxdiff.patch
>
> Allow that varchar can be used as cursorname as well.
> Other character variable types were already supported.
> Depends on patch 4.
>
> 7) 1g-regressiontests-ctxdiff.patch
>
> Introduce cursor.pgc regression test for both native
> and compat mode. Depends on all patches.
>
> 8) 1h-fix-parse.pl-ctxdiff.patch
>
> Now useless patch, in the previous dynamic cursorname
> patch the following scenario occured: the same rule
> had both an "addon" and a "rule" extension. Without
> this fix, the following code was generated in preproc.y:
>    ruleA: <accepted syntax>
>       {
>             <addon code block>
>       {
>             <automatic code block>
>       }
> With the cleanup I did during this splitup, this scenario
> doesn't happen, but this fix may be considered useful.
> Applicable separately.
>
> After every patch (except 4) both the core and ecpg
> "make check" are successful.

It would've been nice if you'd changed the subject line before posting these.

Also, please update commitfest.postgresql.org appropriately.

...Robert


ECPG dynamic cursorname patch revised and split Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Robert Haas írta:
> On Fri, Oct 2, 2009 at 9:01 PM, Boszormenyi Zoltan <zb@cybertec.at> wrote:
>   
>> Hi,
>>
>> Michael Meskes írta:
>>     
>>> It is accepted either way. I was just pointing out that it might be easier to
>>> review/commit at least parts of your patches if they can be applied seperately.
>>>
>>>       
>> I have split up (and cleaned up a little) the dynamic
>> cursorname patch into smaller logical, easier-to-review
>> pieces. Descriptions below.
>>
>> ...
>> After every patch (except 4) both the core and ecpg
>> "make check" are successful.
>>     
>
> It would've been nice if you'd changed the subject line before posting these.
>   

At 3am, I forgot this. :(
I hope the archive threading doesn't break and
my previous mail will be referenced by this one.

> Also, please update commitfest.postgresql.org appropriately.
>   

I just did, thanks for the reminder.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
On Thu, Oct 1, 2009 at 7:48 AM, Magnus Hagander <magnus@hagander.net> wrote:
> On Thu, Oct 1, 2009 at 04:11, Itagaki Takahiro
> <itagaki.takahiro@oss.ntt.co.jp> wrote:
>>
>> Magnus Hagander <magnus@hagander.net> wrote:
>>
>>> I can certainly review the win32 encoding patch, but I was rather
>>> hoping for some comments from others on if we're interested in a win32
>>> only solution, or if we want something more generic. Should we just go
>>> with the win32-only one for now?
>>
>> Yes, because Windows is only platform that supports UTF-16 encoding natively.
>> I believe my patch is the best solution for Windows even if we have another
>> approach for other platforms.
>
> Actually, I think a better argument is that since Windows will *never*
> accept UTF8 logging, and that's what most databases will be in, much
> of this patch will be required anyway. So I should probably review and
> get this part in while we think about other solutions *as well* for
> other platforms.

Given the above, it seems that perhaps we could go ahead and apply this?

...Robert


Re: CommitFest 2009-09, two weeks on

From
Joe Conway
Date:
Itagaki Takahiro wrote:
> The point is *memory leak* in dblink when a query is canceled or
> become time-out. I think it is a bug, and my patch could fix it.

Please see if this works for you.

Joe

Index: dblink.c
===================================================================
RCS file: /opt/src/cvs/pgsql/contrib/dblink/dblink.c,v
retrieving revision 1.84
diff -c -r1.84 dblink.c
*** dblink.c    12 Sep 2009 23:20:52 -0000    1.84
--- dblink.c    4 Oct 2009 02:19:17 -0000
***************
*** 97,109 ****
  static char *generate_relation_name(Oid relid);
  static void dblink_connstr_check(const char *connstr);
  static void dblink_security_check(PGconn *conn, remoteConn *rconn);
! static void dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail);
  static char *get_connect_string(const char *servername);
  static char *escape_param_str(const char *from);

  /* Global */
  static remoteConn *pconn = NULL;
  static HTAB *remoteConnHash = NULL;

  /*
   *    Following is list that holds multiple remote connections.
--- 97,111 ----
  static char *generate_relation_name(Oid relid);
  static void dblink_connstr_check(const char *connstr);
  static void dblink_security_check(PGconn *conn, remoteConn *rconn);
! static void dblink_res_error(const char *conname, const char *dblink_context_msg, bool fail);
  static char *get_connect_string(const char *servername);
  static char *escape_param_str(const char *from);
+ static void dblink_error_callback(void *arg);

  /* Global */
  static remoteConn *pconn = NULL;
  static HTAB *remoteConnHash = NULL;
+ static PGresult *res = NULL;

  /*
   *    Following is list that holds multiple remote connections.
***************
*** 143,149 ****
--- 145,154 ----
      do { \
              msg = pstrdup(PQerrorMessage(conn)); \
              if (res) \
+             { \
                  PQclear(res); \
+                 res = NULL; \
+             } \
              elog(ERROR, "%s: %s", p2, msg); \
      } while (0)

***************
*** 212,217 ****
--- 217,238 ----
              } \
      } while (0)

+ #define ERRORCONTEXTCALLBACK \
+     ErrorContextCallback    dberrcontext
+
+ #define PUSH_DBERRCONTEXT(_error_callback_) \
+     do { \
+         dberrcontext.callback = _error_callback_; \
+         dberrcontext.arg = (void *) NULL; \
+         dberrcontext.previous = error_context_stack; \
+         error_context_stack = &dberrcontext; \
+     } while (0)
+
+ #define POP_DBERRCONTEXT \
+     do { \
+         error_context_stack = dberrcontext.previous; \
+     } while (0)
+
  /*
   * Create a persistent connection to another database
   */
***************
*** 325,331 ****
  dblink_open(PG_FUNCTION_ARGS)
  {
      char       *msg;
-     PGresult   *res = NULL;
      PGconn       *conn = NULL;
      char       *curname = NULL;
      char       *sql = NULL;
--- 346,351 ----
***************
*** 333,339 ****
--- 353,361 ----
      StringInfoData buf;
      remoteConn *rconn = NULL;
      bool        fail = true;    /* default to backward compatible behavior */
+     ERRORCONTEXTCALLBACK;

+     PUSH_DBERRCONTEXT(dblink_error_callback);
      DBLINK_INIT;
      initStringInfo(&buf);

***************
*** 381,389 ****
      if (PQtransactionStatus(conn) == PQTRANS_IDLE)
      {
          res = PQexec(conn, "BEGIN");
!         if (PQresultStatus(res) != PGRES_COMMAND_OK)
              DBLINK_RES_INTERNALERROR("begin error");
          PQclear(res);
          rconn->newXactForCursor = TRUE;

          /*
--- 403,412 ----
      if (PQtransactionStatus(conn) == PQTRANS_IDLE)
      {
          res = PQexec(conn, "BEGIN");
!         if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
              DBLINK_RES_INTERNALERROR("begin error");
          PQclear(res);
+         res = NULL;
          rconn->newXactForCursor = TRUE;

          /*
***************
*** 402,412 ****
      res = PQexec(conn, buf.data);
      if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
      {
!         dblink_res_error(conname, res, "could not open cursor", fail);
          PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
      }
-
      PQclear(res);
      PG_RETURN_TEXT_P(cstring_to_text("OK"));
  }

--- 425,437 ----
      res = PQexec(conn, buf.data);
      if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
      {
!         dblink_res_error(conname, "could not open cursor", fail);
          PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
      }
      PQclear(res);
+     res = NULL;
+
+     POP_DBERRCONTEXT;
      PG_RETURN_TEXT_P(cstring_to_text("OK"));
  }

***************
*** 418,431 ****
  dblink_close(PG_FUNCTION_ARGS)
  {
      PGconn       *conn = NULL;
-     PGresult   *res = NULL;
      char       *curname = NULL;
      char       *conname = NULL;
      StringInfoData buf;
      char       *msg;
      remoteConn *rconn = NULL;
      bool        fail = true;    /* default to backward compatible behavior */
!
      DBLINK_INIT;
      initStringInfo(&buf);

--- 443,457 ----
  dblink_close(PG_FUNCTION_ARGS)
  {
      PGconn       *conn = NULL;
      char       *curname = NULL;
      char       *conname = NULL;
      StringInfoData buf;
      char       *msg;
      remoteConn *rconn = NULL;
      bool        fail = true;    /* default to backward compatible behavior */
!     ERRORCONTEXTCALLBACK;
!
!     PUSH_DBERRCONTEXT(dblink_error_callback);
      DBLINK_INIT;
      initStringInfo(&buf);

***************
*** 471,481 ****
      res = PQexec(conn, buf.data);
      if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
      {
!         dblink_res_error(conname, res, "could not close cursor", fail);
          PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
      }
-
      PQclear(res);

      /* if we started a transaction, decrement cursor count */
      if (rconn->newXactForCursor)
--- 497,507 ----
      res = PQexec(conn, buf.data);
      if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
      {
!         dblink_res_error(conname, "could not close cursor", fail);
          PG_RETURN_TEXT_P(cstring_to_text("ERROR"));
      }
      PQclear(res);
+     res = NULL;

      /* if we started a transaction, decrement cursor count */
      if (rconn->newXactForCursor)
***************
*** 488,499 ****
              rconn->newXactForCursor = FALSE;

              res = PQexec(conn, "COMMIT");
!             if (PQresultStatus(res) != PGRES_COMMAND_OK)
                  DBLINK_RES_INTERNALERROR("commit error");
              PQclear(res);
          }
      }

      PG_RETURN_TEXT_P(cstring_to_text("OK"));
  }

--- 514,527 ----
              rconn->newXactForCursor = FALSE;

              res = PQexec(conn, "COMMIT");
!             if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
                  DBLINK_RES_INTERNALERROR("commit error");
              PQclear(res);
+             res = NULL;
          }
      }

+     POP_DBERRCONTEXT;
      PG_RETURN_TEXT_P(cstring_to_text("OK"));
  }

***************
*** 509,519 ****
      int            call_cntr;
      int            max_calls;
      AttInMetadata *attinmeta;
-     PGresult   *res = NULL;
      MemoryContext oldcontext;
      char       *conname = NULL;
      remoteConn *rconn = NULL;
!
      DBLINK_INIT;

      /* stuff done only on the first call of the function */
--- 537,548 ----
      int            call_cntr;
      int            max_calls;
      AttInMetadata *attinmeta;
      MemoryContext oldcontext;
      char       *conname = NULL;
      remoteConn *rconn = NULL;
!     ERRORCONTEXTCALLBACK;
!
!     PUSH_DBERRCONTEXT(dblink_error_callback);
      DBLINK_INIT;

      /* stuff done only on the first call of the function */
***************
*** 585,597 ****
              (PQresultStatus(res) != PGRES_COMMAND_OK &&
               PQresultStatus(res) != PGRES_TUPLES_OK))
          {
!             dblink_res_error(conname, res, "could not fetch from cursor", fail);
              SRF_RETURN_DONE(funcctx);
          }
          else if (PQresultStatus(res) == PGRES_COMMAND_OK)
          {
              /* cursor does not exist - closed already or bad name */
              PQclear(res);
              ereport(ERROR,
                      (errcode(ERRCODE_INVALID_CURSOR_NAME),
                       errmsg("cursor \"%s\" does not exist", curname)));
--- 614,627 ----
              (PQresultStatus(res) != PGRES_COMMAND_OK &&
               PQresultStatus(res) != PGRES_TUPLES_OK))
          {
!             dblink_res_error(conname, "could not fetch from cursor", fail);
              SRF_RETURN_DONE(funcctx);
          }
          else if (PQresultStatus(res) == PGRES_COMMAND_OK)
          {
              /* cursor does not exist - closed already or bad name */
              PQclear(res);
+             res = NULL;
              ereport(ERROR,
                      (errcode(ERRCODE_INVALID_CURSOR_NAME),
                       errmsg("cursor \"%s\" does not exist", curname)));
***************
*** 635,640 ****
--- 665,671 ----
          if (funcctx->max_calls < 1)
          {
              PQclear(res);
+             res = NULL;
              SRF_RETURN_DONE(funcctx);
          }

***************
*** 690,701 ****
--- 721,736 ----
          /* make the tuple into a datum */
          result = HeapTupleGetDatum(tuple);

+         POP_DBERRCONTEXT;
          SRF_RETURN_NEXT(funcctx, result);
      }
      else
      {
          /* do when there is no more left */
          PQclear(res);
+         res = NULL;
+
+         POP_DBERRCONTEXT;
          SRF_RETURN_DONE(funcctx);
      }
  }
***************
*** 755,766 ****
      int            max_calls;
      AttInMetadata *attinmeta;
      char       *msg;
-     PGresult   *res = NULL;
      bool        is_sql_cmd = false;
      char       *sql_cmd_status = NULL;
      MemoryContext oldcontext;
      bool        freeconn = false;
!
      DBLINK_INIT;

      /* stuff done only on the first call of the function */
--- 790,802 ----
      int            max_calls;
      AttInMetadata *attinmeta;
      char       *msg;
      bool        is_sql_cmd = false;
      char       *sql_cmd_status = NULL;
      MemoryContext oldcontext;
      bool        freeconn = false;
!     ERRORCONTEXTCALLBACK;
!
!     PUSH_DBERRCONTEXT(dblink_error_callback);
      DBLINK_INIT;

      /* stuff done only on the first call of the function */
***************
*** 857,863 ****
          {
              if (freeconn)
                  PQfinish(conn);
!             dblink_res_error(conname, res, "could not execute query", fail);
              MemoryContextSwitchTo(oldcontext);
              SRF_RETURN_DONE(funcctx);
          }
--- 893,899 ----
          {
              if (freeconn)
                  PQfinish(conn);
!             dblink_res_error(conname, "could not execute query", fail);
              MemoryContextSwitchTo(oldcontext);
              SRF_RETURN_DONE(funcctx);
          }
***************
*** 926,932 ****
--- 962,971 ----
          if (funcctx->max_calls < 1)
          {
              if (res)
+             {
                  PQclear(res);
+                 res = NULL;
+             }
              MemoryContextSwitchTo(oldcontext);
              SRF_RETURN_DONE(funcctx);
          }
***************
*** 984,995 ****
--- 1023,1038 ----
          /* make the tuple into a datum */
          result = HeapTupleGetDatum(tuple);

+         POP_DBERRCONTEXT;
          SRF_RETURN_NEXT(funcctx, result);
      }
      else
      {
          /* do when there is no more left */
          PQclear(res);
+         res = NULL;
+
+         POP_DBERRCONTEXT;
          SRF_RETURN_DONE(funcctx);
      }
  }
***************
*** 1119,1125 ****
  dblink_exec(PG_FUNCTION_ARGS)
  {
      char       *msg;
-     PGresult   *res = NULL;
      text       *sql_cmd_status = NULL;
      TupleDesc    tupdesc = NULL;
      PGconn       *conn = NULL;
--- 1162,1167 ----
***************
*** 1129,1135 ****
      remoteConn *rconn = NULL;
      bool        freeconn = false;
      bool        fail = true;    /* default to backward compatible behavior */
!
      DBLINK_INIT;

      if (PG_NARGS() == 3)
--- 1171,1179 ----
      remoteConn *rconn = NULL;
      bool        freeconn = false;
      bool        fail = true;    /* default to backward compatible behavior */
!     ERRORCONTEXTCALLBACK;
!
!     PUSH_DBERRCONTEXT(dblink_error_callback);
      DBLINK_INIT;

      if (PG_NARGS() == 3)
***************
*** 1172,1178 ****
          (PQresultStatus(res) != PGRES_COMMAND_OK &&
           PQresultStatus(res) != PGRES_TUPLES_OK))
      {
!         dblink_res_error(conname, res, "could not execute command", fail);

          /* need a tuple descriptor representing one TEXT column */
          tupdesc = CreateTemplateTupleDesc(1, false);
--- 1216,1222 ----
          (PQresultStatus(res) != PGRES_COMMAND_OK &&
           PQresultStatus(res) != PGRES_TUPLES_OK))
      {
!         dblink_res_error(conname, "could not execute command", fail);

          /* need a tuple descriptor representing one TEXT column */
          tupdesc = CreateTemplateTupleDesc(1, false);
***************
*** 1198,1207 ****
--- 1242,1253 ----
           */
          sql_cmd_status = cstring_to_text(PQcmdStatus(res));
          PQclear(res);
+         res = NULL;
      }
      else
      {
          PQclear(res);
+         res = NULL;
          ereport(ERROR,
                  (errcode(ERRCODE_S_R_E_PROHIBITED_SQL_STATEMENT_ATTEMPTED),
                   errmsg("statement returning results not allowed")));
***************
*** 1211,1216 ****
--- 1257,1263 ----
      if (freeconn)
          PQfinish(conn);

+     POP_DBERRCONTEXT;
      PG_RETURN_TEXT_P(sql_cmd_status);
  }

***************
*** 2418,2424 ****
  }

  static void
! dblink_res_error(const char *conname, PGresult *res, const char *dblink_context_msg, bool fail)
  {
      int            level;
      char       *pg_diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
--- 2465,2471 ----
  }

  static void
! dblink_res_error(const char *conname, const char *dblink_context_msg, bool fail)
  {
      int            level;
      char       *pg_diag_sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
***************
*** 2453,2459 ****
--- 2500,2509 ----
      xpstrdup(message_context, pg_diag_context);

      if (res)
+     {
          PQclear(res);
+         res = NULL;
+     }

      if (conname)
          dblink_context_conname = conname;
***************
*** 2550,2552 ****
--- 2600,2615 ----

      return buf->data;
  }
+
+ /*
+  * error context callback to let us free resources
+  */
+ static void
+ dblink_error_callback(void *arg)
+ {
+     if (res)
+     {
+         PQclear(res);
+         res = NULL;
+     }
+ }

Attachment

dblink memory leak

From
Itagaki Takahiro
Date:
Joe Conway <mail@joeconway.com> wrote:

> > The point is *memory leak* in dblink when a query is canceled or
> > become time-out. I think it is a bug, and my patch could fix it.
> 
> Please see if this works for you.

It does not work because errors can occur in caller of dblink functions;
Error callback should be still registered after SRF_RETURN_NEXT, so we
cannot place callback context on stack of the function. More works needed.

RegisterExprContextCallback() might be good for this purpose,
but we need to modify callbacks are fired even if error.

Regards,
---
ITAGAKI Takahiro
NTT Open Source Software Center




Re: dblink memory leak

From
Tom Lane
Date:
Itagaki Takahiro <itagaki.takahiro@oss.ntt.co.jp> writes:
> Joe Conway <mail@joeconway.com> wrote:
>> Please see if this works for you.

> It does not work because errors can occur in caller of dblink functions;
> Error callback should be still registered after SRF_RETURN_NEXT, so we
> cannot place callback context on stack of the function. More works needed.

Yeah, I meant to comment on that: it's an abuse of the error context
mechanism and will never be safe.  (An example is that if someone
innocently did an elog(LOG) or something like that, the callback would
get triggered.)  The global PGresult value seems awfully dangerous too.

I think what you want to do instead is use PG_TRY blocks to ensure that
transient results are cleaned up.
        regards, tom lane


Re: dblink memory leak

From
Itagaki Takahiro
Date:
Tom Lane <tgl@sss.pgh.pa.us> wrote:

> I think what you want to do instead is use PG_TRY blocks to ensure that
> transient results are cleaned up.

I think PG_TRY blocks are not enough, too. PG_TRY requires a statement
block, but we need to return from dblink functions per tuple.
Error and interruption can occur at the caller:
   ExecMakeTableFunctionResult()   {       for (;;)       {
*here*      CHECK_FOR_INTERRUPTS();           result = FunctionCallInvoke(&fcinfo);  => { PG_TRY ... END }           if
(rsinfo.isDone== ExprEndResult)               break;           tuplestore_puttuple(tupstore, &tmptup);       }   }
 

Also, we should think SRF-functions might not be called repeatedly
until max_calls whether the transaction is committed or rollbacked
because we might have some optimization in FunctionScan in the future.
For example:   SELECT * FROM dblink() LIMIT 3
might call dblink() only 3 times if we optimize executor logic
(it should not occur for now, though).

Regards,
---
ITAGAKI Takahiro
NTT Open Source Software Center




Re: dblink memory leak

From
Tom Lane
Date:
Itagaki Takahiro <itagaki.takahiro@oss.ntt.co.jp> writes:
> I think PG_TRY blocks are not enough, too. PG_TRY requires a statement
> block, but we need to return from dblink functions per tuple.

That bit will have to be undone.  There is no reason for dblink not to
return a tuplestore.
        regards, tom lane


Re: dblink memory leak

From
Joe Conway
Date:
Tom Lane wrote:
> Itagaki Takahiro <itagaki.takahiro@oss.ntt.co.jp> writes:
>> I think PG_TRY blocks are not enough, too. PG_TRY requires a statement
>> block, but we need to return from dblink functions per tuple.
>
> That bit will have to be undone.  There is no reason for dblink not to
> return a tuplestore.

That's a really good point. It was originally written thinking we would
eventually be able to stream tuples rather than materialize them, but
given that many years have passed and we are no closer (I believe) to a
true streaming mode for SRFs, a tuplestore would be much cleaner.

Given that change, is there even any leak to even worry about? As long
as the PGresult object is created in the correct memory context, it
ought to get cleaned up automatically, no?

I can't promise to make this change before 15 October, but I will get to
it before the end of CF3.

Joe



Re: dblink memory leak

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> Given that change, is there even any leak to even worry about? As long
> as the PGresult object is created in the correct memory context, it
> ought to get cleaned up automatically, no?

No, because libpq knows nothing of backend memory contexts; it just
allocates with malloc.  You'll still need a PG_TRY block to ensure you
release PGresults during error cleanup.  The change to using tuplestores
will just help you localize that requirement in well-defined places.

> I can't promise to make this change before 15 October, but I will get to
> it before the end of CF3.

No big hurry, I think, considering the leak has always been there.
        regards, tom lane


Re: dblink memory leak

From
Joe Conway
Date:
Tom Lane wrote:
> Joe Conway <mail@joeconway.com> writes:
>> Given that change, is there even any leak to even worry about? As long
>> as the PGresult object is created in the correct memory context, it
>> ought to get cleaned up automatically, no?
>
> No, because libpq knows nothing of backend memory contexts; it just
> allocates with malloc.  You'll still need a PG_TRY block to ensure you
> release PGresults during error cleanup.  The change to using tuplestores
> will just help you localize that requirement in well-defined places.

I should have known that! Thanks for the wack on the head...

>> I can't promise to make this change before 15 October, but I will get to
>> it before the end of CF3.
>
> No big hurry, I think, considering the leak has always been there.

Great. It seems like this is too invasive a change to backport. My
feeling is that not enough people have complained about this specific
scenario to warrant the risk.

Joe


Re: dblink memory leak

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> Tom Lane wrote:
>> No big hurry, I think, considering the leak has always been there.

> Great. It seems like this is too invasive a change to backport. My
> feeling is that not enough people have complained about this specific
> scenario to warrant the risk.

Agreed, the risk/reward ratio doesn't seem favorable for a backport.
        regards, tom lane


Re: dblink memory leak

From
Robert Haas
Date:
On Mon, Oct 5, 2009 at 1:46 PM, Joe Conway <mail@joeconway.com> wrote:
> Tom Lane wrote:
>> Itagaki Takahiro <itagaki.takahiro@oss.ntt.co.jp> writes:
>>> I think PG_TRY blocks are not enough, too. PG_TRY requires a statement
>>> block, but we need to return from dblink functions per tuple.
>>
>> That bit will have to be undone.  There is no reason for dblink not to
>> return a tuplestore.
>
> That's a really good point. It was originally written thinking we would
> eventually be able to stream tuples rather than materialize them, but
> given that many years have passed and we are no closer (I believe) to a
> true streaming mode for SRFs, a tuplestore would be much cleaner.
>
> Given that change, is there even any leak to even worry about? As long
> as the PGresult object is created in the correct memory context, it
> ought to get cleaned up automatically, no?
>
> I can't promise to make this change before 15 October, but I will get to
> it before the end of CF3.

Another possibility is that Itagaki Takahiro, who developed the
original patch, might be willing to develop something along these
lines instead.

However, it does seem that that original patch will not be accepted,
for the reason that the committers prefer the approach discussed
upthread.  Therefore, I am marking the "query cancel issues in dblink"
patch as "Returned with Feedback".

...Robert


Re: dblink memory leak

From
Joe Conway
Date:
Robert Haas wrote:
> On Mon, Oct 5, 2009 at 1:46 PM, Joe Conway <mail@joeconway.com> wrote:
>> I can't promise to make this change before 15 October, but I will get to
>> it before the end of CF3.
>
> Another possibility is that Itagaki Takahiro, who developed the
> original patch, might be willing to develop something along these
> lines instead.

Either way is fine -- good suggestion ;-)

> However, it does seem that that original patch will not be accepted,
> for the reason that the committers prefer the approach discussed
> upthread.  Therefore, I am marking the "query cancel issues in dblink"
> patch as "Returned with Feedback".

Yes, thanks for doing that.

Joe



Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
On Wed, Sep 30, 2009 at 12:24 PM, Heikki Linnakangas
<heikki.linnakangas@enterprisedb.com> wrote:
>>  Do you
>> have any sense of how soon you'll feel confident to commit either
>> patch?
>
> I'm bad at estimating. Not this week for sure, and next week I'm
> traveling and won't be able to spend as much time on it as I am right
> now. If no new major issues are found, and all the outstanding issues
> are resolved by me or Simon by then, maybe the week after that.

It's now the week after that, so unless you're in the process of
typing that 'cvs commit' command, I'm going to move HS + SR out to the
next CommitFest so that we can close this one out and stamp alpha2.

<brief pause for objections will now ensue>

...Robert


Re: CommitFest 2009-09, two weeks on

From
KaiGai Kohei
Date:
Robert Haas wrote:
> On Wed, Sep 30, 2009 at 12:24 PM, Heikki Linnakangas
> <heikki.linnakangas@enterprisedb.com> wrote:
>>>  Do you
>>> have any sense of how soon you'll feel confident to commit either
>>> patch?
>> I'm bad at estimating. Not this week for sure, and next week I'm
>> traveling and won't be able to spend as much time on it as I am right
>> now. If no new major issues are found, and all the outstanding issues
>> are resolved by me or Simon by then, maybe the week after that.
> 
> It's now the week after that, so unless you're in the process of
> typing that 'cvs commit' command, I'm going to move HS + SR out to the
> next CommitFest so that we can close this one out and stamp alpha2.
> 
> <brief pause for objections will now ensue>

I have a question.
When we register the postponed patches on the CF-Nov site again,
which tag should be choosen? "Needs Review"? or "Ready for Commiter"?

Thanks,
-- 
OSS Platform Development Division, NEC
KaiGai Kohei <kaigai@ak.jp.nec.com>


Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
2009/10/14 KaiGai Kohei <kaigai@ak.jp.nec.com>:
> Robert Haas wrote:
>> On Wed, Sep 30, 2009 at 12:24 PM, Heikki Linnakangas
>> <heikki.linnakangas@enterprisedb.com> wrote:
>>>>  Do you
>>>> have any sense of how soon you'll feel confident to commit either
>>>> patch?
>>> I'm bad at estimating. Not this week for sure, and next week I'm
>>> traveling and won't be able to spend as much time on it as I am right
>>> now. If no new major issues are found, and all the outstanding issues
>>> are resolved by me or Simon by then, maybe the week after that.
>>
>> It's now the week after that, so unless you're in the process of
>> typing that 'cvs commit' command, I'm going to move HS + SR out to the
>> next CommitFest so that we can close this one out and stamp alpha2.
>>
>> <brief pause for objections will now ensue>
>
> I have a question.
> When we register the postponed patches on the CF-Nov site again,
> which tag should be choosen? "Needs Review"? or "Ready for Commiter"?

Needs Review.

...Robert


Re: CommitFest 2009-09, two weeks on

From
Heikki Linnakangas
Date:
Robert Haas wrote:
> On Wed, Sep 30, 2009 at 12:24 PM, Heikki Linnakangas
> <heikki.linnakangas@enterprisedb.com> wrote:
>>>  Do you
>>> have any sense of how soon you'll feel confident to commit either
>>> patch?
>> I'm bad at estimating. Not this week for sure, and next week I'm
>> traveling and won't be able to spend as much time on it as I am right
>> now. If no new major issues are found, and all the outstanding issues
>> are resolved by me or Simon by then, maybe the week after that.
> 
> It's now the week after that, so unless you're in the process of
> typing that 'cvs commit' command, I'm going to move HS + SR out to the
> next CommitFest so that we can close this one out and stamp alpha2.

No objections here.

--  Heikki Linnakangas EnterpriseDB   http://www.enterprisedb.com


Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
On Thu, Oct 15, 2009 at 2:27 AM, Heikki Linnakangas
<heikki.linnakangas@enterprisedb.com> wrote:
> Robert Haas wrote:
>> On Wed, Sep 30, 2009 at 12:24 PM, Heikki Linnakangas
>> <heikki.linnakangas@enterprisedb.com> wrote:
>>>>  Do you
>>>> have any sense of how soon you'll feel confident to commit either
>>>> patch?
>>> I'm bad at estimating. Not this week for sure, and next week I'm
>>> traveling and won't be able to spend as much time on it as I am right
>>> now. If no new major issues are found, and all the outstanding issues
>>> are resolved by me or Simon by then, maybe the week after that.
>>
>> It's now the week after that, so unless you're in the process of
>> typing that 'cvs commit' command, I'm going to move HS + SR out to the
>> next CommitFest so that we can close this one out and stamp alpha2.
>
> No objections here.

OK, done.

...Robert


Re: CommitFest 2009-09, two weeks on

From
Alvaro Herrera
Date:
Boszormenyi Zoltan escribió:

> I have split up (and cleaned up a little) the dynamic
> cursorname patch into smaller logical, easier-to-review
> pieces. Descriptions below.
> 
> 1) 1a-unified-optfromin-fetch-ctxdiff.patch
> 
> ecpg supports optional FROM/IN in FETCH and
> MOVE statements (mainly because it's required by
> Informix-compatibility). Unify core and ecpg grammar
> as per Tom Lane's suggestion.

I have applied this patch after some tinkering.  I mainly added support
for "fetch_args: FORWARD opt_from_in name" and "BACKWARD opt_from_in
name" in ecpg.addons which apparently you forgot.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.


Re: CommitFest 2009-09, two weeks on

From
Tom Lane
Date:
Alvaro Herrera <alvherre@commandprompt.com> writes:
> I have applied this patch after some tinkering.

Shouldn't there be a docs change in that commit?
        regards, tom lane


Re: CommitFest 2009-09, two weeks on

From
Alvaro Herrera
Date:
Tom Lane escribió:
> Alvaro Herrera <alvherre@commandprompt.com> writes:
> > I have applied this patch after some tinkering.
> 
> Shouldn't there be a docs change in that commit?

True -- fixed.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.


Re: CommitFest 2009-09, two weeks on

From
Alvaro Herrera
Date:
Boszormenyi Zoltan escribió:

> 2) 1b-cursor_name-ctxdiff.patch
> 
> "name" -> "cursor_name" transition in core grammar
> and ecpg grammar. Currently it does nothing, it's a
> preparation phase. Depends on patch 1.

Applied this part too.

I cannot apply the other ones -- they belong to the ECPG maintainer.  I
hope I cleared his road a bit.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support


Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Alvaro Herrera írta:
> Boszormenyi Zoltan escribió:
>
>   
>> I have split up (and cleaned up a little) the dynamic
>> cursorname patch into smaller logical, easier-to-review
>> pieces. Descriptions below.
>>
>> 1) 1a-unified-optfromin-fetch-ctxdiff.patch
>>
>> ecpg supports optional FROM/IN in FETCH and
>> MOVE statements (mainly because it's required by
>> Informix-compatibility). Unify core and ecpg grammar
>> as per Tom Lane's suggestion.
>>     
>
> I have applied this patch after some tinkering.  I mainly added support
> for "fetch_args: FORWARD opt_from_in name" and "BACKWARD opt_from_in
> name" in ecpg.addons which apparently you forgot.
>   

Thanks. Your fix is correct if this patch is considered
standalone. This means I have to re-post the later
patches to fix the reject this fix causes in them.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Alvaro Herrera írta:
> Boszormenyi Zoltan escribió:
>
>   
>> 2) 1b-cursor_name-ctxdiff.patch
>>
>> "name" -> "cursor_name" transition in core grammar
>> and ecpg grammar. Currently it does nothing, it's a
>> preparation phase. Depends on patch 1.
>>     
>
> Applied this part too.
>
> I cannot apply the other ones -- they belong to the ECPG maintainer.  I
> hope I cleared his road a bit.
>   

Thanks and best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: CommitFest 2009-09, two weeks on

From
Alvaro Herrera
Date:
Boszormenyi Zoltan escribió:
> Alvaro Herrera írta:

> > I have applied this patch after some tinkering.  I mainly added support
> > for "fetch_args: FORWARD opt_from_in name" and "BACKWARD opt_from_in
> > name" in ecpg.addons which apparently you forgot.
> 
> Thanks. Your fix is correct if this patch is considered
> standalone. This means I have to re-post the later
> patches to fix the reject this fix causes in them.

Yeah.  BTW I don't think the rest of the pieces in this series make
sense to apply separately, because they don't do anything useful by
themselves (one of them introduces an unused function, what good is in
that?).  I think they should be submitted as a single patch.

If you want to submit patches in a series like this one, they need to be
considered standalone, I think.  The Linux kernel devs work differently
than us here.

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.


Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
On Thu, Nov 12, 2009 at 2:49 PM, Alvaro Herrera
<alvherre@commandprompt.com> wrote:
> Boszormenyi Zoltan escribió:
>> Alvaro Herrera írta:
>
>> > I have applied this patch after some tinkering.  I mainly added support
>> > for "fetch_args: FORWARD opt_from_in name" and "BACKWARD opt_from_in
>> > name" in ecpg.addons which apparently you forgot.
>>
>> Thanks. Your fix is correct if this patch is considered
>> standalone. This means I have to re-post the later
>> patches to fix the reject this fix causes in them.
>
> Yeah.  BTW I don't think the rest of the pieces in this series make
> sense to apply separately, because they don't do anything useful by
> themselves (one of them introduces an unused function, what good is in
> that?).  I think they should be submitted as a single patch.
>
> If you want to submit patches in a series like this one, they need to be
> considered standalone, I think.  The Linux kernel devs work differently
> than us here.

Zoltan broke them up because Michael asked him to do so.

...Robert


Re: CommitFest 2009-09, two weeks on

From
Michael Meskes
Date:
On Thu, Nov 12, 2009 at 03:07:27PM -0500, Robert Haas wrote:
> > If you want to submit patches in a series like this one, they need to be
> > considered standalone, I think.  The Linux kernel devs work differently
> > than us here.
> 
> Zoltan broke them up because Michael asked him to do so.

Actually these patchsets add different features. I see no reason why they
should be done as one patch. However, I haven't had the time to look into the
latest ones, but at least that was the situation when I asked Zoltan to split
the patch.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL


Re: CommitFest 2009-09, two weeks on

From
Hans-Jürgen Schönig
Date:
On Nov 13, 2009, at 8:06 AM, Michael Meskes wrote:

> On Thu, Nov 12, 2009 at 03:07:27PM -0500, Robert Haas wrote:
>>> If you want to submit patches in a series like this one, they need
>>> to be
>>> considered standalone, I think.  The Linux kernel devs work
>>> differently
>>> than us here.
>>
>> Zoltan broke them up because Michael asked him to do so.
>
> Actually these patchsets add different features. I see no reason why
> they
> should be done as one patch. However, I haven't had the time to look
> into the
> latest ones, but at least that was the situation when I asked Zoltan
> to split
> the patch.
>
> Michael
> --
> Michael Meskes
> Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
> Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
> ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
> VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux,
> PostgreSQL
>



good morning,

are there some pending technical issues with those patches or can we
basically review and commit?
many thanks,
    hans


--
Cybertec Schönig & Schönig GmbH
Reyergasse 9 / 2
A-2700 Wiener Neustadt
Web: www.postgresql-support.de



Re: CommitFest 2009-09, two weeks on

From
Robert Haas
Date:
2009/11/13 Hans-Jürgen Schönig <hs@cybertec.at>:
>
> On Nov 13, 2009, at 8:06 AM, Michael Meskes wrote:
>
>> On Thu, Nov 12, 2009 at 03:07:27PM -0500, Robert Haas wrote:
>>>>
>>>> If you want to submit patches in a series like this one, they need to be
>>>> considered standalone, I think.  The Linux kernel devs work differently
>>>> than us here.
>>>
>>> Zoltan broke them up because Michael asked him to do so.
>>
>> Actually these patchsets add different features. I see no reason why they
>> should be done as one patch. However, I haven't had the time to look into
>> the
>> latest ones, but at least that was the situation when I asked Zoltan to
>> split
>> the patch.
>>
>> Michael
>> --
>> Michael Meskes
>> Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
>> Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
>> ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
>> VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL
>>
>
>
>
> good morning,
>
> are there some pending technical issues with those patches or can we
> basically review and commit?

*scratches head*

How is anyone supposed to answer that question?  It is in the process
of reviewing them that one decides whether there are any technical
issues...

...Robert


Re: CommitFest 2009-09, two weeks on

From
Boszormenyi Zoltan
Date:
Alvaro Herrera írta:
> Boszormenyi Zoltan escribió:
>   
>> Alvaro Herrera írta:
>>     
>>> I have applied this patch after some tinkering.  I mainly added support
>>> for "fetch_args: FORWARD opt_from_in name" and "BACKWARD opt_from_in
>>> name" in ecpg.addons which apparently you forgot.
>>>       
>> Thanks. Your fix is correct if this patch is considered
>> standalone. This means I have to re-post the later
>> patches to fix the reject this fix causes in them.
>>     
>
> Yeah.  BTW I don't think the rest of the pieces in this series make
> sense to apply separately, because they don't do anything useful by
> themselves (one of them introduces an unused function, what good is in
> that?).  I think they should be submitted as a single patch.
>
> If you want to submit patches in a series like this one, they need to be
> considered standalone, I think.  The Linux kernel devs work differently
> than us here.
>   

Dan started reviewing the dynamic cursorname patch.
He looked at it in the original form and he said that
he's not familiar with the ECPG code.

I have drafted the docs for the generated ECPG grammar
(it was applied mainstream by Michael shortly after
being posted) and have split this patch in question to help
Dan in the review. The patch pieces explain the various
problems about the implementation.

Is it really *that* apparent that I read too much LKML? :-D

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



ECPG patch 1, dynamic cursorname

From
Boszormenyi Zoltan
Date:
Hi,

I have rebased the ECPG patches to current CVS.
This mail contains the dynamic cursorname,
the fine-grained split-up was re-united as per
Alvaro's comment.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

ECPG patch 2, SQLDA support

From
Boszormenyi Zoltan
Date:
New version: rebased to current CVS.

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch 3, DESCRIBE [OUTPUT] support

From
Boszormenyi Zoltan
Date:
New version: rebased to current CVS.

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

ECPG patch 4, out-of-scope cursor support in Informix-mode

From
Boszormenyi Zoltan
Date:
New version: rebased to current CVS.

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch 1, dynamic cursorname

From
Michael Meskes
Date:
On Mon, Nov 16, 2009 at 11:58:04AM +0100, Boszormenyi Zoltan wrote:
> I have rebased the ECPG patches to current CVS.
> This mail contains the dynamic cursorname,
> the fine-grained split-up was re-united as per
> Alvaro's comment.

Rest of it committed to HEAD.

Thanks for your work.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL


Re: ECPG patch 1, dynamic cursorname

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Mon, Nov 16, 2009 at 11:58:04AM +0100, Boszormenyi Zoltan wrote:
>   
>> I have rebased the ECPG patches to current CVS.
>> This mail contains the dynamic cursorname,
>> the fine-grained split-up was re-united as per
>> Alvaro's comment.
>>     
>
> Rest of it committed to HEAD.
>
> Thanks for your work.
>
> Michael
>   

Thanks very much for committing this.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch 2, SQLDA support

From
Jaime Casanova
Date:
On Mon, Nov 16, 2009 at 5:59 AM, Boszormenyi Zoltan <zb@cybertec.at> wrote:
> New version: rebased to current CVS.
>

This one no longer applies to HEAD, could you update it please?

--
Atentamente,
Jaime Casanova
Soporte y capacitación de PostgreSQL
Asesoría y desarrollo de sistemas
Guayaquil - Ecuador
Cel. +59387171157


Re: ECPG patch 2, SQLDA support

From
Boszormenyi Zoltan
Date:
Hi,

Jaime Casanova írta:
> On Mon, Nov 16, 2009 at 5:59 AM, Boszormenyi Zoltan <zb@cybertec.at> wrote:
>   
>> New version: rebased to current CVS.
>>
>>     
>
> This one no longer applies to HEAD, could you update it please?
>   

Will post a new version soon, Michael asked to turn it
into an ECPG native feature instead of compat-mode-only.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch 2, SQLDA support

From
Boszormenyi Zoltan
Date:
Boszormenyi Zoltan írta:
> Will post a new version soon, Michael asked to turn it
> into an ECPG native feature instead of compat-mode-only.
>

Attached is the new version that applies cleanly to HEAD.

Changes:
- SQLDA is now an ECPG native feature, not compat-only.
- As a consequence, and to be coherent with the Informix syntax,
  keyword "SQL" in SQL DESCRIPTOR is now mandatory
  to denote the named SQL descriptor. "DESCRIPTOR"
  without "SQL" means SQLDA descriptor
- SQLDA can now return more than one tuples using
  the ->desc_next pointer
- Bcause SQLDA is now a native feature, there are two
  sqlda.pgc regression tests, to test compat-only syntax in
  compat mode and multi-tuple return values in native mode.
- sqlda->sqlvar[i].sqltype uses ECPGt_* type symbols,
  no more funny-looking typedefs in sqltypes.h, it's a clean
  compat-only header, as it was before

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch 3, DESCRIBE [OUTPUT] support

From
Boszormenyi Zoltan
Date:
New version, rebased to the previously sent
new SQLDA patch.

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch 2, SQLDA support

From
Boszormenyi Zoltan
Date:
Boszormenyi Zoltan írta:
> Boszormenyi Zoltan írta:
>
>> Will post a new version soon, Michael asked to turn it
>> into an ECPG native feature instead of compat-mode-only.
>>
>>
>
> Attached is the new version that applies cleanly to HEAD.
>
> Changes:
> - SQLDA is now an ECPG native feature, not compat-only.
> - As a consequence, and to be coherent with the Informix syntax,
>   keyword "SQL" in SQL DESCRIPTOR is now mandatory
>   to denote the named SQL descriptor. "DESCRIPTOR"
>   without "SQL" means SQLDA descriptor
> - SQLDA can now return more than one tuples using
>   the ->desc_next pointer
> - Bcause SQLDA is now a native feature, there are two
>   sqlda.pgc regression tests, to test compat-only syntax in
>   compat mode and multi-tuple return values in native mode.
> - sqlda->sqlvar[i].sqltype uses ECPGt_* type symbols,
>   no more funny-looking typedefs in sqltypes.h, it's a clean
>   compat-only header, as it was before
>

New version, fixed some loose ends introduced by
the native mode and multi-tuple SQLDA.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch 3, DESCRIBE [OUTPUT] support

From
Boszormenyi Zoltan
Date:
Boszormenyi Zoltan írta:
> New version, rebased to the previously sent
> new SQLDA patch.
>

New version, fixed some loose ends introduced by
the native mode and multi-tuple SQLDA. No more
build_sqlda() in ecpglib/descriptor.c, common code
is factored out for ECPGt_descriptor and ECPGt_sqlda
in ECPGdescribe().

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch 4, out-of-scope cursor support in Informix-mode

From
Boszormenyi Zoltan
Date:
New version: rebased to current CVS and
fix the rejects caused by the newer SQLDA
and DESCRIBE patches. Note that it's still
compat-mode only, I will send a modified patch
in the next email that is ECPG-wide, so it can be
decided if the feature is wanted in native mode or not.

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Boszormenyi Zoltan írta:
> New version: rebased to current CVS and
> fix the rejects caused by the newer SQLDA
> and DESCRIBE patches. Note that it's still
> compat-mode only, I will send a modified patch
> in the next email that is ECPG-wide, so it can be
> decided if the feature is wanted in native mode or not.

Attached. Changes against the compat-mode only patch are:
- ECPG_informix_set_var() and ECPG_informix_get_var()
  were renamed to ECPGset_var() and ECPGget_var() and
  were moved into libecpg. The previous calls are kept
  in libecpg_compat.so as wrappers for compatibility reasons.
- adjust_informix() was renamed as adjust_outofscope_cursor_vars()
  to indicate its real purpose. The comment at the beginning
  of the function is modified to explain why it's useful.

The code produced by this is not too ugly this way in
native mode, only some ECPGset_var() calls are added
when the DECLARE are in the same function as OPEN/FETCH/CLOSE.
Global variables used in DECLARE aren't transformed at all.

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch N+1, fix auto-prepare

From
Boszormenyi Zoltan
Date:
Hi,

here's another patch that aims to fix auto-prepare.

The reason is, that in the project porting from Informix,
a small test case that used a cursor and two small SELECTs
issued for every record retrieved by the cursor showed that
for this case, the ESQL compiled binary finished about 60%
faster then the ECPG compiled counterpart running against
PostgreSQL. The cursor retrieved a little over 60'000 records.

We have modified the test code to prepare the two SELECTs
and now the new test code was faster then the ESQL/Informix
code, parsing and planning the two small SELECTs had such
an accumulated runtime effect.

Then we looked at ECPG and discovered that it already has
the auto-prepare feature, and tried it using "ecpg -r prepare".

However, it turned out that the auto-prepare feature is
over-zealous, it tries to prepare statements that are rejected
by the server, returning -400 (ECPG_PGSQL). One example is

  char *sqlstr = "SELECT ...";

  EXEC SQL PREPARE stmt1 FROM :sqlstr;
  EXEC SQL DECLARE cur1 CURSOR FOR stmt1;

The attached patch is an attempt to make the preprocessor
only pass ECPGst_prepnormal when it's definitely appropriate,
i.e. only for DELETE, INSERT, UPDATE and SELECT(-like)
statements in the grammar.

Comments?

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch N+1, fix auto-prepare

From
Michael Meskes
Date:
On Tue, Dec 15, 2009 at 02:19:19PM +0100, Boszormenyi Zoltan wrote:
> here's another patch that aims to fix auto-prepare.
> ...
> --- pgsql.6/src/interfaces/ecpg/preproc/output.c    2009-12-15 13:12:37.000000000 +0100
> *************** hashline_number(void)
> *** 106,112 ****
>   }
>   
>   void
> ! output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
>   {
>   
>       fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection :
"NULL",questionmarks);
 
> --- 106,112 ----
>   }
>   
>   void
> ! output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st, int auto_prepare)
>   {
>   
>       fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection :
"NULL",questionmarks);
 

Why do you add another argument to output_statement? You should easily be able
to use the existing ECPG_statement_type argument for this. How about changing
ECPGst_normal to ECPGst_normal and ECPGst_nonprep or something like this? Or
did I miss something?

Besides I don't think it's a good idea to create a local variable overriding a
global one with the same name. 


Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL


Re: ECPG patch N+1, fix auto-prepare

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Tue, Dec 15, 2009 at 02:19:19PM +0100, Boszormenyi Zoltan wrote:
>> here's another patch that aims to fix auto-prepare.
>> ...
>> --- pgsql.6/src/interfaces/ecpg/preproc/output.c    2009-12-15 13:12:37.000000000 +0100
>> *************** hashline_number(void)
>> *** 106,112 ****
>>   }
>>
>>   void
>> ! output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
>>   {
>>
>>       fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection :
"NULL",questionmarks); 
>> --- 106,112 ----
>>   }
>>
>>   void
>> ! output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st, int auto_prepare)
>>   {
>>
>>       fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat, force_indicator, connection ? connection :
"NULL",questionmarks); 
>
> Why do you add another argument to output_statement? You should easily be able
> to use the existing ECPG_statement_type argument for this. How about changing
> ECPGst_normal to ECPGst_normal and ECPGst_nonprep or something like this? Or
> did I miss something?
>
> Besides I don't think it's a good idea to create a local variable overriding a
> global one with the same name.

OK, here's another approach. output_statement()'s interface
is kept as the original, and not this function decides which
value it uses. I also introduced
    static char *ecpg_statement_type_name[]
for the textual names of the ECPGst_* symbols to keep the
preprocessed code readable, and minimize the impact on the
regression tests. So output_statement() always emits
ECPGst_* symbols in the preprocessed code instead of
ECPGst_normal/prepnormal and numeric value for the
other two cases. This way only 7 regression tests' source
has changed instead of 45... There are less
    1 -> ECPGst_execute and
    2 -> ECPGst_exec_immediate
changes than
    ECPGst_normal -> 0
changes would have been if I chose emitting the numeric value.

Is it acceptable?

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch N+1, fix auto-prepare

From
Michael Meskes
Date:
> OK, here's another approach. output_statement()'s interface
> is kept as the original, and not this function decides which

I still think this could be solved more easily.

> value it uses. I also introduced
>     static char *ecpg_statement_type_name[]
> for the textual names of the ECPGst_* symbols to keep the
> preprocessed code readable, and minimize the impact on the
> regression tests. So output_statement() always emits
> ECPGst_* symbols in the preprocessed code instead of
> ECPGst_normal/prepnormal and numeric value for the
> other two cases. This way only 7 regression tests' source
> has changed instead of 45... There are less
>     1 -> ECPGst_execute and
>     2 -> ECPGst_exec_immediate
> changes than
>     ECPGst_normal -> 0
> changes would have been if I chose emitting the numeric value.
> 
> Is it acceptable?

Yes sure.

I changed some small parts of your patch (see above) and will commit in a few
minutes. Just running regression tests.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL


Re: ECPG patch N+1, fix auto-prepare

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
>> OK, here's another approach. output_statement()'s interface
>> is kept as the original, and not this function decides which
>>     
>
> I still think this could be solved more easily.
>   

Thanks very much for committing it.

But I don't understand your change. My code was:

=====================================
ecpg.addons:
ECPG: stmtDeleteStmt block
ECPG: stmtInsertStmt block
ECPG: stmtSelectStmt block
ECPG: stmtUpdateStmt block       { output_statement($1, 1, auto_prepare ? ECPGst_prepnormal :
ECPGst_normal); }
=====================================
output.c:
static char *ecpg_statement_type_name[] = {       "ECPGst_normal",       "ECPGst_execute",
"ECPGst_exec_immediate",      "ECPGst_prepnormal"
 
};

void
output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
{
       fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat,
force_indicator, connection ? connection : "NULL", questionmarks);       if (st == ECPGst_normal || st ==
ECPGst_prepnormal)      {               fprintf(yyout, "%s, \"", ecpg_statement_type_name[st]);
output_escaped_str(stmt,false);               fputs("\", ", yyout);       }       else               fprintf(yyout,
"%s,%s, ", ecpg_statement_type_name[st],
 
stmt);
=====================================

So the ECPGst_normal vs. prepnormal is decided at the caller
and output_statement() is simplified a bit vs the original.

Your code is:

=====================================
ecpg.addons:
ECPG: stmtDeleteStmt block
ECPG: stmtInsertStmt block
ECPG: stmtSelectStmt block
ECPG: stmtUpdateStmt block       { output_statement($1, 1, ECPGst_prepnormal); }
=====================================
output.c:
static char *ecpg_statement_type_name[] = {       "ECPGst_normal",       "ECPGst_execute",
"ECPGst_exec_immediate",      "ECPGst_prepnormal"
 
};

void
output_statement(char *stmt, int whenever_mode, enum ECPG_statement_type st)
{       fprintf(yyout, "{ ECPGdo(__LINE__, %d, %d, %s, %d, ", compat,
force_indicator, connection ? connection : "NULL", questionmarks);       if (st == ECPGst_execute || st ==
ECPGst_exec_immediate)      {               fprintf(yyout, "%s, %s, ", ecpg_statement_type_name[st],
 
stmt);       }       else       {               if (st == ECPGst_prepnormal && auto_prepare)
fputs("ECPGst_prepnormal,\"", yyout);               else                       fputs("ECPGst_normal, \"", yyout);
 
               output_escaped_str(stmt, false);               fputs("\", ", yyout);       }
=====================================

Your code in ecpg.addons calls output_statement()
unconditionally with ECPGst_prepnormal and
output_statement() decides what to do with the
"auto_prepare" global variable. Your code doesn't
seem more readable than mine, but does the same
with the currently existing callers.

>> value it uses. I also introduced
>>     static char *ecpg_statement_type_name[]
>> for the textual names of the ECPGst_* symbols to keep the
>> preprocessed code readable, and minimize the impact on the
>> regression tests. So output_statement() always emits
>> ECPGst_* symbols in the preprocessed code instead of
>> ECPGst_normal/prepnormal and numeric value for the
>> other two cases. This way only 7 regression tests' source
>> has changed instead of 45... There are less
>>     1 -> ECPGst_execute and
>>     2 -> ECPGst_exec_immediate
>> changes than
>>     ECPGst_normal -> 0
>> changes would have been if I chose emitting the numeric value.
>>
>> Is it acceptable?
>>     
>
> Yes sure.
>
> I changed some small parts of your patch (see above) and will commit in a few
> minutes. Just running regression tests.
>   

Okay, I have to rebase my SQLDA and DESCRIBE
patches again, since the regression tests' results may
have changed beause of this patch. I will post them soon.

Again, thanks for committing it.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch N+1, fix auto-prepare

From
Michael Meskes
Date:
On Wed, Dec 16, 2009 at 11:54:41AM +0100, Boszormenyi Zoltan wrote:
> Your code in ecpg.addons calls output_statement()
> unconditionally with ECPGst_prepnormal and
> output_statement() decides what to do with the
> "auto_prepare" global variable. Your code doesn't
> seem more readable than mine, but does the same
> with the currently existing callers.

It better should do the same. :-)

Maybe finding it simpler this way just comes from me being used to the way this
part of the source code works. It's essantially the same, I only moved that one
auto_prepare test out of the parser.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL


Re: ECPG patch 2, SQLDA support

From
Boszormenyi Zoltan
Date:
Rebased to current CVS HEAD after my auto-prepare fix
was added. The new regression tests' C source has changed
because of this.

The other two patches don't need re-posting, as
they apply with minimal fuzz and no rejects and
their regression tests work as-is.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

ECPG SQLDA support

From
Boszormenyi Zoltan
Date:
Hi,

new patch attached.

Per Michael's request, a DB2 / Sybase compatible
SQLDA structure is implemented for ECPG's native mode.
The Informix-compatible structure is only for compat mode.
The sqlda.h header switches between the two different
structures depending on a new #define introduced in
and added to the generated C source by the preprocessor
in compat-mode. Also, per discussion with Michael,
     FETCH ... USING DESCRIPTOR sqlda
is also accepted by the grammar in native mode, too.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

ECPG DESCRIBE [OUTPUT] support

From
Boszormenyi Zoltan
Date:
Hi,

new patch is attached. Modified according to
the new DB2 / Sybase compatible SQLDA structure.
ECPGdescribe() has an "int compat" parameter, because:
- the (struct prepared_statement *)->stmt ->compat is not set, and
- it's more sensible to use the compat mode of the
  ECPGdescribe() caller, because different source files can be
  compiled with different (native or compat) modes.
The Informix-specific syntax "DESCRIBE ... INTO sqlda" is also
accepted in native mode now.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

ECPG out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Hi,

new patch attached, rebased to the latest
SQLDA and DESCRIBE patches.
This is the variant with support in native mode.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG SQLDA support

From
Alvaro Herrera
Date:
Boszormenyi Zoltan wrote:

I happened to notice this by chance:

> + #if (LONG_BIT == 64)
> + #define    SQLINT8        ECPGt_long
> + #define    SQLSERIAL8    ECPGt_long
> + #else
> + #define    SQLINT8        ECPGt_long_long
> + #define    SQLSERIAL8    ECPGt_long_long
> + #endif

I'm not sure how portable is the LONG_BIT business.  We don't seem to
use it anywhere else (hmm, but then we do use CHAR_BIT elsewhere)

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
The PostgreSQL Company - Command Prompt, Inc.


Re: ECPG SQLDA support

From
Boszormenyi Zoltan
Date:
Alvaro Herrera írta:
> Boszormenyi Zoltan wrote:
>
> I happened to notice this by chance:
>
>   
>> + #if (LONG_BIT == 64)
>> + #define    SQLINT8        ECPGt_long
>> + #define    SQLSERIAL8    ECPGt_long
>> + #else
>> + #define    SQLINT8        ECPGt_long_long
>> + #define    SQLSERIAL8    ECPGt_long_long
>> + #endif
>>     
>
> I'm not sure how portable is the LONG_BIT business.  We don't seem to
> use it anywhere else (hmm, but then we do use CHAR_BIT elsewhere)
>   

I specifically looked for a portable solution, as   #if sizeof(...) == N
is not evaluated at compile time.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG SQLDA support

From
Tom Lane
Date:
Alvaro Herrera <alvherre@commandprompt.com> writes:
> I'm not sure how portable is the LONG_BIT business.

I think checking SIZEOF_LONG would be preferred, since that's what
we use elsewhere.  Although actually I wonder why this code exists
at all --- wouldn't it be easier to make these depend on "int64"?
        regards, tom lane


Re: ECPG SQLDA support

From
Boszormenyi Zoltan
Date:
Tom Lane írta:
> Alvaro Herrera <alvherre@commandprompt.com> writes:
>   
>> I'm not sure how portable is the LONG_BIT business.
>>     
>
> I think checking SIZEOF_LONG would be preferred, since that's what
> we use elsewhere.  Although actually I wonder why this code exists
> at all --- wouldn't it be easier to make these depend on "int64"?
>
>             regards, tom lane
>   

Don't ask me why ECPGt_long_long and ECPGt_unsigned_long_long
exist. But they do, and the libecpg code has some   #ifdef HAVE_LONG_LONG_INT_64
surrounding code handling them. Maybe it would've been better to be
consistent with that coding.

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG DESCRIBE [OUTPUT] support

From
Robert Haas
Date:
On Mon, Jan 4, 2010 at 1:51 PM, Boszormenyi Zoltan <zb@cybertec.at> wrote:
> new patch is attached. Modified according to
> the new DB2 / Sybase compatible SQLDA structure.
> ECPGdescribe() has an "int compat" parameter, because:
> - the (struct prepared_statement *)->stmt ->compat is not set, and
> - it's more sensible to use the compat mode of the
>  ECPGdescribe() caller, because different source files can be
>  compiled with different (native or compat) modes.
> The Informix-specific syntax "DESCRIBE ... INTO sqlda" is also
> accepted in native mode now.

For tracking purposes, can you add a "Patch"-type comment for each of
these to the relevant entry on commitfest.postgresql.org?

Thanks,

...Robert


Re: ECPG SQLDA support

From
Michael Meskes
Date:
On Mon, Jan 04, 2010 at 07:39:14PM +0100, Boszormenyi Zoltan wrote:
> new patch attached.
> ...

Great job Zoltan, committed.

> The sqlda.h header switches between the two different
> structures depending on a new #define introduced in
> and added to the generated C source by the preprocessor

I changed this to use the already existing _ECPG_INFORMIX_H define.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL


Re: ECPG SQLDA support

From
Michael Meskes
Date:
On Mon, Jan 04, 2010 at 02:32:56PM -0500, Tom Lane wrote:
> I think checking SIZEOF_LONG would be preferred, since that's what
> we use elsewhere.  Although actually I wonder why this code exists
> at all --- wouldn't it be easier to make these depend on "int64"?

It does use int64. However, ecpg uses HAVE_LONG_LONG_INT64 to decide whether
it's datatype ECPGt_long_long exists. I changed the patch to use the same
define as usual.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL


Re: ECPG DESCRIBE [OUTPUT] support

From
Boszormenyi Zoltan
Date:
Hi,

I just saw that you committed the DESCRIBE patch.

Please, also add this small change that adds ecpg_raise()
calls to ECPGdescribe() to return the proper sqlca error
in error paths for:
- unsupported call for DESCRIBE INPUT
- no such connection name
- no such prepared statement

Thanks and best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG DESCRIBE [OUTPUT] support

From
Michael Meskes
Date:
On Fri, Jan 15, 2010 at 01:16:18PM +0100, Boszormenyi Zoltan wrote:
> Please, also add this small change that adds ecpg_raise()
> calls to ECPGdescribe() to return the proper sqlca error
> in error paths for:
> ...

Done.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ: 179140304, AIM/Yahoo/Skype: michaelmeskes, Jabber: meskes@jabber.org
VfL Borussia! Forca Barca! Go SF 49ers! Use: Debian GNU/Linux, PostgreSQL


ECPG documentation patch

From
Boszormenyi Zoltan
Date:
Hi,

here's the documentation patch for the new ECPG features.

- I changed the order of sections "Using Descriptor Areas" and
  "Informix compatibility mode"
- split the "Using Descriptor Areas", so it now have two subsections:
  "Named SQL Descriptor Areas" and "SQLDA Descriptor Areas".
  The second one talks about the native mode SQLDA only.
- Documented DESCRIBE and the USING/INTO quirks.
- Documented the "string" pseudo-type in compat mode
- Modified the section name "Additional embedded SQL statements",
  it now reads "Additional/missing embedded SQL statements" and
  documented the lack of "FREE cursor_name" statement and
  the behaviour of "FREE statement_name" statement.
- Documented the Informix-compatible SQLDA under the
  "Informix compatibility mode" section.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Fix auto-prepare #2

From
Boszormenyi Zoltan
Date:
Hi,

we have found that auto-prepare causes a problem if the connection
is closed and re-opened and the previously prepared query is issued
again. The application gets back a error code -201 which seems bogus
and it turned out to be a missing
    return (false);
after ecpg_raise(ECPG_SQLSTATE_INVALID_SQL_STATEMENT_NAME)
on line 1756 in execute.c, so the error handling later in the same function
masqueraded this error. But fixing this doesn't solve the main problem
that the query is in the auto-prepared query cache but not is not prepared
on the server if the connection is closed and re-opened.

The same problem may also arise if the same query is used over multiple
simultaneous connections.

This fix is that after looking up the query and having it found in the cache
we also have to check whether this query was prepared in the current
connection. The attached patch implements this fix and solves the problem
described above. Also, the missing "return false;" is also added to ECPGdo()
in execute.c.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: Fix auto-prepare #2

From
Takahiro Itagaki
Date:
Hi, I'm reviewing your patch and have a couple of comments.

Boszormenyi Zoltan <zb@cybertec.at> wrote:

> we have found that auto-prepare causes a problem if the connection
> is closed and re-opened and the previously prepared query is issued
> again.

You didn't attach actual test cases for the bug, so I verified it
by executing the routines twice in ecpg/test/preproc/autoprep.pgc.
The attached "6-pg85-fix-auto-prepare-multiconn-3-test.patch"
is an additional regression test for it. Is it enough for your case?

> This fix is that after looking up the query and having it found in the cache
> we also have to check whether this query was prepared in the current
> connection. The attached patch implements this fix and solves the problem
> described above. Also, the missing "return false;" is also added to ECPGdo()
> in execute.c.

In addition to the two issues, I found memory leaks by careless calls
of ecpg_strdup() in ecpg_auto_prepare(). Prepared stetements also might
leak in a error path. I tryd to fix both of them in the attached
"6-pg85-fix-auto-prepare-multiconn-3.patch", but please recheck the issues.

Regards,
---
Takahiro Itagaki
NTT Open Source Software Center


Attachment

Re: Fix auto-prepare #2

From
Boszormenyi Zoltan
Date:
Hi,

Takahiro Itagaki írta:
> Hi, I'm reviewing your patch and have a couple of comments.
>

thanks for the review, comments below.

> Boszormenyi Zoltan <zb@cybertec.at> wrote:
>
>
>> we have found that auto-prepare causes a problem if the connection
>> is closed and re-opened and the previously prepared query is issued
>> again.
>>
>
> You didn't attach actual test cases for the bug, so I verified it
> by executing the routines twice in ecpg/test/preproc/autoprep.pgc.
> The attached "6-pg85-fix-auto-prepare-multiconn-3-test.patch"
> is an additional regression test for it. Is it enough for your case?
>

Yes, my bad that I didn't attach a test case.
The modification to the autoprep.pgc is enough to trigger it
because the INSERTs are auto-prepared.

>> This fix is that after looking up the query and having it found in the cache
>> we also have to check whether this query was prepared in the current
>> connection. The attached patch implements this fix and solves the problem
>> described above. Also, the missing "return false;" is also added to ECPGdo()
>> in execute.c.
>>
>
> In addition to the two issues, I found memory leaks by careless calls
> of ecpg_strdup() in ecpg_auto_prepare().

Good catch, thanks. I didn't look in ECPGprepare(),
so I just copied the statement and the logic from the ELSE branch.

>  Prepared stetements also might
> leak in a error path.

Yes, it is true as well, the statement name ("ecpgN") is not freed
in the error path in ECPGdo().

However, thinking a little more about this code:
    con = ecpg_get_connection(connection_name);
    prep = ecpg_find_prepared_statement(stmtID, con, NULL);
    if (!prep && !ECPGprepare(...))

I only wanted to call ECPGprepare() in case it wasn't already prepared.
ECPGprepare() also checks for the statement being already prepared
with ecpg_find_prepared_statement() but in case it exists it
DEALLOCATEs the statement and PREPAREs again so there's
would be no saving for auto-prepare calling it unconditionally and
we are doing a little extra work by calling ecpg_find_prepared_statement()
twice. We need a common function shared by ECPGprepare() and
ecpg_auto_prepare() to not do extra work in the auto-prepare case.

The attached patch implements this and also your leak fixes
plus includes your change for the autoprep.pgc regression test.

Thanks and best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Michael Meskes
Date:
Zoltan,

while testing your patch I went through the test cases and found this in outofscope.pgc:

> + #include <inttypes.h>

As we know by now this won't work. :-)

Besides, would you mind simplifying the test case a little bit? There is no
need to have it test all the sqlda stuff, too. I don't mind having two cases
testing sqlda but this makes testing out of scope variable handling more
difficult especially with sqlda being a rather complex system with different
struct definitions and so on.

Also I wonder why you added struct.pgc. It seems to build and run without a
problem on a non-patched system. Is it an additional test that just happened to
be included here?

Michael

-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL


Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> Zoltan,
>
> while testing your patch I went through the test cases and found this in outofscope.pgc:
>
>   
>> + #include <inttypes.h>
>>     
>
> As we know by now this won't work. :-)
>   

Okay, I will fix it. :-) I forgot it's in there as well.

> Besides, would you mind simplifying the test case a little bit? There is no
> need to have it test all the sqlda stuff, too. I don't mind having two cases
> testing sqlda but this makes testing out of scope variable handling more
> difficult especially with sqlda being a rather complex system with different
> struct definitions and so on.
>   

Okay.

> Also I wonder why you added struct.pgc. It seems to build and run without a
> problem on a non-patched system. Is it an additional test that just happened to
> be included here?
>   

It was included in there because the first symptom
that lead to this patch under Informix compat mode that
a simple struct variable wasn't properly unrolled because
adjust_informix() lost informiation about the type.
Did I accidentally move it to native mode? I'll move it back.

I will send an updated patch.

Thanks,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Boszormenyi Zoltan írta:
> I will send an updated patch.
>

Attached with the requested modifications.

Best regards,
Zoltán Böszörményi

--
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/


Attachment

Re: Fix auto-prepare #2

From
Takahiro Itagaki
Date:
Boszormenyi Zoltan <zb@cybertec.at> wrote:

> I only wanted to call ECPGprepare() in case it wasn't already prepared.
> ECPGprepare() also checks for the statement being already prepared
> with ecpg_find_prepared_statement() but in case it exists it
> DEALLOCATEs the statement and PREPAREs again so there's
> would be no saving for auto-prepare calling it unconditionally and
> we are doing a little extra work by calling ecpg_find_prepared_statement()
> twice. We need a common function shared by ECPGprepare() and
> ecpg_auto_prepare() to not do extra work in the auto-prepare case.
> 
> The attached patch implements this and also your leak fixes
> plus includes your change for the autoprep.pgc regression test.

Good. I think the patch is ready to commit.

A comment for committer (Michael?) :
I was cofused by the AddStmtToCache's 2nd argument "char *stmtID"
because it doesn't have a const. Should it be "const char *" ?
If the argument has a const, callers assume that they can pass
a not-strdup'ed string as the argument.

Regards,
---
Takahiro Itagaki
NTT Open Source Software Center




Re: Fix auto-prepare #2

From
Michael Meskes
Date:
Takahiro-san,

> Good. I think the patch is ready to commit.

Thanks for reviewing it. I just committed the patch.

> A comment for committer (Michael?) :
> I was cofused by the AddStmtToCache's 2nd argument "char *stmtID"
> because it doesn't have a const. Should it be "const char *" ?
> If the argument has a const, callers assume that they can pass
> a not-strdup'ed string as the argument.

Valid point, I can see no reason for not making this a "const char *". So let's
try.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL


Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Michael Meskes
Date:
> diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/compat_informix-struct.c
pgsql.4.1/src/interfaces/ecpg/test/expected/compat_informix-struct.c
> ...
> +     /* Test DECLARE ... SELECT ... INTO with struct type */
> + 
> +     ECPGset_var( 0, &( myvar ), __LINE__);\
> +  ECPGset_var( 1, &( mynullvar ), __LINE__);\
> +  ECPG_informix_reset_sqlca(); /* declare mycur cursor for select * from a1 */
> + #line 45 "struct.pgc"
> + 
> +     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare mycur cursor for select * from a1", ECPGt_EOIT, 
> +     ECPGt_int,&(myvar.id),(long)1,(long)1,sizeof(int), 
> ...

Why does the preproc spit out ECPGset_var's but no ECPGget_var's in this test case? 

Michael

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL


Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
>> diff -dcrpN pgsql.orig/src/interfaces/ecpg/test/expected/compat_informix-struct.c
pgsql.4.1/src/interfaces/ecpg/test/expected/compat_informix-struct.c
>> ...
>> +     /* Test DECLARE ... SELECT ... INTO with struct type */
>> + 
>> +     ECPGset_var( 0, &( myvar ), __LINE__);\
>> +  ECPGset_var( 1, &( mynullvar ), __LINE__);\
>> +  ECPG_informix_reset_sqlca(); /* declare mycur cursor for select * from a1 */
>> + #line 45 "struct.pgc"
>> + 
>> +     { ECPGdo(__LINE__, 1, 1, NULL, 0, ECPGst_normal, "declare mycur cursor for select * from a1", ECPGt_EOIT, 
>> +     ECPGt_int,&(myvar.id),(long)1,(long)1,sizeof(int), 
>> ...
>>     
>
> Why does the preproc spit out ECPGset_var's but no ECPGget_var's in this test case? 
>   

Because there's no ECPGget_var()s emitted for
- global variables
- variables in the same function

ECPGget_var() is only used in case the cursor declaration
used INTO/USING and it's in a different function from
the one where OPEN/FETCH/CLOSE reside. But this
cannot be determined easily, e.g. short of making ECPG
a two-pass precompiler, so ECPGset_var() is always used.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Michael Meskes
Date:
On Fri, Jan 22, 2010 at 06:11:51PM +0100, Boszormenyi Zoltan wrote:
> > Why does the preproc spit out ECPGset_var's but no ECPGget_var's in this test case? 
> >   
> 
> Because there's no ECPGget_var()s emitted for
> - global variables
> - variables in the same function
> 
> ECPGget_var() is only used in case the cursor declaration
> used INTO/USING and it's in a different function from
> the one where OPEN/FETCH/CLOSE reside. But this
> cannot be determined easily, e.g. short of making ECPG
> a two-pass precompiler, so ECPGset_var() is always used.

This shows some well thought implementation. But what I was wondering about was
why this is used as test case. While I see the need to test this part of ecpg I
thought this test case was added because it showed a problem without your
changes.

Michael

-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL


Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Fri, Jan 22, 2010 at 06:11:51PM +0100, Boszormenyi Zoltan wrote:
>   
>>> Why does the preproc spit out ECPGset_var's but no ECPGget_var's in this test case? 
>>>   
>>>       
>> Because there's no ECPGget_var()s emitted for
>> - global variables
>> - variables in the same function
>>
>> ECPGget_var() is only used in case the cursor declaration
>> used INTO/USING and it's in a different function from
>> the one where OPEN/FETCH/CLOSE reside. But this
>> cannot be determined easily, e.g. short of making ECPG
>> a two-pass precompiler, so ECPGset_var() is always used.
>>     
>
> This shows some well thought implementation.

Thanks. But the truth is that your comment about "this
adjust_informix() hack goes into native mode only over
my dead body" made me come up with this change and
the reasoning. :-) Thus if some code with cursors does
everything in one function then only some useless
ECPGset_var() calls are added by the preprocessor,
making the change the least intrusive for old regression tests.

>  But what I was wondering about was
> why this is used as test case. While I see the need to test this part of ecpg I
> thought this test case was added because it showed a problem without your
> changes.
>   

The problem that popped up first was that adjust_informix()
didn't properly deal with structs, remember? I tried some
small changes to fix that but they turned out to be improper
ones. The small changes worked for the initial problem,
i.e. IIRC in some cases adjust_informix() was bypassed
and the struct/union members were unrolled properly
for Informix compat mode, too. The regression test
"compat_informix/struct.pgc" shows this case. Then our
client showed a much larger programme which actually
used cursors in an event driver way. E.g. PgUp/PgDn
called different functions that contained only FETCH NEXT
or FETCH PRIOR. This was a curses based terminal programme
and my first little patch that solved only the struct unrolling case
failed in this case, because either ECPG segfaulted in
adjust_informix() or the code that ECPG produced for the
FETCH statements didn't have the proper output variables.
This is lead to the changes in the patch, which can be
summarized as:
1. track function names via the lexer (to minimize the impact  of ECPGget_var(), now we can compare the function name
wherethe cursor was DECLAREd and is used)
 
2. track type names for structs/unions to be able to emit   (* ( typename *) &var) in adjust_informix(), and
3. rewriting adjust_informix() to handle struct/union

The result is that cursors handling statements (OPEN/FETCH/MOVE)
can now be safely put into a different function from where
it was DECLAREd. And this makes possible to use ECPG
in event driven code, which is a feature that I think worth
considering making available in native mode, too. This is
why adjust_informix() was also renamed. And while I agree
with your comment about that "this can lead to dangerous
programming", I think the only thing needed is to document
the safety borders, not to prevent crossing them. C is about
"living la vida loca". ;-)

The regression test introduced (preproc/outofscope.pgc) tries
to show this functionality. Currently (without the patch) this
test makes ECPG abort in ecpg_type_name().

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Michael Meskes
Date:
On Sun, Jan 24, 2010 at 07:25:24PM +0100, Boszormenyi Zoltan wrote:
> The problem that popped up first was that adjust_informix()
> didn't properly deal with structs, remember? I tried some

Yes, that's what made me wondering.

> i.e. IIRC in some cases adjust_informix() was bypassed
> and the struct/union members were unrolled properly
> for Informix compat mode, too. The regression test
> "compat_informix/struct.pgc" shows this case. Then our

Now this is what I don't get. Shouldn't this test use different functions to
really show this problem? Isn't it hidden now by the new functionality of not
spitting out ECPGget_var's?

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL


Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Sun, Jan 24, 2010 at 07:25:24PM +0100, Boszormenyi Zoltan wrote:
>   
>> The problem that popped up first was that adjust_informix()
>> didn't properly deal with structs, remember? I tried some
>>     
>
> Yes, that's what made me wondering.
>
>   
>> i.e. IIRC in some cases adjust_informix() was bypassed
>> and the struct/union members were unrolled properly
>> for Informix compat mode, too. The regression test
>> "compat_informix/struct.pgc" shows this case. Then our
>>     
>
> Now this is what I don't get.

I may have been unclear. My first attempts at solving it
either basically bypassed adjust_informix() or tried to
unroll the structs *before* calling adjust_informix().
IIRC, your comment about that solution was something
like "unrolling should be done at only one place centrally".
Which I agreed after learning what dump_variables() and
ECPGdump_a_type() do.

>  Shouldn't this test use different functions to
> really show this problem?

I don't think so. The problem only happened in case of
cursors because this was the only case when adjust_informix()
was called and the lack of handling struct/union there
was the problem. The final "else" branch used ecpg_type_name()
which calls abort() in case of unknown types.

>  Isn't it hidden now by the new functionality of not
> spitting out ECPGget_var's?
>   

No. This problem is hidden by the fact the adjust_informix()
(now adjust_outofscope_cursor_vars()) now handles structs/unions
properly and the struct members are properly unrolled by
ECPGdump_a_type().

The "not spitting out ECPGget_var()" part is about tidying
the preprocessed C source. As I wrote previously, globals
don't need transformation and nor the locals in case the
OPEN/FETCH statements are in the same function as DECLARE.

But considering all the above, we might not need the new
compat_informix/struct.pgc regression test. I think it was tested
already in e.g. preproc/array_of_struct.pgc and preproc/type.pgc
and the new feature (if accepted) is a unified one, it would show
the problem for native mode as well.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Michael Meskes
Date:
On Mon, Jan 25, 2010 at 07:52:05PM +0100, Boszormenyi Zoltan wrote:
> But considering all the above, we might not need the new
> compat_informix/struct.pgc regression test. I think it was tested
> already in e.g. preproc/array_of_struct.pgc and preproc/type.pgc
> and the new feature (if accepted) is a unified one, it would show
> the problem for native mode as well.

That was my feeling too and the reason for these questions. Again, this has
nothing to do with the feature you implemented, it was just about this special
test.

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL


Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
> On Mon, Jan 25, 2010 at 07:52:05PM +0100, Boszormenyi Zoltan wrote:
>   
>> But considering all the above, we might not need the new
>> compat_informix/struct.pgc regression test. I think it was tested
>> already in e.g. preproc/array_of_struct.pgc and preproc/type.pgc
>> and the new feature (if accepted) is a unified one, it would show
>> the problem for native mode as well.
>>     
>
> That was my feeling too and the reason for these questions. Again, this has
> nothing to do with the feature you implemented, it was just about this special
> test.
>   

Should I send you a new patch without this regression test
or do you delete it before applying the patch?

BTW, thank you very much for the review.

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Michael Meskes
Date:
> Should I send you a new patch without this regression test
> or do you delete it before applying the patch?

Na, I will just remove it, no need to worry.

Michael
--
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL


Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Boszormenyi Zoltan
Date:
Michael Meskes írta:
>> Should I send you a new patch without this regression test
>> or do you delete it before applying the patch?
>>     
>
> Na, I will just remove it, no need to worry.
>
> Michael
>   

Thanks for applying it. You seem to have accidentally
removed the outofscope.pgc test, too. The test results are there
and the test is wired up in Makefile and in ecpg_schedule[_tcp]
but the actual regression test code is missing:

make[2]: *** No rule to make target `outofscope', needed by `all'.  Stop.
make[2]: Leaving directory
`/home/zozo/Schönig-számlák/leoni/2/new/new/new/8/pgsql/src/interfaces/ecpg/test/preproc'
make[1]: *** [all] Error 2
make[1]: Leaving directory
`/home/zozo/Schönig-számlák/leoni/2/new/new/new/8/pgsql/src/interfaces/ecpg/test'
make: *** [check] Error 2

Best regards,
Zoltán Böszörményi

-- 
Bible has answers for everything. Proof:
"But let your communication be, Yea, yea; Nay, nay: for whatsoever is more
than these cometh of evil." (Matthew 5:37) - basics of digital technology.
"May your kingdom come" - superficial description of plate tectonics

----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/



Re: ECPG patch 4.1, out-of-scope cursor support in native mode

From
Michael Meskes
Date:
On Tue, Jan 26, 2010 at 10:56:52AM +0100, Boszormenyi Zoltan wrote:
> Thanks for applying it. You seem to have accidentally
> removed the outofscope.pgc test, too. The test results are there

Yup, my bad. I'm already trying to recover and testing. Apparently the files
weren't added but I didn't notice. 

Michael
-- 
Michael Meskes
Michael at Fam-Meskes dot De, Michael at Meskes dot (De|Com|Net|Org)
Michael at BorussiaFan dot De, Meskes at (Debian|Postgresql) dot Org
ICQ 179140304, AIM/Yahoo/Skype michaelmeskes, Jabber meskes@jabber.org
VfL Borussia! Força Barça! Go SF 49ers! Use Debian GNU/Linux, PostgreSQL