Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Closing a statement causes a "malformed object" error on the result - by design ?

57 views
Skip to first unread message

R.Wieser

unread,
Jun 26, 2016, 11:00:00 AM6/26/16
to
Hello All,

To access some data in a SQLite3 database I tried to execute the below:

$statement = $db->prepare( ....);
...
$results = $statement->execute();
$statement->close();

$row = $results->fetchArray();

The problem is that that last line throws an "malformed object" error*.
However, when I move the "statement->close();" line to the bottom all goes
well.

*the error itself feels incorrect, as the problem is not the object
($results) itself, but just that it can't find its parent ($statement)
anymore ...

(I currently assume that the fact that the $results object needs the
$statement object is most likely because the $results doesn't actually store
all results internally, but instead each fetchArray() call will just
retrieve the next record from the database.)

Question: is the closing a "parent" object causing the "child" to
malfunction an expected/described something within PHP, or should I consider
it a bug.

FYI: My frame of reference is COM/OCX objects, where dependancies are solved
by the "child" incrementing a reference count in its "parent" , which causes
the "parent" to "stay alive" even when they are told to terminate, up until
all "childs" that depend on it are closed too.

Regards,
Rudy Wieser



Jerry Stuckle

unread,
Jun 26, 2016, 12:23:11 PM6/26/16
to
This has nothing to do with parent/child relationships. Retrieving data
from the database requires an open connection.

And this is not a COM/OCX object, and does not work like one.

--
==================
Remove the "x" from my email address
Jerry Stuckle
jstu...@attglobal.net
==================

R.Wieser

unread,
Jun 26, 2016, 4:04:57 PM6/26/16
to
Jerry,

> This has nothing to do with parent/child relationships.

No ? Please explain why you think it doesn't, and how you describe the
relationship between the $result and $statement objects.

> Retrieving data from the database requires an open
> connection.

And that has to do with the problem as I described .... what exactly ?

Also notice that I described in my previous message that :

#1 The data could be retrieved in its whole (as an array of arrays) and
given to the $result object, meaning that in such a case there is no open
conection needed anymore.

#2 I described how the "open connection" chain could be maintained when the
"parent" ($statement) object is told to terminate (by keeping the "parent"
object alive).

To that you can add:

#3 The "child" ($result) object could keep the connection open itself.

> And this is not a COM/OCX object, and does not work
> like one.

No ? Please describe how they are different. Do PHP objects not handle
dependancies ? If so, why not ?

Bottom line: You're welcome to tell me I've got this-or-that wrong, but
without any explanation to the why of it such a remark looses its value (and
in my particular case will be forgotten rather quickly -- sorry).

Regards,
Rudy Wieser


-- Origional message:
Jerry Stuckle <jstu...@attglobal.net> schreef in berichtnieuws
nkovh9$koq$1...@jstuckle.eternal-september.org...

Jerry Stuckle

unread,
Jun 26, 2016, 4:45:14 PM6/26/16
to
On 6/26/2016 4:07 PM, R.Wieser wrote:
> Jerry,
>
>> This has nothing to do with parent/child relationships.
>
> No ? Please explain why you think it doesn't, and how you describe the
> relationship between the $result and $statement objects.
>

There is no inheritance relationship between a $statement object and a
$result object. The $result object is just an object returned by the
execution of a $statement object.

>> Retrieving data from the database requires an open
>> connection.
>
> And that has to do with the problem as I described .... what exactly ?
>

fetchArray() retrieves data from the database. It requires an open
connection to the database.

> Also notice that I described in my previous message that :
>
> #1 The data could be retrieved in its whole (as an array of arrays) and
> given to the $result object, meaning that in such a case there is no open
> conection needed anymore.
>

Whether it *could be* or not is immaterial. Retrieving data from the
database requires an open connection.

> #2 I described how the "open connection" chain could be maintained when the
> "parent" ($statement) object is told to terminate (by keeping the "parent"
> object alive).
>

Once again, there is no inheritance relationship between a $statement
object and other objects.

> To that you can add:
>
> #3 The "child" ($result) object could keep the connection open itself.
>

Once gain, there is no inheritance relationship between a $result object
and other objects.

