Обсуждение: ODBC and Large Objects, FAQ not working

Поиск
Список
Период
Сортировка

ODBC and Large Objects, FAQ not working

От
"Christian Hang"
Дата:
Hi,

I know you've read this all before, as I went through most postings concerning this issue. But I 
haven't found a reply that helped me, so I hope I'll get one this way.

I want to hook up Microsoft Access (2000) via ODBC (6.400007) to my PostgreSQL server 
(6.5.3, Linux 2.2.10). Everything works fine, but I am having trouble inserting OLE objects into 
my database.

I created the "lo" type suggested in the ODBC FAQ and a basic table (CREATE TABLE ole (id 
int4, bild lo);) for testing purposes. But when I insert an OLE object, I get the error message
"Couldnt open large object for writing (ERROR #1)".
I attached the corresponding log.

I'd appreciate your help in this matter, as I tried any advice given in earlier postings concerning 
problems like this, but nothing would help.

Chris


----

Error log:

conn=144654652, query='BEGIN'
conn=144654652, query='INSERT INTO  "ole"  ("id") VALUES (1)'
conn=144654652, query='COMMIT'
conn=144654652, query='SELECT "oid","id","bild"  FROM "ole"  WHERE "oid" IS NULL'   [ fetched 0 rows ]
conn=144654652, query='SELECT "ole"."oid" FROM "ole" WHERE 
"id" = 1'   [ fetched 1 rows ]
conn=144654652, query='SELECT "oid","id","bild"  FROM "ole"  
WHERE "oid" = 19718'   [ fetched 1 rows ]
conn=144654652, query='SELECT "oid","id","bild"  FROM "ole"  WHERE "oid" = 19718'   [ fetched 1 rows ]
conn=144654652, query='SELECT "oid","id","bild"  FROM "ole"  WHERE "oid" = 19718'   [ fetched 1 rows ]
ERROR from backend during send_function: 'ERROR:  lo_lseek: invalid large obj descriptor (0)
'
STATEMENT ERROR: func=SQLPutData, desc='', errnum=1, errmsg='Couldnt open large object 
for writing.'                ------------------------------------------------------------
hdbc=144654652,stmt=144669180, result=0                manual_result=0, prepare=0, internal=0
bindings=0,bindings_allocated=0                parameters=145688992, parameters_allocated=1
statement_type=1,statement='INSERT INTO  "ole"  ("bild") VALUES (?)'                stmt_with_params='INSERT INTO
"ole" ("id") VALUES (1)'                data_at_exec=0, current_exec_param=0, put_data=1                currTuple=-1,
current_col=-1,lobj_fd=-1                maxRows=0, rowset_size=1, keyset_size=0, cursor_type=0, scroll_concurrency=1
            cursor_name='SQL_CUR089F79FC'                ----------------QResult Info -------------------------------
 
CONN ERROR: func=SQLPutData, desc='', errnum=0, errmsg='ERROR:  lo_lseek: invalid large 
obj descriptor (0)
'           ------------------------------------------------------------           henv=145686660, conn=144654652,
status=1,num_stmts=16           sock=145688632, stmts=145688672, lobj_type=19268           ---------------- Socket Info
-------------------------------          socket=308, reverse=0, errornumber=0, errormsg='(null)'
buffer_in=144660980,buffer_out=144665080           buffer_filled_in=53, buffer_filled_out=0, buffer_read_in=53
 
ERROR from backend during send_function: 'ERROR:  lo_lseek: invalid large obj descriptor (0)
'
STATEMENT ERROR: func=SQLPutData, desc='', errnum=1, errmsg='Couldnt open large object 
for writing.'                ------------------------------------------------------------
hdbc=144654652,stmt=144669180, result=0                manual_result=0, prepare=0, internal=0
bindings=0,bindings_allocated=0                parameters=145688992, parameters_allocated=1
statement_type=1,statement='INSERT INTO  "ole"  ("bild") VALUES (?)'                stmt_with_params='INSERT INTO
"ole" ("id") VALUES (1)'                data_at_exec=0, current_exec_param=0, put_data=1                currTuple=-1,
current_col=-1,lobj_fd=-1                maxRows=0, rowset_size=1, keyset_size=0, cursor_type=0, scroll_concurrency=1
            cursor_name='SQL_CUR089F79FC'                ----------------QResult Info -------------------------------
 
CONN ERROR: func=SQLPutData, desc='', errnum=0, errmsg='ERROR:  lo_lseek: invalid large 
obj descriptor (0)
'           ------------------------------------------------------------           henv=145686660, conn=144654652,
status=1,num_stmts=16           sock=145688632, stmts=145688672, lobj_type=19268           ---------------- Socket Info
-------------------------------          socket=308, reverse=0, errornumber=0, errormsg='(null)'
buffer_in=144660980,buffer_out=144665080           buffer_filled_in=53, buffer_filled_out=0, buffer_read_in=53
 
