Postgresql 错误28“;“堆栈空间不足”;用VB6执行大型查询&;ADO 2.8
场景:Postgresql 错误28“;“堆栈空间不足”;用VB6执行大型查询&;ADO 2.8,postgresql,vb6,oledb,ado,postgis,Postgresql,Vb6,Oledb,Ado,Postgis,场景: 使用ADO连接从Visual Basic 6应用程序执行SQL命令。通过PostgreSQL OLEDB提供程序执行方法到PostgreSQL 9.2数据库 查询: 这是一个简单的EXECUTE prepared_statement_name(x,y,z),尽管它涉及PostGIS几何体类型,因此它类似于: EXECUTE prepared_statement_name (1, ST_GeomFromText('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 9
使用ADO连接从Visual Basic 6应用程序执行SQL命令。通过PostgreSQL OLEDB提供程序执行方法到PostgreSQL 9.2数据库 查询:
这是一个简单的
EXECUTE prepared_statement_name(x,y,z)
,尽管它涉及PostGIS几何体类型,因此它类似于:
EXECUTE prepared_statement_name (1, ST_GeomFromText('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))', 900001));
问题:当几何体是一个包含许多顶点的巨大而复杂的多边形时,查询会变得非常长(几千个字符),并且
连接.Execute
方法会导致错误28:“堆栈空间不足”
这个过程中没有递归或嵌套循环,很明显错误是由于查询长度过长造成的
我想如果我在执行之前将大查询以“块”的形式传递给提供者,我可以避免这个错误,但这只是一个想法,我不知道这是否可能以及如何实现
我不知道,非常感谢您的帮助。因为这听起来像是一个VB6级别的问题,而且您已经使用了当前的Pg版本,我担心您可能需要使用一些特别难看的解决方法
如果可能的话,尝试找到一种增加VB6查询缓冲区大小的方法,通过VB6 ODBC接口在块中发送查询等。 也许这会给你一些更理智的线索。我不会说VB6(谢天谢地),所以我无法对其进行评估:
只有在所有其他方法都失败的情况下,才将以下方法作为最后手段使用:- 创建一个
表,如TEMPORARY
Create TEMPORARY table my\u query(id integer,text querychunk)
将语句逐块插入到临时表中,使用参数化查询避免引用问题
- 创建一个包装器PL/PgSQL函数,该函数执行
,将临时表的返回查询执行格式('EXECUTE stm_name(…)”
字符串作为参数传递。是的,这非常难看
CREATE TABLE real_table (blah text);
PREPARE test_stm2(text) AS INSERT INTO real_table VALUES ($1);
CREATE TEMPORARY TABLE data_chunks(datord integer, datchunk text);
PREPARE chunk_insert(integer, text) AS INSERT INTO data_chunks(datord,datchunk) VALUES ($1,$2);
-- You'll really want to do this via proper parameterised statements
-- to avoid quoting nightmares; I'm using dollar-quoting as a workaround
EXECUTE chunk_insert(0, $val$POLYGON((0 0, 0 1, 1 1,$val$);
EXECUTE chunk_insert(1, $val$ 1, 1 0, 0 0))$val$);
DO
$$
BEGIN
EXECUTE 'EXECUTE test_stm2($1);'
USING
(SELECT string_agg(datchunk,'' ORDER BY datord) FROM data_chunks);
END;
$$ LANGUAGE plpgsql;
结果:
regress=> SELECT * FROM real_table ;
blah
---------------------------------------
POLYGON((0 0, 0 1, 1 1, 1, 1 0, 0 0))
(1 row)
SELECT
也可以采用类似的方法。您可以在由CREATE或REPLACE function
定义的函数中使用RETURN QUERY EXECUTE
,因为DO
块不能返回结果。例如,对于返回一组整数的查询,您可以编写:
CREATE OR REPLACE FUNCTION test_wrapper_func() RETURNS SETOF integer AS $$
BEGIN
RETURN QUERY EXECUTE format('EXECUTE test_stm(%L);', (SELECT string_agg(datchunk,'' ORDER BY datord) FROM data_chunks));
END;
$$ LANGUAGE plpgsql;
您将注意到两级EXECUTE
。这是因为PL/PgSQLEXECUTE
与SQL级EXECUTE
是完全不同的语句。PL/PgSQLEXECUTE
以动态SQL的形式运行字符串,而SQLEXECUTE
则运行一条准备好的语句。这里我们通过动态SQL运行一条准备好的语句
想知道我为什么要使用PL/PgSQL吗?因为您不能将子查询用作EXECUTE
参数。如果您不将其作为预处理语句运行,则可以避免查询的PL/PgSQL包装
regress=> EXECUTE test_stm2( (SELECT string_agg(datchunk,'' ORDER BY datord) FROM data_chunks) );
ERROR: cannot use subquery in EXECUTE parameter
您的代码中可能没有递归或循环,但Postgre/PostGIS很可能是内部的。我希望您唯一的选择是重新构造yoru查询或分块执行。如果您可以提供一个溢出查询的示例,可能有人可以进一步提供帮助。嗯,VB6?从1998年开始,2005年结束?使用PostGIS?看起来很奇怪combo。您似乎忘记提及您的PostgreSQL、PostGIS和PSQLDBC版本。@Deanna感谢您的评论,但它与递归没有任何关系。同一查询在任何其他客户端(例如pgAdminIII)中都可以正常执行。查询正是问题中的一个,只需向多边形添加几千个顶点。@Craig Ringer是的,我知道VB6已经过时,听起来像是一个“奇怪的组合”(有趣的组合),但这就是我得到的,我必须修复它,遗留软件是最差的软件。PostgreSQL 9.2、PostGIS 2.0、pgFoundry PgOleDb 1.0.20是这些版本(是的,那些最新的版本使vb6组合更加糟糕…@Eggplant足够公平了…我在1983年做过一些(!!)去年微软Xenix/386的软件,所以我知道痛苦是什么样的。不管怎样,首先:如果你直接通过psql
在VB6中执行一个失败的查询,它会因为同样的错误而失败吗?或者直接通过psql
运行它会成功吗?哇,这是一个巧妙的解决方案,它可能“丑陋”,但它也是“安全的”:它将所有内容保留在一些查询中,我仍然可以将所有“丑陋的东西”打包到事务中!与此同时,我正在开发一个更丑陋的解决方案,该解决方案涉及db类和ado之间的应用程序中的一个附加层,该层应该拦截所有命令并在硬盘上编写脚本文件,然后使用psql执行它(是的,从vb6启动psql…。现在这很难看!!!:)我喜欢你的解决方案,它需要更改一些查询,但避免了外部交互。非常感谢!我非常感谢你付出的努力和时间。我现在能够自己实现整个概念,你为我节省了一些时间损失!vb6又得分了!-)