>> And this is not a COM/OCX object, and does not work
>> like one.
>
> No ? Please describe how they are different. Do PHP objects not handle
> dependancies ? If so, why not ?
>

They are entirely different objects, for entirely different uses. You
are trying to compare apples and oranges.

> Bottom line: You're welcome to tell me I've got this-or-that wrong, but
> without any explanation to the why of it such a remark looses its value (and
> in my particular case will be forgotten rather quickly -- sorry).
>

I told you you were wrong, and exactly why you were wrong.

Peter H. Coffin

unread,
Jun 26, 2016, 4:55:09 PM6/26/16
to
On Sun, 26 Jun 2016 22:07:10 +0200, R.Wieser wrote:
> Jerry,
>
>> This has nothing to do with parent/child relationships.
>
> No ? Please explain why you think it doesn't, and how you describe the
> relationship between the $result and $statement objects.
>
>> Retrieving data from the database requires an open
>> connection.
>
> And that has to do with the problem as I described .... what exactly ?
>
> Also notice that I described in my previous message that :
>
> #1 The data could be retrieved in its whole (as an array of arrays) and
> given to the $result object, meaning that in such a case there is no open
> conection needed anymore.

That's a pretty big assumption, considering that a result set COULD BE
millions and millions of rows. Heck, your own code is reading it row by
row. It's a lot easier for ME to imagine that the database fills up it's
output buffer with results and lets PHP read rows out until it needs
to refill the buffer with more rows. And THAT would definitely need a
database connection to stay open.

--
10. I will not interrogate my enemies in the inner sanctum -- a small
hotel well outside my borders will work just as well.
--Peter Anspach's list of things to do as an Evil Overlord

Christoph M. Becker

unread,
Jun 26, 2016, 7:33:16 PM6/26/16
to
On 26.06.2016 at 17:02, R.Wieser wrote:

> To access some data in a SQLite3 database I tried to execute the below:

I presume you mean something like:

<?php

$conn = new SQLite3(':memory:');
$conn->exec('CREATE TABLE test (id int)');
$conn->exec('INSERT INTO test VALUES (1)');
$statement= $conn->prepare('SELECT * FROM test');
$result = $statement->execute();
$statement->close();
$row = $result->fetchArray();

> The problem is that that last line throws an "malformed object" error*.
> However, when I move the "statement->close();" line to the bottom all goes
> well.
>
> *the error itself feels incorrect, as the problem is not the object
> ($results) itself, but just that it can't find its parent ($statement)
> anymore ...

I get:

| Warning: SQLite3Result::fetchArray(): The SQLite3Result object has
| not been correctly initialised in ... on line 9

From looking at the message and the actual behavior I assume that
SQLite3Stmt::close() invalidates the SQLite3Result object. This is,
however, something I'd like to see documented in the php.net manual.

> Question: is the closing a "parent" object causing the "child" to
> malfunction an expected/described something within PHP, or should I consider
> it a bug.

I don't think it's a bug, but the behavior should be explicitly
mentioned in the manual, so I suggest to file a doc bug against
<https://bugs.php.net/>.

--
Christoph M. Becker

R.Wieser

unread,
Jun 27, 2016, 5:42:36 AM6/27/16
to
Peter,

> That's a pretty big assumption, considering that a result set
> COULD BE millions and millions of rows.

:-) It isn't an assumption, its a *possibility*. It would definitily workd
for small amounts of data (with the definition of "small amounts" being
debatable. :-) )

Also, in my bracketed paragraph in my initial message I already mention that
its not quite likely that it works that way -- due to exactly the reason you
stated in the above.

> And THAT would definitely need a database connection
> to stay open.

That a solution has been choosen where the connection needs to stay open
isn't the problem.

What is is that terminating the $statement object that, as far as I can
tell, has done its job after the ->execute() method returns, breaks the
connection between the $results object and the database -- with no inbuild
method managing to forgo this kind of breakage nor an error message
indicating the actual problem.