conn=144654652, SQLDisconnect



Re: ODBC and Large Objects, FAQ not working

От
"Christian Hang"
Дата:
Hi,

> Reason of this problem is that PsqlODBC handles the large object without
> transaction.  Since PostgreSQL 6.5, the large object must be handled in
> transaction.
> 
> To solve, we should insert source code to begin transaction into PsqlODBC
> source before calling lo_create and lo_open functions.  Also should commit
> transaction after calling lo_close too.
> 
> Sorry, I have not tested this solution yet.
> 

Is there a driver update in the near future planed, or can you give 
me a hint, how I can manage this on my own? I have some 
experiences with C, but how to update the current driver in 
Windows with the new code is off my limits.

Thank,

Christian Hang


Re: ODBC and Large Objects, FAQ not working

От
"Hiroki Kataoka"
Дата:
> > Reason of this problem is that PsqlODBC handles the large object without
> > transaction.  Since PostgreSQL 6.5, the large object must be handled in
> > transaction.
> > 
> > To solve, we should insert source code to begin transaction 
> > into PsqlODBC
> > source before calling lo_create and lo_open functions.  Also 
> > should commit
> > transaction after calling lo_close too.
> > 
> > Sorry, I have not tested this solution yet.
> > 
> 
> Is there a driver update in the near future planed, or can you give 
> me a hint, how I can manage this on my own? I have some 
> experiences with C, but how to update the current driver in 
> Windows with the new code is off my limits.

I will attach a patch for PsqlODBC 6.40.0007 to solve this problem.  This
patch also includes another large object patch reported by Sam in this
mailing list.

I have done short test with this patch.

=====
Hiroki Kataoka

