[GRASS-dev] SQLite driver problem

Hi,

I have some troubles with the SQLite driver with a SELECT statement:

GRASS 6.4.1svn (patGB1):~ > echo 'SELECT cat FROM
MRR1_09_marked_csv_lines_id ' | db.execute
D2/3: dbDbmscap(): opendir
[/home/neteler/grass64/dist.x86_64-unknown-linux-gnu/driver/db/]
D2/3: dbDbmscap(): opendir
[/home/neteler/grass64/dist.x86_64-unknown-linux-gnu/driver/db/]
D3/3:
db_driver_open_database()
D3/3: name = '$GISDBASE/$LOCATION_NAME/$MAPSET/sqlite.db'
D3/3: tokens[0] = $GISDBASE
D3/3: -> /home/neteler/grassdata
D3/3: tokens[1] = $LOCATION_NAME
D3/3: -> patGB1
D3/3: tokens[2] = $MAPSET
D3/3: -> fra_sqlite
D3/3: tokens[3] = sqlite.db
D2/3: name2 = '/home/neteler/grassdata/patGB1/fra_sqlite/sqlite.db'
D3/3: sql: SELECT cat FROM MRR1_09_marked_csv_lines_id

D3/3: execute: SELECT cat FROM MRR1_09_marked_csv_lines_id

DBMI-SQLite driver error:
Error in sqlite3_step():
unknown error

ERROR: Error while executing: 'SELECT cat FROM MRR1_09_marked_csv_lines_id
       '

But within "sqlite3", the statement works:

sqlite3 $HOME/grassdata/patGB1/fra_sqlite/sqlite.db
SQLite version 3.7.3
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> SELECT cat,count(length) FROM MRR1_09_marked_csv_lines_id
GROUP BY length;
23|23
39|16
90|29
...
sqlite>

I wonder what the problem could be...

Markus

On 14/12/10 16:11, Markus Neteler wrote:

Hi,

I have some troubles with the SQLite driver with a SELECT statement:

GRASS 6.4.1svn (patGB1):~> echo 'SELECT cat FROM
MRR1_09_marked_csv_lines_id ' | db.execute

I wonder what the problem could be...

s/db.execute/db.select

Moritz

On Tue, Dec 14, 2010 at 4:43 PM, Moritz Lennert
<mlennert@club.worldonline.be> wrote:

On 14/12/10 16:11, Markus Neteler wrote:

Hi,

I have some troubles with the SQLite driver with a SELECT statement:

GRASS 6.4.1svn (patGB1):~> echo 'SELECT cat FROM
MRR1_09_marked_csv_lines_id ' | db.execute

I wonder what the problem could be...

s/db.execute/db.select

Cool.

But I thought that both did essentially the same job? Apparently not... I wonder
if we could trap "SELECT" in db.execute and point the user to db.select.
?

Markus

On 14/12/10 16:49, Markus Neteler wrote:

On Tue, Dec 14, 2010 at 4:43 PM, Moritz Lennert
<mlennert@club.worldonline.be> wrote:

On 14/12/10 16:11, Markus Neteler wrote:

Hi,

I have some troubles with the SQLite driver with a SELECT statement:

GRASS 6.4.1svn (patGB1):~> echo 'SELECT cat FROM
MRR1_09_marked_csv_lines_id ' | db.execute

I wonder what the problem could be...

s/db.execute/db.select

Cool.

But I thought that both did essentially the same job? Apparently not...

No, db.select is only for selection and db.execute is for any other db manipulations (update, delete, insert, create table, etc). They use different functions to interact with the DB. Don't know what Radim's reasoning was behind this, but I guess he had a good one :-).

I wonder
if we could trap "SELECT" in db.execute and point the user to db.select.
?

That's not as easy as it sounds, since you might have SELECT clauses in UPDATE and other db.execute clauses (e.g. INSERT INTO mytable SELECT x, y, z FROM othertable). So the trapping would have to be a bit more sophisticated, at least looking out for a SELECT at the beginning of the statement. But definitely possible. Probably best done right before the

ret = db_execute_immediate(driver, &stmt);

at
line 74 of db/base/execute.c (grass6)
or
line 75 of /db/db.execute/main.c (grass_trunk)

Moritz

Moritz wrote:

> s/db.execute/db.select

Markus wrote:

Cool.

But I thought that both did essentially the same job?

nope.

Apparently not... I wonder if we could trap "SELECT" in
db.execute and point the user to db.select.
?

I recall that Radim gave a good explanation about why they had
to be separated; probably to be found in the ML archives near to
the time when this was added to the db.execute man page:
"""
NOTES
       db.execute only executes SQL statements and does not return any data. If you need
       data returned from the database, use db.select.
"""

Hamish

Moritz Lennert wrote:

>> s/db.execute/db.select
>
> Cool.
>
> But I thought that both did essentially the same job? Apparently not...

No, db.select is only for selection and db.execute is for any other db
manipulations (update, delete, insert, create table, etc). They use
different functions to interact with the DB. Don't know what Radim's
reasoning was behind this, but I guess he had a good one :-).

A select command returns data; the others return only a status
indication. This is typically reflected in the underlying API (libpq,
sqlite, etc) having different interfaces for queries (select
statements) and other statements.

--
Glynn Clements <glynn@gclements.plus.com>

On 14/12/10 18:49, Moritz Lennert wrote:

I wonder
if we could trap "SELECT" in db.execute and point the user to db.select.
?

That's not as easy as it sounds, since you might have SELECT clauses in
UPDATE and other db.execute clauses (e.g. INSERT INTO mytable SELECT x,
y, z FROM othertable). So the trapping would have to be a bit more
sophisticated, at least looking out for a SELECT at the beginning of the
statement.

Even that would not work as some RDMS (e.g. PostgreSQL) allow a syntax such as

SELECT * INTO table2 FROM table1

(equivalent to CREATE TABLE table2 AS SELECT * FROM table1)

which is a db.execute statement...

Not sure that there is a better solution than the hint in the NOTES section of the man page Hamish pointed to.

Moritz