I went with a fine toothcomb over the $results->fetchArray() line for quite
some time (didn't understand how it could have gotten "malformed") before I
came to the conclusion that that line nor the object was to blame for the
error. :-\

Regards,
Rudy Wieser


-- Origional message:
Peter H. Coffin <hel...@ninehells.com> schreef in berichtnieuws
slrnnn0g94....@nibelheim.ninehells.com...

R.Wieser

unread,
Jun 27, 2016, 5:42:39 AM6/27/16
to
Christoph,

> I presume you mean something like: [snip]

Something like that, but instead of INSERTing I was SELECTing data. At some
point I even tried a basic "SELECT * FROM MyTable".

> I get:
>
> | Warning: SQLite3Result::fetchArray(): The SQLite3Result
> | object has not been correctly initialised in ... on line 9

An error message which is as deceiving as mine was ...

I mean, the object *was* initialized correctly, but executing something on a
*fully other object* caused a bad side-effect on this (SQLite3Result) one.
:-(

> I don't think it's a bug, but the behavior should be
> explicitly mentioned in the manual,

:-) Which is pretty-much what my question was all about: Is someone aware of
this behaviour, and if so knows what its origin is.

Its possible that PHP objects simply do not know he concept of dependancy
(although I find that hard to believe), but also that its a simple bug that
has been solved in later versions of the php_sqlite3.dll -- though your
above response shows that, although the error message has changed, the
problem (if it actually is one) still exists.

> so I suggest to file a doc bug against <https://bugs.php.net/.

I'm currently not even sure if it is in fact a bug.

I would not want to play the role of a first-best noob who, because he
doesn't understand how something is designed to work and is not aware of the
relevant documentation, declares its to be one and thereby wastes the time
of those bug-list maintainers ... :-( :-)

Regards,
Rudy Wieser


-- Origional message:
Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
nkponn$fii$1...@solani.org...

R.Wieser

unread,
Jun 27, 2016, 6:24:37 AM6/27/16
to
Jerry,

> There is no inheritance relationship between a $statement object
> and a $result object.

And I never said or even indicated as much. There *is* however a
*dependancy* relationship between them. One I tried to describe.

> The $result object is just an object returned by the execution of
> a $statement object.

I think I disagree with you there. Such a "just an object" would not
throw an error because its creator has been terminated.

Heck, I could even consider the fact that I get an "malformed object" back
from the $results object when its creator $statement object has been
terminated as an indication of an actual inheritance problem (part of the
childs objects, methods and data disappear when the parent is removed).

> Whether it *could be* or not is immaterial. Retrieving data from
> the database requires an open connection.

If you put it that way I have to say you are wrong.

And as I'm in rome where the romans (you) do not believe in explaining
themselves I have to behave like one and not explain myself either. :-)

> They are entirely different objects, for entirely different uses.
> You are trying to compare apples and oranges.

I'm afraid you misread that. I did not compare *anything* with it. I did
however give a [quote]frame of reference[/quote] you could perhaps easier
explain how PHP extension objects work -- by focussing on the differences,
instead of their similarities. You know, to make your answering of my
question a bit easier.

> I told you you were wrong, and exactly why you were wrong.

I beg to differ. You're quick enough to play the "you're wrong" card, but
somehow cannot bring yourself to explain how you came to that conclusion, or
what should have been done instead. In other words: you do not seem to be
out to actually *help*.


I have an idea: You keep posting messages consisting outof "you're wrong"
lines with no explanation for such a stance and/or what you think should be
done instead, and I will try to ignore them as much as I can. What do you
think ? Its a deal ? :-)

Regards,
Rudy Wieser


- Origional message:
Jerry Stuckle <jstu...@attglobal.net> schreef in berichtnieuws
nkpesl$f9c$1...@jstuckle.eternal-september.org...

Christoph M. Becker

unread,
Jun 27, 2016, 7:10:00 AM6/27/16
to
On 27.06.2016 at 11:44, R.Wieser wrote:

> Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
> nkponn$fii$1...@solani.org...
>
>> I presume you mean something like: [snip]
>
> Something like that, but instead of INSERTing I was SELECTing data. […]

I was also SELECTing; the INSERT was only to have something to select.
:) See <https://3v4l.org/AYuI3>.

>> I don't think it's a bug, but the behavior should be
>> explicitly mentioned in the manual,
>
> :-) Which is pretty-much what my question was all about: Is someone aware of
> this behaviour, and if so knows what its origin is.