===== cur here =====
diff -rc src.v06-40-0007/bind.c src.v06-40-0007.test/bind.c
*** src.v06-40-0007/bind.c    Fri Jan  8 11:32:46 1999
--- src.v06-40-0007.test/bind.c    Wed Dec  8 21:31:35 1999
***************
*** 124,130 ****     }      if (stmt->parameters[ipar].EXEC_buffer) {
!         free(stmt->parameters[ipar].EXEC_buffer);         stmt->parameters[ipar].EXEC_buffer = NULL;     } 
--- 124,131 ----     }      if (stmt->parameters[ipar].EXEC_buffer) {
!         if (stmt->parameters[ipar].SQLType != SQL_LONGVARBINARY)
!             free(stmt->parameters[ipar].EXEC_buffer);         stmt->parameters[ipar].EXEC_buffer = NULL;     } 
diff -rc src.v06-40-0007/convert.c src.v06-40-0007.test/convert.c
*** src.v06-40-0007/convert.c    Fri Apr  9 18:47:40 1999
--- src.v06-40-0007.test/convert.c    Wed Dec  8 21:36:30 1999
***************
*** 40,45 ****
--- 40,46 ---- #include <math.h> #include "convert.h" #include "statement.h"
+ #include "qresult.h" #include "bind.h" #include "pgtypes.h" #include "lobj.h"
***************
*** 895,901 ****
--- 896,926 ----              }             else {
+   
+                 /* begin transaction if needed */
+                 if(!CC_is_in_trans(stmt->hdbc)) {
+                     QResultClass *res;
+                     char ok; 
+                     res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
+                     if (!res) {
+                         stmt->errormsg = "Could not begin (in-line) a transaction";
+                         stmt->errornumber = STMT_EXEC_ERROR;
+                         SC_log_error(func, "", stmt);
+                         return SQL_ERROR;
+                     }
+                     ok = QR_command_successful(res);
+                     QR_Destructor(res);
+                     if (!ok) {
+                         stmt->errormsg = "Could not begin (in-line) a transaction";
+                         stmt->errornumber = STMT_EXEC_ERROR;
+                         SC_log_error(func, "", stmt);
+                         return SQL_ERROR;
+                     }
+ 
+                     CC_set_in_trans(stmt->hdbc);
+                 }
+                  /*    store the oid */                 lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
        if (lobj_oid == 0) {
 
***************
*** 917,922 ****
--- 942,971 ----                 retval = lo_write(stmt->hdbc, lobj_fd, buffer, used);
lo_close(stmt->hdbc,lobj_fd);
 
+ 
+                 /* commit transaction if needed */
+                 if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) {
+                     QResultClass *res;
+                     char ok;
+ 
+                     res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
+                     if (!res) {
+                         stmt->errormsg = "Could not commit (in-line) a transaction";
+                         stmt->errornumber = STMT_EXEC_ERROR;
+                         SC_log_error(func, "", stmt);
+                         return SQL_ERROR;
+                     }
+                     ok = QR_command_successful(res);
+                     QR_Destructor(res);
+                     if (!ok) {
+                         stmt->errormsg = "Could not commit (in-line) a transaction";
+                         stmt->errornumber = STMT_EXEC_ERROR;
+                         SC_log_error(func, "", stmt);
+                         return SQL_ERROR;
+                     }
+ 
+                     CC_set_no_trans(stmt->hdbc);
+                 }             }              /*    the oid of the large object -- just put that in for the
***************
*** 1340,1345 ****
--- 1389,1417 ----     */      if ( ! bindInfo || bindInfo->data_left == -1) {
+ 
+         /* begin transaction if needed */
+         if(!CC_is_in_trans(stmt->hdbc)) {
+             QResultClass *res;
+             char ok;
+ 
+             res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
+             if (!res) {
+                 stmt->errormsg = "Could not begin (in-line) a transaction";
+                 stmt->errornumber = STMT_EXEC_ERROR;
+                 return COPY_GENERAL_ERROR;
+             }
+             ok = QR_command_successful(res);
+             QR_Destructor(res);
+             if (!ok) {
+                 stmt->errormsg = "Could not begin (in-line) a transaction";
+                 stmt->errornumber = STMT_EXEC_ERROR;
+                 return COPY_GENERAL_ERROR;
+             }
+ 
+             CC_set_in_trans(stmt->hdbc);
+         }
+          oid = atoi(value);         stmt->lobj_fd = lo_open(stmt->hdbc, oid, INV_READ);         if (stmt->lobj_fd <
0){
 
***************
*** 1374,1379 ****
--- 1446,1474 ----     retval = lo_read(stmt->hdbc, stmt->lobj_fd, (char *) rgbValue, cbValueMax);     if (retval < 0)
{        lo_close(stmt->hdbc, stmt->lobj_fd);
 
+ 
+         /* commit transaction if needed */
+         if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) {
+             QResultClass *res;
+             char ok;
+ 
+             res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
+             if (!res) {
+                 stmt->errormsg = "Could not commit (in-line) a transaction";
+                 stmt->errornumber = STMT_EXEC_ERROR;
+                 return COPY_GENERAL_ERROR;
+             }
+             ok = QR_command_successful(res);
+             QR_Destructor(res);
+             if (!ok) {
+                 stmt->errormsg = "Could not commit (in-line) a transaction";
+                 stmt->errornumber = STMT_EXEC_ERROR;
+                 return COPY_GENERAL_ERROR;
+             }
+ 
+             CC_set_no_trans(stmt->hdbc);
+         }
+          stmt->lobj_fd = -1;          stmt->errornumber = STMT_EXEC_ERROR;
***************
*** 1396,1401 ****
--- 1491,1519 ----      if (! bindInfo || bindInfo->data_left == 0) {         lo_close(stmt->hdbc, stmt->lobj_fd);
+ 
+         /* commit transaction if needed */
+         if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) {
+             QResultClass *res;
+             char ok;
+ 
+             res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
+             if (!res) {
+                 stmt->errormsg = "Could not commit (in-line) a transaction";
+                 stmt->errornumber = STMT_EXEC_ERROR;
+                 return COPY_GENERAL_ERROR;
+             }
+             ok = QR_command_successful(res);
+             QR_Destructor(res);
+             if (!ok) {
+                 stmt->errormsg = "Could not commit (in-line) a transaction";
+                 stmt->errornumber = STMT_EXEC_ERROR;
+                 return COPY_GENERAL_ERROR;
+             }
+ 
+             CC_set_no_trans(stmt->hdbc);
+         }
+          stmt->lobj_fd = -1;    /* prevent further reading */     } 
diff -rc src.v06-40-0007/execute.c src.v06-40-0007.test/execute.c
*** src.v06-40-0007/execute.c    Fri Jan  8 11:33:02 1999
--- src.v06-40-0007.test/execute.c    Wed Dec  8 21:38:45 1999
***************
*** 517,522 ****
--- 517,547 ----     /* close the large object */     if ( stmt->lobj_fd >= 0) {         lo_close(stmt->hdbc,
stmt->lobj_fd);
+ 
+         /* commit transaction if needed */
+         if (!globals.use_declarefetch && CC_is_in_autocommit(stmt->hdbc)) {
+             QResultClass *res;
+             char ok;
+ 
+             res = CC_send_query(stmt->hdbc, "COMMIT", NULL);
+             if (!res) {
+                 stmt->errormsg = "Could not commit (in-line) a transaction";
+                 stmt->errornumber = STMT_EXEC_ERROR;
+                 SC_log_error(func, "", stmt);
+                 return SQL_ERROR;
+             }
+             ok = QR_command_successful(res);
+             QR_Destructor(res);
+             if (!ok) {
+                 stmt->errormsg = "Could not commit (in-line) a transaction";
+                 stmt->errornumber = STMT_EXEC_ERROR;
+                 SC_log_error(func, "", stmt);
+                 return SQL_ERROR;
+             }
+ 
+             CC_set_no_trans(stmt->hdbc);
+         }
+          stmt->lobj_fd = -1;     } 
***************
*** 607,612 ****
--- 632,661 ----         /*    Handle Long Var Binary with Large Objects */         if ( current_param->SQLType ==
SQL_LONGVARBINARY){ 
 
+             /* begin transaction if needed */
+             if(!CC_is_in_trans(stmt->hdbc)) {
+                 QResultClass *res;
+                 char ok;
+ 
+                 res = CC_send_query(stmt->hdbc, "BEGIN", NULL);
+                 if (!res) {
+                     stmt->errormsg = "Could not begin (in-line) a transaction";
+                     stmt->errornumber = STMT_EXEC_ERROR;
+                     SC_log_error(func, "", stmt);
+                     return SQL_ERROR;
+                 }
+                 ok = QR_command_successful(res);
+                 QR_Destructor(res);
+                 if (!ok) {
+                     stmt->errormsg = "Could not begin (in-line) a transaction";
+                     stmt->errornumber = STMT_EXEC_ERROR;
+                     SC_log_error(func, "", stmt);
+                     return SQL_ERROR;
+                 }
+ 
+                 CC_set_in_trans(stmt->hdbc);
+             }
+              /*    store the oid */             current_param->lobj_oid = lo_creat(stmt->hdbc, INV_READ | INV_WRITE);
           if (current_param->lobj_oid == 0) {
 
diff -rc src.v06-40-0007/statement.c src.v06-40-0007.test/statement.c
*** src.v06-40-0007/statement.c    Thu Sep  2 22:08:04 1999
--- src.v06-40-0007.test/statement.c    Wed Dec  8 21:40:15 1999
***************
*** 327,333 ****             }              if (self->parameters[i].EXEC_buffer) {
!                 free(self->parameters[i].EXEC_buffer);                 self->parameters[i].EXEC_buffer = NULL;
    }         }
 
--- 327,334 ----             }              if (self->parameters[i].EXEC_buffer) {
!                 if (self->parameters[i].SQLType != SQL_LONGVARBINARY)
!                     free(self->parameters[i].EXEC_buffer);                 self->parameters[i].EXEC_buffer = NULL;
        }         }
 



