如何在 COBOL 中编写 SQLite 回调
How to write SQLite callback in COBOL
我是一名 COBOL 程序员,我最近的项目是将 COBOL 应用程序连接到 SQLite3 数据库。
我一直在关注 this guide,他们的解决方案正是我在 COBOL 应用程序中所需要的。我已经成功创建、连接、插入数据和关闭数据库,但是当我尝试从数据库中 select 数据时出现问题。
在教程中,他们使用双指针回调。
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
我在 COBOL 中的解决方案如下
WORKING-STORAGE SECTION.
*----------------------------------------------------------------*
01 sqlite3-db pointer.
01 err_msg pointer.
01 sqlite pointer.
01 res pointer.
01 notused pointer.
01 argc pic 99 comp-5.
01 argv pointer.
01 azColName pointer.
01 Writefunction-Ptr procedure-pointer.
procedure division.
set Writefunction-Ptr to entry "sqlite-callback".
*>Random code.
call "sqlite3_exec" using
by value sqlite3-db
by reference sqlQuery
by value Writefunction-Ptr
by value 0
by reference err_msg
returning rc
end-call
*>Random code.
stop run.
entry "sqlite-callback" using
by value notused
by value argc
by reference argv
by reference azColName.
display argc
goback.
Entry-Termination.
回调有效,因为它称为从数据库返回的行数,整数 argc 包含 table 包含的列数。
问题是:
COBOL中的双指针,它们是如何表示的?在我的解决方案中,我声明了一个指针并在指针上使用 "by reference" 调用回调。不知道这是否是在 COBOL 中表示双指针的正确方法?
如何显示 azColName 和 argv 的内容,而不仅仅是指针指向的内存地址?
我现在尝试使用 SET ADDRESS OF,但我仍然无法正常工作。一定是我错过了什么。我目前的解决方案如下:
WORKING-STORAGE SECTION.
01 argv pointer.
Linkage Section.
01 link-area pic x.
procedure division using link-area.
*> RANDOM CODE
set address of link-area to argv
call "sqlite3_exec" using
by value sqlite3-db
by reference z"SELECT * FROM Cars"
by value Writefunction-Ptr
by value 0
by reference err_msg
returning rc
end-call
*> RANDOM CODE
entry "sqlite-callback" using
by value notused
by value argc
by reference argv
by reference azColName.
display argc.
if address of link-area not = null
display "Contents of new argv: " link-area
else
display "empty"
end-if
goback.
Entry-Termination.
我得到的结果是if语句始终为假,所以显示字符串"empty"。但是 argc 仍然设置为 table.
中的列数
可行的解决方案:
WORKING-STORAGE SECTION.
01 argv.
03 firstColumn pointer.
03 secondColumn pointer.
03 thirdColumn pointer.
01 azColName pointer.
01 argc pic 99 comp-5.
01 notused pointer.
01 Writefunction-Ptr procedure-pointer.
*-----------------------------------------------------------------
Linkage Section.
01 Cars_Id pic 9(2).
01 Cars_Name pic X(20).
01 Cars_Price pic 9(10).
/-----------------------------------------------------------------
procedure division.
//code
set Writefunction-Ptr to entry "sqlite-callback".
initialize sqlQuery
move z"SELECT * FROM Cars;" to sqlQuery
call "sqlite3_exec" using
by value sqlite3-db
by reference sqlQuery
by value Writefunction-Ptr
by value 0
by reference err_msg
returning rc
end-call
//code
stop run.
entry "sqlite-callback" using
by value notused
by value argc
by reference argv
by reference azColName.
set address of Cars_Id to firstColumn
set address of Cars_Name to secondColumn
set address of Cars_Price to thirdColumn
display Cars_Id "|" Cars_Name "|" Cars_Price
goback.
Entry-Termination.
我们真的需要知道您使用的编译器。
你的 SET 语句在错误的地方。 argv
只有在调用 ENTRY
时才有地址。在条目被调用之前,它将是二进制零,或者一些不可预测的垃圾。
如果您将 SET 移到 ENTRY 之后,您应该能够使用 LINK-AREA 的值。 argv
仍然只是一个地址,但是 LINK-AREA(请给它一个更好的名字)将指向那个地址,所以将它定义为 argv 应该被定义,然后 LINK-AREA可以用来获取argv的实际内容。
使用 BY REFERENCE
时,编译器生成代码以传递带有数据项地址的指针。
在 PROCEDURE DIVISION USING
或 ENTRY USING
上,项目也应该是 BY REFERENCE 并且编译器生成代码以将您的 LINKAGE SECTION 定义映射到传递的地址。
如果您使用 BY CONTENT
,这与此类似,但编译器会在您的程序中获取数据的副本,并传递一个引用该数据的指针。关于仍然定义为 BY REFERENCE 的 PROCEDURE DIVISION 或 ENTRY 的 USING。
使用 BY VALUE
编译器 "passes" 实际值,尽管存在限制,无论是标准中指定的限制还是实际编译器对标准的扩展。 PROCEDURE DIVISION 或 ENTRY 的 USING 也应指定 BY VALUE。
在所有 USING 上,BY REFERENCE/CONTENT/VALUE 被传播,如果所有都相同并且您想要 BY REFERENCE,则根本不需要指定 BY,这是默认值。
如果你 "pass" a POINTER
(USAGE POINTER
) 那么你可以访问使用 SET ADDRESS OF
指向的数据。 SET ADDRESS OF 项必须在 LINKAGE SECTION
中。
您还可以使用带有 SET ADDRESS OF 的隐式指针。 SET ADDRESS OF a TO ADDRESS OF b 会将 LINKAGE SECTION 中映射的地址更改为 b 的地址,b 是在程序的 DATA DIVISION
(除 FILE SECTION
).
如果您想查看 POINTER 指向的数据,请定义一个具有正确大小和类型的项目并使用 SET ADDRESS OF item TO pointer-name。
指针当然可以指向一个简单的数据项或一组数据项(结构)。
LINKAGE SECTION 中的所有项目在被引用之前必须有一个地址。 USING 上的那些由编译器赋予可寻址性(并且编译器假定传递了正确数量的 addresses/items )。所有其他 LINKAGE SECTION 项必须具有通过 SET ADDRESS OF 或通过在使用 CALL
中传递 ADDRESS OF 并让被调用程序设置地址来建立的可寻址性。
我是一名 COBOL 程序员,我最近的项目是将 COBOL 应用程序连接到 SQLite3 数据库。
我一直在关注 this guide,他们的解决方案正是我在 COBOL 应用程序中所需要的。我已经成功创建、连接、插入数据和关闭数据库,但是当我尝试从数据库中 select 数据时出现问题。
在教程中,他们使用双指针回调。
static int callback(void *NotUsed, int argc, char **argv, char **azColName){
int i;
for(i=0; i<argc; i++){
printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
}
printf("\n");
return 0;
}
我在 COBOL 中的解决方案如下
WORKING-STORAGE SECTION.
*----------------------------------------------------------------*
01 sqlite3-db pointer.
01 err_msg pointer.
01 sqlite pointer.
01 res pointer.
01 notused pointer.
01 argc pic 99 comp-5.
01 argv pointer.
01 azColName pointer.
01 Writefunction-Ptr procedure-pointer.
procedure division.
set Writefunction-Ptr to entry "sqlite-callback".
*>Random code.
call "sqlite3_exec" using
by value sqlite3-db
by reference sqlQuery
by value Writefunction-Ptr
by value 0
by reference err_msg
returning rc
end-call
*>Random code.
stop run.
entry "sqlite-callback" using
by value notused
by value argc
by reference argv
by reference azColName.
display argc
goback.
Entry-Termination.
回调有效,因为它称为从数据库返回的行数,整数 argc 包含 table 包含的列数。
问题是:
COBOL中的双指针,它们是如何表示的?在我的解决方案中,我声明了一个指针并在指针上使用 "by reference" 调用回调。不知道这是否是在 COBOL 中表示双指针的正确方法?
如何显示 azColName 和 argv 的内容,而不仅仅是指针指向的内存地址?
我现在尝试使用 SET ADDRESS OF,但我仍然无法正常工作。一定是我错过了什么。我目前的解决方案如下:
WORKING-STORAGE SECTION.
01 argv pointer.
Linkage Section.
01 link-area pic x.
procedure division using link-area.
*> RANDOM CODE
set address of link-area to argv
call "sqlite3_exec" using
by value sqlite3-db
by reference z"SELECT * FROM Cars"
by value Writefunction-Ptr
by value 0
by reference err_msg
returning rc
end-call
*> RANDOM CODE
entry "sqlite-callback" using
by value notused
by value argc
by reference argv
by reference azColName.
display argc.
if address of link-area not = null
display "Contents of new argv: " link-area
else
display "empty"
end-if
goback.
Entry-Termination.
我得到的结果是if语句始终为假,所以显示字符串"empty"。但是 argc 仍然设置为 table.
中的列数可行的解决方案:
WORKING-STORAGE SECTION.
01 argv.
03 firstColumn pointer.
03 secondColumn pointer.
03 thirdColumn pointer.
01 azColName pointer.
01 argc pic 99 comp-5.
01 notused pointer.
01 Writefunction-Ptr procedure-pointer.
*-----------------------------------------------------------------
Linkage Section.
01 Cars_Id pic 9(2).
01 Cars_Name pic X(20).
01 Cars_Price pic 9(10).
/-----------------------------------------------------------------
procedure division.
//code
set Writefunction-Ptr to entry "sqlite-callback".
initialize sqlQuery
move z"SELECT * FROM Cars;" to sqlQuery
call "sqlite3_exec" using
by value sqlite3-db
by reference sqlQuery
by value Writefunction-Ptr
by value 0
by reference err_msg
returning rc
end-call
//code
stop run.
entry "sqlite-callback" using
by value notused
by value argc
by reference argv
by reference azColName.
set address of Cars_Id to firstColumn
set address of Cars_Name to secondColumn
set address of Cars_Price to thirdColumn
display Cars_Id "|" Cars_Name "|" Cars_Price
goback.
Entry-Termination.
我们真的需要知道您使用的编译器。
你的 SET 语句在错误的地方。 argv
只有在调用 ENTRY
时才有地址。在条目被调用之前,它将是二进制零,或者一些不可预测的垃圾。
如果您将 SET 移到 ENTRY 之后,您应该能够使用 LINK-AREA 的值。 argv
仍然只是一个地址,但是 LINK-AREA(请给它一个更好的名字)将指向那个地址,所以将它定义为 argv 应该被定义,然后 LINK-AREA可以用来获取argv的实际内容。
使用 BY REFERENCE
时,编译器生成代码以传递带有数据项地址的指针。
在 PROCEDURE DIVISION USING
或 ENTRY USING
上,项目也应该是 BY REFERENCE 并且编译器生成代码以将您的 LINKAGE SECTION 定义映射到传递的地址。
如果您使用 BY CONTENT
,这与此类似,但编译器会在您的程序中获取数据的副本,并传递一个引用该数据的指针。关于仍然定义为 BY REFERENCE 的 PROCEDURE DIVISION 或 ENTRY 的 USING。
使用 BY VALUE
编译器 "passes" 实际值,尽管存在限制,无论是标准中指定的限制还是实际编译器对标准的扩展。 PROCEDURE DIVISION 或 ENTRY 的 USING 也应指定 BY VALUE。
在所有 USING 上,BY REFERENCE/CONTENT/VALUE 被传播,如果所有都相同并且您想要 BY REFERENCE,则根本不需要指定 BY,这是默认值。
如果你 "pass" a POINTER
(USAGE POINTER
) 那么你可以访问使用 SET ADDRESS OF
指向的数据。 SET ADDRESS OF 项必须在 LINKAGE SECTION
中。
您还可以使用带有 SET ADDRESS OF 的隐式指针。 SET ADDRESS OF a TO ADDRESS OF b 会将 LINKAGE SECTION 中映射的地址更改为 b 的地址,b 是在程序的 DATA DIVISION
(除 FILE SECTION
).
如果您想查看 POINTER 指向的数据,请定义一个具有正确大小和类型的项目并使用 SET ADDRESS OF item TO pointer-name。
指针当然可以指向一个简单的数据项或一组数据项(结构)。
LINKAGE SECTION 中的所有项目在被引用之前必须有一个地址。 USING 上的那些由编译器赋予可寻址性(并且编译器假定传递了正确数量的 addresses/items )。所有其他 LINKAGE SECTION 项必须具有通过 SET ADDRESS OF 或通过在使用 CALL
中传递 ADDRESS OF 并让被调用程序设置地址来建立的可寻址性。