The behavior stems from the fact that when SQLite3Result::fetchArray()
is called, it is first checked whether the related stmt_obj is
initialised[1]. When SQLite3Stmt::close() is called, the stmt_obj is,
however, destroyed[2], so the warning is raised[3].

Of course, it would be possible to check for existing results, and to
not close the statement when ::close() is called (maybe raising a
notice/warning) in this case, but that would require the programmer to
call SQLite3Result::finalize() before calling SQLite3Stmt::close(), what
appears to be too tedious.

It might have been best not to offer SQLite3Stmt::close() in the first
place, and simply close the statement when the statement object will be
destroyed (as it's done by PDO), but removing the close() method now
would cause major BC issues, so that doesn't appear to be an option.

>> so I suggest to file a doc bug against <https://bugs.php.net/.
>
> I'm currently not even sure if it is in fact a bug.

I didn't suggest that this is a bug, but rather a *doc* bug, i.e.
something important that the documentation is missing. It might be
arguable that the warning message is a real bug, or at least could be
improved, but that appears to be secondary, if the documentation already
would state that a statement must not be closed, if further operations
on any of its results will be executed.

> I would not want to play the role of a first-best noob who, because he
> doesn't understand how something is designed to work and is not aware of the
> relevant documentation, declares its to be one and thereby wastes the time
> of those bug-list maintainers ... :-( :-)

Understandable. :) I've filed a ticket myself:
<https://bugs.php.net/72502>.

[1]
<https://github.com/php/php-src/blob/php-7.0.8/ext/sqlite3/sqlite3.c#L1753>
[2]
<https://github.com/php/php-src/blob/php-7.0.8/ext/sqlite3/sqlite3.c#L1286>
[3]
<https://github.com/php/php-src/blob/php-7.0.8/ext/sqlite3/sqlite3.c#L68-L72>

--
Christoph M. Becker

R.Wieser

unread,
Jun 27, 2016, 9:00:06 AM6/27/16
to
Christoph,

> The behavior stems from the fact that when
> SQLite3Result::fetchArray() is called, it is first checked
> whether the related stmt_obj is initialised[1]. When
> SQLite3Stmt::close() is called, the stmt_obj is, however,
> destroyed[2], so the warning is raised[3].

Thanks for this specific answer.

> Of course, it would be possible to check for existing results, and to
> not close the statement when ::close() is called (maybe raising a
> notice/warning) in this case,

That is what happens with COM/OCX objects: a reference count is incremented
when a dependant "child" object is created, and decremented when such a
"child" object is destroyed. And an object ofcourse only gets destroyed
when that reference (dependancy) count reaches Zero.

>but that would require the programmer to call
> SQLite3Result::finalize() before calling SQLite3Stmt::close(),
> what appears to be too tedious.

Well, calling $statement->close() seems to be rather normal, so why would
$result->close() than suddenly be tedious ?

Also, the object could be auto-closing when all data is read. Furthermore,
currently it looks like the $statement->close() does actually also close (in
a way) the $result (enumerator), but without actually releasing it (which I
would consider to be a "bad thing") ...

And that makes me wonder: who does actually take care of releasing the
$results objects resources still there when $statement object is
closed/destroyed ? Shouldn't I be prepared to do that anyway ? (note to
self: check if $restults->close() or something similar exists)

And no, in case of a COM/OCX object with its reference count the "parent"
object can be told to terminate before all its "childs" are closed. It
will ofcourse not actually *do* so until the above-mentioned reference count
reaches zero (though variable holding the object reference will (/should)
get set to NULL).