Re: [INTERFACES] Re: ODBC and Large Objects, FAQ not working

От
"Christian Hang"
Дата:
On 8 Dec 99, at 22:43, Hiroki Kataoka wrote:

> > Is there a driver update in the near future planed, or can you give 
> > me a hint, how I can manage this on my own? I have some 
> > experiences with C, but how to update the current driver in 
> > Windows with the new code is off my limits.
> 
> I will attach a patch for PsqlODBC 6.40.0007 to solve this problem.  This
> patch also includes another large object patch reported by Sam in this
> mailing list.

Thanks a lot! I downloaded the source code and edited it according 
to your patch. 

Now the problem I have is that I don't know how to compile the 
code and integrate it into the ODBC-driver! Do I need a C-Compiler 
for Windows/DOS to create a new dll-file, compile and integrate it 
on the server side or how does it work?

A last help in this matter will be highly appreciated.

Greetings,

Christian


Re: ODBC and Large Objects, FAQ not working

От
"Hiroki Kataoka"
Дата:
> > > Is there a driver update in the near future planed, or can you give
> > > me a hint, how I can manage this on my own? I have some
> > > experiences with C, but how to update the current driver in
> > > Windows with the new code is off my limits.
> >
> > I will attach a patch for PsqlODBC 6.40.0007 to solve this
> problem.  This
> > patch also includes another large object patch reported by Sam in this
> > mailing list.
>
> Thanks a lot! I downloaded the source code and edited it according
> to your patch.
>
> Now the problem I have is that I don't know how to compile the
> code and integrate it into the ODBC-driver! Do I need a C-Compiler
> for Windows/DOS to create a new dll-file, compile and integrate it
> on the server side or how does it work?

To compile the PsqlODBC source, you need MS Visual C++ 4.0 or higher.

Step 1: Install original PsqlODBC driver to the Client PC.  If you have
already installed it, then you may skip this step.
Step 2: Compile the patched source.
Step 3: Replace original PSQLODBC.DLL file with compiled new one. There is
in C:\WINDOWS\SYSTEM(Windows9x) or C:\WINNT\SYSTEM32(WindowsNT).
Step 4: Try to use any large objects with new ODBC driver.

There is no work on the server side.

=====
Hiroki Kataoka