Visual FoxPro application calls Postgres psqlodbc driver 9.3.0400 Both are 32 bit application running in Windows 7 x64
This call causes Buffer Ovverrun exception in psqlodbc35w.dll with stack trace below. How to fix the issue ? psqlodbc is open source applicaton written in C and probably compiled by Visual Studio., maybe it is possible to chnage it in some was so that exceptino does not occur ? Visual Studio 2015 Community Edition is installed.
After crash Visual Studio 2015 Community Edition debugger is invoked. It shows stack trace:
> psqlodbc35w.dll!__crt_debugger_hook() Unknown
psqlodbc35w.dll!__report_gsfailure() Line 315 + 0x7 bytes C
psqlodbc35w.dll!SC_create_errorinfo(const StatementClass_ * self) Line 1423 + 0xa bytes C
psqlodbc35w.dll!PGAPI_StmtError(void * hstmt, short RecNumber, unsigned char * szSqlState, long * pfNativeError, unsigned char * szErrorMsg, short cbErrorMsgMax, short * pcbErrorMsg, unsigned short flag) Line 1612 C
psqlodbc35w.dll!PGAPI_GetDiagField(short HandleType, void * Handle, short RecNumber, short DiagIdentifier, void * DiagInfoPtr, short BufferLength, short * StringLengthPtr) Line 280 C
psqlodbc35w.dll!SQLGetDiagFieldW(short fHandleType, void * handle, short iRecord, short fDiagField, void * rgbDiagInfo, short cbDiagInfoMax, short * pcbDiagInfo) Line 374 + 0x16 bytes C
odbc32(dot)dll!_VFreeErrors(at)4() + 0x401f bytes
odbc32(dot)dll!_SearchStatusCode(at)8() + 0x25 bytes
odbc32(dot)dll!_IsStmtPositioned(at)4() + 0x14 bytes
odbc32(dot)dll!_SQLExecute(at)4() - 0xfd3e bytes
odbc32(dot)dll!_SQLExecDirect(at)12() + 0x77 bytes
vfp9r.dll!0c3904c6()
...
Debug window shows lot of loaded moduled and at end:
...
The thread 'Win32 Thread' (0x2778) has exited with code 0 (0x0).
A buffer overrun has occurred in alguss.EXE which has corrupted the program's internal state. Press Break to debug the program or Continue to terminate the program.
For more details please see Help topic 'How to debug Buffer Overrun Issues'.
Posted also in http://www.postgresql.org/message-id/1B88854920C942948F943E26B452E3A4@dell2
Update
Here is FoxPro code which causes crash. Crash occurs in odbc driver before query is sent to Postgres. Tables in query are not required to be present in database. Simply run query using postgres odbc official driver. Maybe using $ characters in query causes odbc crash.
SET TEXTMERGE ON
SET TEXTMERGE TO (sys(2015))
TEXT TEXTMERGE NOSHOW
CREATE or replace FUNCTION public.f_infA()
RETURNS TABLE (
kuupaev date,
nimi text,
tasudok text,
regnr text,
kmprotsent text,
neto numeric,
myyk numeric,
erisus01 bool,
erisus02 bool,
erisus03 bool
) AS $f_InfA$
WITH
myyk as (
SELECT
dok.kuupaev,
dok.tasudok,
klient.regnr,
CASE when klient.regnr is null OR klient.regnr='' then klient.nimi else '' end::char(80) as nimi,
20 as kmprotsent,
k01+k011+k01erik as myyk20,
0 as myyk9,
MAX(klient.nimi)::char(80) as maxnimi,
bool_or(k01erik<>0) as erisus01,
bool_or(d09<>0) as erisus02,
SUM( ROUND( rid.hind * case when rid.kogus<>0 then rid.kogus else 1 end*
CASE when rid.kogpak<>0 then rid.kogpak else 1 end
/case when dok.doktyyp<>'Y' then 1 else 1+myygikoo.kmprotsent/100 end *
CASE when dok.raha=prpalk.pohiraha then 1
when dok.exchrate<>0 then dok.Exchrate else kurss.kurss end,2)
) as neto
FROM prpalk, tehing
JOIN dok ON tehing.dokumnr=dok.dokumnr
JOIN rid ON dok.dokumnr=rid.dokumnr
JOIN klient ON dok.klient=klient.kood
LEFT JOIN myygikoo ON rid.myygikood=myygikoo.myygikood or ( rid.myygikood is null and myygikoo.myygikood ='' )
LEFT JOIN kurss ON dok.raha=kurss.raha AND dok.kuupaev=kurss.kuupaev
LEFT JOIN toode ON rid.toode=toode.toode
WHERE (rid.toode is null or toode.grupp<>'S' OR rid.toode='LE' or (toode.klass like '%T%' AND toode.klass not like '%E%'
AND toode.klass not like '%M%')) and
tehing.alusdok='LG' AND ( (k01+k011+k01erik)<>0 )
AND klient.nimi not ilike '%AUDIITORBÜROO%'
AND klient.nimi not ilike '%ADVOKAADIBÜROO%'
AND klient.nimi not ilike 'Notar %'
AND klient.nimi not ilike '% Notar'
AND rid.hind <> 0 -- Et ei tekiks arvetel taara 0 hinnaga väljastamisel erisuse koodi 03
AND klient.nimi not ilike 'Eraisik'
AND klient.nimi not ilike 'Jaeostja'
and not klient.kmdkeeld
GROUP BY 1,2,3,4,5,6,7
union all
SELECT
dok.kuupaev,
dok.tasudok,
klient.regnr,
CASE when klient.regnr is null OR klient.regnr='' then klient.nimi else '' end::char(80) as nimi,
9,
0 as myyk20,
k02+k021 as myyk9,
MAX(klient.nimi)::char(80) as maxnimi,
bool_or(k01erik<>0) as erisus01,
bool_or(d09<>0) as erisus02,
SUM( ROUND( rid.hind * case when rid.kogus<>0 then rid.kogus else 1 end*
CASE when rid.kogpak<>0 then rid.kogpak else 1 end
/case when dok.doktyyp<>'Y' then 1 else 1+myygikoo.kmprotsent/100 end *
CASE when dok.raha=prpalk.pohiraha then 1
when dok.exchrate<>0 then dok.Exchrate else kurss.kurss end,2)
) as neto
FROM prpalk, tehing
JOIN dok ON tehing.dokumnr=dok.dokumnr
JOIN rid ON dok.dokumnr=rid.dokumnr
JOIN klient ON dok.klient=klient.kood
LEFT JOIN myygikoo ON rid.myygikood=myygikoo.myygikood or ( rid.myygikood is null and myygikoo.myygikood ='' )
LEFT JOIN kurss ON dok.raha=kurss.raha AND dok.kuupaev=kurss.kuupaev
LEFT JOIN toode ON rid.toode=toode.toode
WHERE (rid.toode is null or toode.grupp<>'S' OR rid.toode='LE' or (toode.klass like '%T%' AND toode.klass not like '%E%'
AND toode.klass not like '%M%')) and
tehing.alusdok='LG' AND (k02+k021)<>0
AND klient.nimi not ilike '%AUDIITORBÜROO%'
AND klient.nimi not ilike '%ADVOKAADIBÜROO%'
AND klient.nimi not ilike 'Notar %'
AND klient.nimi not ilike '% Notar'
AND rid.hind <> 0 -- Et ei tekiks arvetel taara 0 hinnaga väljastamisel erisuse koodi 03
AND klient.nimi not ilike 'Eraisik'
AND klient.nimi not ilike 'Jaeostja'
and not klient.kmdkeeld
GROUP BY 1,2,3,4,5,6,7
union all
SELECT
omrid.adkuupaev,
omrid.ettemarve,
klient.regnr,
CASE when klient.regnr is null OR klient.regnr='' then klient.nimi else '' end::char(80) as nimi,
CASE when sum(k01+k011+k01erik)<>0 then 20 else 9 end,
CASE when sum(k01+k01erik+k011)<>0 then
sum( ROUND(
case when omrid.hinnalis='LM' then -omrid.tasusumma else omrid.tasusumma end *
case when omrid.kogus<>0 then omrid.kogus else 1 end *
case when omrid.raha=prpalk.pohiraha then 1 else
case when omrid.exchrate<>0 then omrid.Exchrate else kurss.kurss end END,2))
else 0 end as myyk20,
CASE when sum(k02+k021)<>0 then
sum( ROUND(
case when omrid.hinnalis='LM' then -omrid.tasusumma else omrid.tasusumma end *
case when omrid.kogus<>0 then omrid.kogus else 1 end *
case when omrid.raha=prpalk.pohiraha then 1 else
case when omrid.exchrate<>0 then omrid.Exchrate else kurss.kurss end END,2))
else 0 end as myyk9,
MAX(klient.nimi)::char(80) as maxnimi,
bool_or(k01erik<>0) as erisus01,
bool_or(d09<>0) as erisus02,
SUM( ROUND(
case when omrid.hinnalis='LM' then -omrid.tasusumma else omrid.tasusumma end *
case when omrid.kogus<>0 then omrid.kogus else 1 end *
case when omrid.raha=prpalk.pohiraha then 1 else
case when omrid.exchrate<>0 then omrid.Exchrate else kurss.kurss end END,2)) as neto
FROM prpalk, tehing
join omdok on tehing.dokumnr=omdok.dokumnr
JOIN omrid ON omrid.dokumnr=tehing.dokumnr -- AND tehing.doknr=omrid.ettemarve
JOIN klient ON omdok.klient=klient.kood
LEFT JOIN kurss ON omrid.raha=kurss.raha AND omrid.adkuupaev=kurss.kuupaev
WHERE tehing.alusdok in ('DT', 'DI') AND ( (k01+k01erik+ k011)>0 )
and omrid.ettemarve is not null and omrid.ettemarve is distinct from ''
AND klient.nimi not ilike '%AUDIITORBÜROO%'
AND klient.nimi not ilike '%ADVOKAADIBÜROO%'
AND klient.nimi not ilike 'Notar %'
AND klient.nimi not ilike '% Notar'
and not klient.kmdkeeld
GROUP BY 1,2,3,4
),
myyk1000 as (
SELECT
regnr,
nimi
FROM myyk
WHERE neto>0
GROUP BY 1,2
HAVING SUM(neto)>1000
)
SELECT
myyk.kuupaev,
myyk.maxnimi as nimi,
myyk.tasudok,
myyk.regnr,
'20' as kmprotsent,
round( SUM(myyk.neto),2) as neto,
round( SUM(myyk.myyk20),2) as myyk,
bool_or(erisus01) as erisus01,
bool_or(erisus02) as erisus02,
bool_or(myyk.kmprotsent=0) as erisus03
FROM myyk1000
JOIN myyk ON myyk1000.regnr=myyk.regnr AND myyk1000.nimi=myyk.nimi
GROUP BY 1,2,3,4
HAVING SUM(myyk.myyk20)<>0
UNION ALL
SELECT
myyk.kuupaev,
myyk.maxnimi as nimi,
myyk.tasudok,
myyk.regnr,
'9',
round( SUM(myyk.neto),2) ,
round( SUM(myyk.myyk9),2),
false,
bool_or(erisus02) as erisus02,
bool_or(myyk.kmprotsent=0) as erisus03
FROM myyk1000
JOIN myyk ON myyk1000.regnr=myyk.regnr AND myyk1000.nimi=myyk.nimi
GROUP BY 1,2,3,4
HAVING SUM(myyk.myyk9)<>0
UNION ALL
SELECT
myyk.kuupaev,
myyk.maxnimi as nimi,
myyk.tasudok,
myyk.regnr,
'erisus20',
round( SUM(myyk.neto),2) ,
round( SUM(myyk.myyk9),2),
false,
bool_or(erisus02) as erisus02,
false as erisus03
FROM myyk1000
JOIN myyk ON myyk1000.regnr=myyk.regnr AND myyk1000.nimi=myyk.nimi
GROUP BY 1,2,3,4
HAVING bool_or(erisus02)
ORDER BY nimi, kuupaev, tasudok
$f_infa$ LANGUAGE sql STABLE;
RESET ROLE;
ENDTEXT
cSqlFail = SET('textmerge',2)
SET TEXTMERGE TO
SQLEXEC(m.g_server.nConnhandle, FILETOSTR(m.cSqlFail) )
connection string used:
cConnString = "DRIVER={PostgreSQL Unicode};"+ ;
"DATABASE=test";"+ ;
"SERVER=localhost;" + ;
"PORT=5432;" + ;
"UID=user;" + ;
"Protocol=-0;" + ;
"B9=0"+ ;
";SSLMODE=allow"
(I am writing here as I can't format it in comments and it turns out to be messy)
Yes, your code causes a crash to occur. It looks like it is a bug in the driver, I would expect it to return an error but not cause VFP to stop executing.
Your code wasn't running neither from pgsl nor SQL console. The error I got was:
227: ERROR: unterminated dollar-quoted string at or near "$f_InfA$
and it also pointed here:
"ESET ROLE;
LINE 14: ) AS $f_InfA$
IOW you already had error in that quote where your dollar-quoted string was not terminated. If it is not a typo in the code you gave here, you have:
... bool
) AS $f_InfA$
...
$f_infa$ LANGUAGE sql STABLE;
RESET ROLE;
in your code. Since dollar-quoted strings are case sensitive as in XML, it is unterminated. Second should be "$f_InfA$" too.
Making it just $$ or $f_InfA$ both, it should work.
Driver shouldn't cause a crash though. HTH