> It might have been best not to offer SQLite3Stmt::close() in the
> first place, and simply close the statement when the statement
> object will be destroyed (as it's done by PDO),

That could, in circumstances, create a problem. Although its a good idea
to have the language destroy an object when it scope ends, there might be
cases where destroying an object before that might be a good idea.

> but removing the close() method now would cause major
> BC issues, so that doesn't appear to be an option.

In that case just do what MS always does in cases like that: keep the
method, but just don't let it actually *do* anything. :-)

> I didn't suggest that this is a bug, but rather a *doc*
> bug, i.e. something important that the documentation
> is missing.

Ackkk... I misunderstood. Yep, that could be considered a bug too.

> I've filed a ticket myself: <https://bugs.php.net/72502>.

Thanks.

Just one request: please do not shift the blame to me when the documentation
has been available all this time. :-D

Regards,
Rudy Wieser


-- Origional message:
Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
nkr1i3$av4$1...@solani.org...
> On 27.06.2016 at 11:44, R.Wieser wrote:
>
> > Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
> > nkponn$fii$1...@solani.org...
> >
> >> I presume you mean something like: [snip]
> >
> > Something like that, but instead of INSERTing I was SELECTing data. [.]

Christoph M. Becker

unread,
Jun 27, 2016, 9:33:45 AM6/27/16
to
On 27.06.2016 at 15:02, R.Wieser wrote:

> Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
> nkr1i3$av4$1...@solani.org...
>
> And that makes me wonder: who does actually take care of releasing the
> $results objects resources still there when $statement object is
> closed/destroyed ? Shouldn't I be prepared to do that anyway ? (note to
> self: check if $restults->close() or something similar exists)

There is SQLite3Result::finalize(), but if you don't call it explicitly,
it will be called by SQLite3Result's destructor[1], which should be
called by SQLite3Stmt's destructor[2]. I'm not sure, however, if that
does really happen. Maybe that's what <https://bugs.php.net/69971> is
about? Might be worth closer examination.

> And no, in case of a COM/OCX object with its reference count the "parent"
> object can be told to terminate before all its "childs" are closed. It
> will ofcourse not actually *do* so until the above-mentioned reference count
> reaches zero (though variable holding the object reference will (/should)
> get set to NULL).

The automatic memory management of PHP is actually mainly done by
reference counting[3], so basically works the same, unless one
explicitly calls ::close().

>> but removing the close() method now would cause major
>> BC issues, so that doesn't appear to be an option.
>
> In that case just do what MS always does in cases like that: keep the
> method, but just don't let it actually *do* anything. :-)

But then a programmer would not be aware that he'd have to explicitly
set the statement to null to force closing the statement. Of course,
the method could be deprecated, but that would require the RFC process[4].

> Just one request: please do not shift the blame to me when the documentation
> has been available all this time. :-D

No, I won't. :)

[1]
<https://github.com/php/php-src/blob/php-7.0.8/ext/sqlite3/sqlite3.c#L2267>
[2]
<https://github.com/php/php-src/blob/php-7.0.8/ext/sqlite3/sqlite3.c#L2114>
[3] <http://php.net/manual/en/features.gc.php>
[4] <https://wiki.php.net/rfc/howto>

--
Christoph M. Becker

Jerry Stuckle

unread,
Jun 27, 2016, 10:12:00 AM6/27/16
to
On 6/27/2016 6:26 AM, R.Wieser wrote:
> Jerry,
>
>> There is no inheritance relationship between a $statement object
>> and a $result object.
>
> And I never said or even indicated as much. There *is* however a
> *dependancy* relationship between them. One I tried to describe.
>

You said: "is the closing a "parent" object causing the "child" to...".
This indicates an inheritance relationship. If that is not what you
mean, you shouldn't use those terms.

>> The $result object is just an object returned by the execution of
>> a $statement object.
>
> I think I disagree with you there. Such a "just an object" would not
> throw an error because its creator has been terminated.
>

Yes, it would, as it does. It is trying to access a connection which is
no longer open.

> Heck, I could even consider the fact that I get an "malformed object" back
> from the $results object when its creator $statement object has been
> terminated as an indication of an actual inheritance problem (part of the
> childs objects, methods and data disappear when the parent is removed).
>

Once again, there is no inheritance relationship. And if you understood
inheritance, you would understand it is impossible for a parent to be
removed without the child also being removed, because the parent is an
integral part of the child.

>> Whether it *could be* or not is immaterial. Retrieving data from
>> the database requires an open connection.
>
> If you put it that way I have to say you are wrong.
>

And you are incorrect in that statement.

> And as I'm in rome where the romans (you) do not believe in explaining
> themselves I have to behave like one and not explain myself either. :-)
>

I did explain what happens, and why it happens. That you do not accept
that explanation is not my problem.

>> They are entirely different objects, for entirely different uses.
>> You are trying to compare apples and oranges.
>
> I'm afraid you misread that. I did not compare *anything* with it. I did
> however give a [quote]frame of reference[/quote] you could perhaps easier
> explain how PHP extension objects work -- by focussing on the differences,
> instead of their similarities. You know, to make your answering of my
> question a bit easier.
>

No, I did not. You tried to compare the PHP/SQLite interface to COM/OCX
code. They are two different interfaces which work completely
differently. You are attempting to compare apples and oranges.

>> I told you you were wrong, and exactly why you were wrong.
>
> I beg to differ. You're quick enough to play the "you're wrong" card, but
> somehow cannot bring yourself to explain how you came to that conclusion, or
> what should have been done instead. In other words: you do not seem to be
> out to actually *help*.
>

I explained it in very simple terms. That you do not accept that
explanation is not my problem.

>
> I have an idea: You keep posting messages consisting outof "you're wrong"
> lines with no explanation for such a stance and/or what you think should be
> done instead, and I will try to ignore them as much as I can. What do you
> think ? Its a deal ? :-)
>

I think you should try to understand what people say instead of arguing
how you *think it should work*. Especially when you are wrong.

R.Wieser

unread,
Jun 27, 2016, 10:43:36 AM6/27/16
to
Christoph,

> There is SQLite3Result::finalize(),

Thanks for that, a quick google shows that "$results->finalize()" is the PHP
syntax for it.

So, I *should* first finalize the $result object, and only than close the
$statement object.

Hmmm ... I wonder what other $statement object related methods will have a
similar effect on the $results object (like "$statement->clear()" )

> but if you don't call it explicitly, it will be called by SQLite3Result's
> destructor[1], which should be called by SQLite3Stmt's destructor[2].

Whurps. Instead of the childs telling the parent its not needed anymore,
the parent needs to remember all of its childs to be able to tell them when
it dies. And every child needs to tell its parent when it gets finalized,
otherwise the parent might try to finalize a child thats no longer there ...

... Or it means that every SQLite3Stmt object can only have a single
SQLite3Result object linked to it at a time ...

> Maybe that's what <https://bugs.php.net/69971> is about?

There is no way for me to find that out I'm afraid: Its marked as private.
:-\ :-)

> The automatic memory management of PHP is actually mainly
> done by reference counting[3], so basically works the same,
> unless one explicitly calls ::close().

Two things:
First, if "::close()" force-closes an object (overriding the reference count
not being Zero) and by it (potentially) creating all kinds of havoc ?
Thats hard to imagine ...

And second, how do I tell an object like SQLite3Stmt that I do not need it
anymore and only really have it close when all its dependant SQLite3Result
objects are finalized ? Assuming that is possible ...

> But then a programmer would not be aware that he'd have to
> explicitly set the statement to null to force closing the statement.

Ah. I thought you ment that you wanted the PHP language itself to manage
the nitty-gritty of when an object like SQLite3Stmt should be cleaned up.

Thanks for the info. Though I'm afraid I need to do a bit more work before
I will be able to understand how those SQLite3Stmt and SQLite3Result
interact (and why). And if its a php_sqlite3.dll thing, or generic to all
objects in PHP.

Regards,
Rudy Wieser


-- Origional message:
Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
nkr9vk$boi$1...@solani.org...

R.Wieser

unread,
Jun 28, 2016, 6:43:20 AM6/28/16
to
Christoph,

I just took a look at the sourcecode of PHP 5.4.29 (last one available for
XP), and noticed the below in the SQLite3Result::fetchArray method:

SQLITE3_CHECK_INITIALIZED(result_obj->db_obj,
result_obj->stmt_obj->initialised, SQLite3Result)

The SQLITE3_CHECK_INITIALIZED looks like this:

#define SQLITE3_CHECK_INITIALIZED(db_obj, member, class_name) \
if (!(member)) { \
php_sqlite3_error(db_obj, "The " #class_name " object has not been
correctly initialised"); \
RETURN_FALSE; \
}

In short, it generates an error citing the result object as the source/cause
when the statement object appears not to be initialized, which is a WTF in
itself. But it also throws the very same error when the statement object is
not actually present (has been closed), which another WTF altogether. :-\

Also when looking at the SQLite3Result::finalize method I do not really see
any kind of reference count being updated (for either the object itself or
its parent, the SQLite3Stmt object). It looks like it simply doesn't have
a build-in mechanism to keep track of dependancies.


Hmmm ... I wanted to make a remark about the above check being present in
this method too, making it impossible for the result object to be destroyed
when the statement object has been closed before it, but looking further
down the code I realized that the result object, when its generated(?) by a
prepared statement, isn't destroyed, cleared or done anything else with
anyway. :-o :-)


Well, this (no dependancy handling) explains why I couldn't get any results
when I told the statement object I didn't need it anymore, as well as
showing that the result object is very dependant on the statement object
itself -- It doesn't actually do anything itself, but defers everything to
the statement object.

Oh well, I just need to rember that in PHP I need to (keep) track (of)
object dependancies myself I guess. :-\

Regards,
Rudy Wieser


-- Origional message:
R.Wieser <add...@not.available> schreef in berichtnieuws
57713b8f$0$5833$e4fe...@news.xs4all.nl...
> Christoph,

[Snip]

Christoph M. Becker

unread,
Jun 28, 2016, 9:25:09 AM6/28/16
to
On 28.06.2016 at 12:45, R.Wieser wrote:

> I just took a look at the sourcecode of PHP 5.4.29 (last one available for
> XP), and noticed the below in the SQLite3Result::fetchArray method:
>
> […]
>
> In short, it generates an error citing the result object as the source/cause
> when the statement object appears not to be initialized, which is a WTF in
> itself. But it also throws the very same error when the statement object is
> not actually present (has been closed), which another WTF altogether. :-\

I have to admit that this behavior is somewhat strange. On the other
hand, would the following message be really more helpful:

| Warning: SQLite3Result::fetchArray(): The SQLite3Stmt object has
| not been correctly initialised

Maybe a bit.

> Hmmm ... I wanted to make a remark about the above check being present in
> this method too, making it impossible for the result object to be destroyed
> when the statement object has been closed before it, but looking further
> down the code I realized that the result object, when its generated(?) by a
> prepared statement, isn't destroyed, cleared or done anything else with
> anyway. :-o :-)

I assume that the developers did that as a deliberate design decision,
because destroying the result object can be done when the prepared
statement object is destroyed, so that it could be reused for the same
prepared statement, if necessary.

> Well, this (no dependancy handling) explains why I couldn't get any results
> when I told the statement object I didn't need it anymore, as well as
> showing that the result object is very dependant on the statement object
> itself -- It doesn't actually do anything itself, but defers everything to
> the statement object.

That appears to be a reasonable design decision, because the sqlite3
library doesn't have any form of result object; instead everything (e.g.
fetching the next row, querying columns, etc.) is done on sqlite3_stmt
objects (thus, the strong coupling between SQLite3Stmt and
SQLite3Result). Neither does PDO, by the way.

> Oh well, I just need to rember that in PHP I need to (keep) track (of)
> object dependancies myself I guess. :-\

No, at least not generally. The Zend engine does track object
dependencies wrt. automatic memory management. Most (if not all)
extensions do rely on that, and that usually works fine (besides some
known issues wrt. cyclic references, which are tolerated for performance
reasons).

From what I can tell (it's getting rather tricky there), the sqlite3
extension also relies on the Zend engine's memory management; of course,
there might be bugs in this regard, but the extension has a pretty fair
code coverage[1], and at least sometimes the tests are supposed to be
run with valgrind enabled, which would report any memory leaks.

[1] <http://gcov.php.net/PHP_5_6/lcov_html/ext/sqlite3/sqlite3.c.gcov.php>

--
Christoph M. Becker

R.Wieser

unread,
Jun 28, 2016, 12:39:03 PM6/28/16
to
Christoph,

> I have to admit that this behavior is somewhat strange. On the
> other hand, would the following message be really more helpful:
>
> | Warning: SQLite3Result::fetchArray(): The SQLite3Stmt object
> | has not been correctly initialised
>
> Maybe a bit.

Remove the word "correctly" (a word which seems to indicate either some kind
of system failure, or something else that also needs to be done) and its
indeed actual cause of the function (method) not being able to perform its
task.

> I assume that the developers did that as a deliberate design
> decision, because destroying the result object can be done
> when the prepared statement object is destroyed, so that it
> could be reused for the same prepared statement, if necessary.

True, but in that case I expect such an object to be flagged as "free" or
"in use" somehow. And I did not see anything like that either.

I also had some fun with trying stuff like the below:

prepare - bind - execute(1) - bind - execute(2) - fetchArray(1) -
fetchArray(2)

In the above case both of the above fetchArray calls, even though they are
called on different results objects, seem to be eating from the same
through. As if every statement object can only maintain a single set of
result data.

Thinking of it I would probably have choosen to implement something to, in
cases like this, invalidate the first results object (it sure as heck does
not return the expected results ...).

> instead everything (e.g. fetching the next row, querying columns,
> etc.) is done on sqlite3_stmt objects

I seem to remember the same thing (a bit of time ago I've been tinkering
with some "real" code to access a small sqlite3 database). Its just that
I assumed that the whole underlying sqlite3_stmt object would be handed off
to PHP's result object -- freeing PHP statement object for the preparation
of a next query.

> No, at least not generally. The Zend engine does track object
> dependencies wrt. automatic memory management.

Good to know. Though than odd that it doesn't quite seem to work for the
SQLite3Stmt object ... There must be more to it.

> From what I can tell (it's getting rather tricky there), the
> sqlite3 extension also relies on the Zend engine's memory
> management;

I see all kinds of usage of that Zend memory manager in there, so I have to
assume you're correct. :-)

> of course, there might be bugs in this regard,

There might, but as its used everywhere it would most likely have popped up
its head meach earlier. In other words: possible, but not likely.

No, I'm afraid that my inexperience with the usage of the sqlite extension,
PHP objects in general as well as not quite being able to make sense of the
error message and having a few unfundated expectations is laying at the
bottom of this all.

I probably will have some fun time ahead by stumbling into other PHP and
extension pitfals and trying to make sense of why they are/"need" to be
there. :-)

Thanks for your responses.

Regards,
Rudy Wieser


-- Origional message:
Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
nkttrg$g1i$1...@solani.org...
> On 28.06.2016 at 12:45, R.Wieser wrote:
>
> > I just took a look at the sourcecode of PHP 5.4.29 (last one available
for
> > XP), and noticed the below in the SQLite3Result::fetchArray method:
> >
> > [.]

Christoph M. Becker

unread,
Jun 28, 2016, 1:29:51 PM6/28/16
to
On 28.06.2016 at 18:41, R.Wieser wrote:

> Christoph M. Becker <cmbec...@arcor.de> schreef in berichtnieuws
> nkttrg$g1i$1...@solani.org...
>
>> | Warning: SQLite3Result::fetchArray(): The SQLite3Stmt object
>> | has not been correctly initialised
>
> Remove the word "correctly" (a word which seems to indicate either some kind
> of system failure, or something else that also needs to be done) and its
> indeed actual cause of the function (method) not being able to perform its
> task.

Hm, it seems your right. I'll check some of the other messages; some of
them might be similarly strange.

> prepare - bind - execute(1) - bind - execute(2) - fetchArray(1) -
> fetchArray(2)
>
> In the above case both of the above fetchArray calls, even though they are
> called on different results objects, seem to be eating from the same
> through. As if every statement object can only maintain a single set of
> result data.

Indeed, that's the case. Consider that fetchArray() basically just
calls sqlite3_step – always on the same statement object. Of course,
this should be documented.

>> No, at least not generally. The Zend engine does track object
>> dependencies wrt. automatic memory management.
>
> Good to know. Though than odd that it doesn't quite seem to work for the
> SQLite3Stmt object ... There must be more to it.

The crux is that non memory-management related dependencies are not
catered to by the Zend engine. That's up to the extension.

The actual design of the sqlite3 extension wrt. statement and their
results might not be optimal, but it's rather unlikely that this will be
changed (for backward compatibility reasons). It might be possible to
do that for PHP 8.0, but even that would require the RFC process, and
the RFC might be declined. Not sure, if that would be worth the effort.

> I probably will have some fun time ahead by stumbling into other PHP and
> extension pitfals and trying to make sense of why they are/"need" to be
> there. :-)

Yes, most likely. However, there is this newsgroup… :)

--
Christoph M. Becker
0 new messages