Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-19 Thread Neil Cerutti
On 2017-10-19, Alan Gauld via Tutor  wrote:
> On 18/10/17 21:09, Albert-Jan Roskam wrote:
>> 
>> On Oct 16, 2017 15:12, Neil Cerutti  wrote:
>
>>> sqlite3 module. In sqlite modifying table definitions is limited
>>> to the simple addition of a new row of data. 
>
>> 
>> Really? How so? I used ALTER TABLE ADD COLUMN the other day, 
>
> I think Neil meant that Sqlite ALTER is limited to adding
> *columns*. Adding rows would be an INSERT not an ALTER.
>
> The only other thing SQLite ALTER can do is change the table name.
>
> But most SQLs allow you to modify existing column definitions
> too, such as add defaults or conditions. You can't do that in
> SQLite, you need to create a new table (TEMP)and copy the data
> across then drop the old table and rename the new one to the
> old. All a bit tedious.

Yes, I meant sqlite can only add columns. Thanks for the
corrections.

-- 
Neil Cerutti

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-19 Thread Alan Gauld via Tutor
On 18/10/17 21:09, Albert-Jan Roskam wrote:
> 
> On Oct 16, 2017 15:12, Neil Cerutti  wrote:

>> sqlite3 module. In sqlite modifying table definitions is limited
>> to the simple addition of a new row of data. 

> 
> Really? How so? I used ALTER TABLE ADD COLUMN the other day, 

I think Neil meant that Sqlite ALTER is limited to adding *columns*.
Adding rows would be an INSERT not an ALTER.

The only other thing SQLite ALTER can do is change the table name.

But most SQLs allow you to modify existing column definitions too,
such as add defaults or conditions. You can't do that in SQLite,
you need to create a new table (TEMP)and copy the data  across
then drop the old table and rename the new one to the old.
All a bit tedious.

-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-18 Thread Albert-Jan Roskam

On Oct 16, 2017 15:12, Neil Cerutti  wrote:
>
> On 2017-10-15, boB Stepp  wrote:
> > Some things I am still pondering:
> >
> > 1)  If I adopt the incremental approach to creating and
> > initializing the working db, then it seems that the list,
> > "sql_scripts", should not be hard-coded into the program.  It
> > seems to me it should be off somewhere by itself with perhaps
> > other things that might evolve/change over time in its own file
> > where it (and its brethren) are easy to locate and update.
>
> An incremental approach is not recommended if you are using the
> sqlite3 module. In sqlite modifying table definitions is limited
> to the simple addition of a new row of data. Any other change
> requires you to create a new table, copy the old data into it,
> and then drop the old table.

Really? How so? I used ALTER TABLE ADD COLUMN the other day, which is part of 
this SQL dialect: https://sqlite.org/lang_altertable.html
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-16 Thread Neil Cerutti
On 2017-10-15, boB Stepp  wrote:
> Some things I am still pondering:
>
> 1)  If I adopt the incremental approach to creating and
> initializing the working db, then it seems that the list,
> "sql_scripts", should not be hard-coded into the program.  It
> seems to me it should be off somewhere by itself with perhaps
> other things that might evolve/change over time in its own file
> where it (and its brethren) are easy to locate and update.

An incremental approach is not recommended if you are using the
sqlite3 module. In sqlite modifying table definitions is limited
to the simple addition of a new row of data. Any other change
requires you to create a new table, copy the old data into it,
and then drop the old table.

> 3)  I am supposed to be delving into writing classes on this
> project. Should the code so far stay as a function or get
> incorporated into a class?  My original intent was to do a
> class for the BloodPressureReadings table, but I am not at the
> point of going there yet.

I don't recommend cobbling together your own ORM, if that's what
you are asking. ;)

> 4)  I wish there was a PEP 8 for SQL!  I have several SQL books
> I have consulted, but I have gotten conflicting suggestions for
> SQL code style.  I have tried to adopt something that seems to
> me to be both consistent and reasonable, but is it good enough?

As long as you can imagine yourself reading it two years from
now, and being able to understand it and make changes, it's
probably an OK style. The two big hurdles for me were acquiescing
to uppercase all the SQL keywords, and learning the quoting
rules. My impression is that SQL is very old, and so lots of
different styles are valid and just fine to use. Your main goal,
at first, should be to stick with standard SQL as much as you
possibly can, to make it easier to switch database engines should
you ever wish to do so.

-- 
Neil Cerutti

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-15 Thread Peter Otten
boB Stepp wrote:

> I was thinking ahead to a follow-up project, the chess rating db.  For
> this I had contemplated having separate sqlite3 database files for
> each school year instead of adding school year information to a single
> database.

Then you need to access multiple databases to see the full history of a 
student and you will end up with a lot of redundant information (name, 
birthday, contact information); if there's an error in the data it will 
typically only be corrected for the latest year, your users will come up 
with creative ways to copy data from one year to the next, introducing 
errors in the process...

In short: it will be a be a mess.


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-15 Thread Peter Otten
boB Stepp wrote:

> On Sun, Oct 15, 2017 at 3:09 AM, Peter Otten <__pete...@web.de> wrote:
>> boB Stepp wrote:
>>
>>> I have not used a "finally" block before.  I just had the thought that
>>> maybe it would run even if an uncaught exception might occur.  I tried
>>> to test this thought by generating a deliberate NameError in the "try"
>>> block and added a print to the "finally" clause.  I got the intended
>>> NameError with no evidence of the added print printing.  But I thought
>>> I would ask just to be sure:  If an uncaught exception occurs, will
>>> the "finally" clause execute?
>>
>>
>> Yes.
>>
> try:
>> ... 1/0
>> ... except ValueError:
>> ... print("not triggered")
>> ... finally:
>> ... print("ALWAYS TRIGGERED")
>> ...
>> ALWAYS TRIGGERED
>> Traceback (most recent call last):
>>   File "", line 2, in 
>> ZeroDivisionError: division by zero
> 
> That is what I thought after reading about "finally".  But look what
> happens if I modify my actual code to generate a NameError:

 
> def ensure_db(filename):
> """Open the database, "filename", if it exists; otherwise, create a
> database named "filename"."""
> 
> db = sqlite3.connect(filename)
> cur = db.cursor()
> 
> try:
> sql_cmd = "SELECT VersionNumber FROM CurrentDBVersion"
> a# This should generate a NameError

Note that at this point `current_db_version` is not yet defined.

> # First element of returned tuple will be the db version number:
> current_db_version = int(cur.execute(sql_cmd).fetchone()[0])
> 
> except sqlite3.OperationalError:
> # This means that the database and the table, "CurrentDBVersion",
> # has not yet been created, implying "version 0".
> current_db_version = 0
> 
> finally:
> sql_scripts = ["../database/create_sqlite3_db.sql"]
> for sql_scriptname in sql_scripts[current_db_version:]:

The finally suite was entered, but now there's another NameError (an 
UnboundLocalError, to be precise), for current_db_version, inside it. Code 
inside the finally suite is executed like it would be anywhere else, so 
anything after the point where the exception was triggered is not run.

> with open(sql_scriptname) as f:
> cur.executescript(f.read())
> print("THIS IS THE FINALLY BLOCK!!!")  # And this *should* print
> 
> return db
 
 
> This results in the following Traceback:
 

>> py main.py
> Traceback (most recent call last):
>   File "main.py", line 16, in ensure_db
> a
> NameError: name 'a' is not defined
> 
> During handling of the above exception, another exception occurred:
> 
> Traceback (most recent call last):
>   File "main.py", line 36, in 
> ensure_db(db_filename)
>   File "main.py", line 27, in ensure_db
> for sql_scriptname in sql_scripts[current_db_version:]:
> UnboundLocalError: local variable 'current_db_version' referenced
> before assignment

While I tend to find chained exceptions annoying they *do* provide all the 
necessary information.
 
> So what is going on here?  Why does "finally" not have its print
> executed?  Does the "...another exception occurred:..." interrupt the
> normal flow of the "try/except/finally" structure and prevent the
> "finally" block from executing?
> 


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-15 Thread boB Stepp
On Sun, Oct 15, 2017 at 2:56 AM, Peter Otten <__pete...@web.de> wrote:
> boB Stepp wrote:

>>
>> I am puzzled.  If one is using version control, then what is the
>> advantage of this incremental approach in creating and populating the
>> database?  Instead, why not just have a single SQL file that generates
>> the finished initial state of the db for the current version?  One can
>> always use the version control system to roll back to an earlier
>> stage.
>
> My idea was presented under the assumption that the there is user data
> entered in version 1 that needs to be preserved when version 2 of the
> application replaces 1.

Ah!  I was missing the forest for the trees.  Sorry 'bout that!

>> I have chickened out and not done a TDD approach yet.  I will probably
>> pause here, wait for feedback from this list, and try to figure out
>> how I should test what I have so far.  And how do you test SQL scripts
>> anyway?
>
> Example: Run the routine to enter a row, then check if it's there and
> contains what you expected. That should fail before the script is run, and
> succeed afterwards.

I guess what bothers me here is that it seems I have to write some
code in the tests file just to get the test database to the point
where I can write the necessary asserts.  But I would have to do that
anyway, wouldn't I?  The whole point of test fixtures, setup and tear
down code, etc.  It just looks like testing dbs will be somewhat
messier than what I have dealt with to date.

>>
>> Some things I am still pondering:
>>
>> 1)  If I adopt the incremental approach to creating and initializing
>> the working db, then it seems that the list, "sql_scripts", should not
>> be hard-coded into the program.  It seems to me it should be off
>> somewhere by itself with perhaps other things that might evolve/change
>> over time in its own file where it (and its brethren) are easy to
>> locate and update.
>
> I think it should be hardcoded. You don't want to run arbitrary scripts that
> happen to be in a folder, say. Version control can take care of any changes.

In some ways I think too much.  I struggle here on what should be my
best practice, to minimize the amount of hard-coded data (I think
usually a good idea.) or, in a particular case like this one, to do
the hard-coding.

>>
>> 2)  Likewise, "db_filename", is currently hard-coded in the if block
>> to start the program.  I have not decided yet what the end result will
>> be, but I might want to allow for the possibility of allowing the user
>> (me) to create multiple databases.
>
> If one user needs multiple databases that /may/ be an indication that you
> are not storing enough information in the database.

I was thinking ahead to a follow-up project, the chess rating db.  For
this I had contemplated having separate sqlite3 database files for
each school year instead of adding school year information to a single
database.

-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-15 Thread boB Stepp
On Sun, Oct 15, 2017 at 3:09 AM, Peter Otten <__pete...@web.de> wrote:
> boB Stepp wrote:
>
>> I have not used a "finally" block before.  I just had the thought that
>> maybe it would run even if an uncaught exception might occur.  I tried
>> to test this thought by generating a deliberate NameError in the "try"
>> block and added a print to the "finally" clause.  I got the intended
>> NameError with no evidence of the added print printing.  But I thought
>> I would ask just to be sure:  If an uncaught exception occurs, will
>> the "finally" clause execute?
>
>
> Yes.
>
 try:
> ... 1/0
> ... except ValueError:
> ... print("not triggered")
> ... finally:
> ... print("ALWAYS TRIGGERED")
> ...
> ALWAYS TRIGGERED
> Traceback (most recent call last):
>   File "", line 2, in 
> ZeroDivisionError: division by zero

That is what I thought after reading about "finally".  But look what
happens if I modify my actual code to generate a NameError:


def ensure_db(filename):
"""Open the database, "filename", if it exists; otherwise, create a
database named "filename"."""

db = sqlite3.connect(filename)
cur = db.cursor()

try:
sql_cmd = "SELECT VersionNumber FROM CurrentDBVersion"
a# This should generate a NameError
# First element of returned tuple will be the db version number:
current_db_version = int(cur.execute(sql_cmd).fetchone()[0])

except sqlite3.OperationalError:
# This means that the database and the table, "CurrentDBVersion", has
# not yet been created, implying "version 0".
current_db_version = 0

finally:
sql_scripts = ["../database/create_sqlite3_db.sql"]
for sql_scriptname in sql_scripts[current_db_version:]:
with open(sql_scriptname) as f:
cur.executescript(f.read())
print("THIS IS THE FINALLY BLOCK!!!")  # And this *should* print

return db


This results in the following Traceback:


> py main.py
Traceback (most recent call last):
  File "main.py", line 16, in ensure_db
a
NameError: name 'a' is not defined

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "main.py", line 36, in 
ensure_db(db_filename)
  File "main.py", line 27, in ensure_db
for sql_scriptname in sql_scripts[current_db_version:]:
UnboundLocalError: local variable 'current_db_version' referenced
before assignment


So what is going on here?  Why does "finally" not have its print
executed?  Does the "...another exception occurred:..." interrupt the
normal flow of the "try/except/finally" structure and prevent the
"finally" block from executing?

-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-15 Thread Peter Otten
boB Stepp wrote:

> I have not used a "finally" block before.  I just had the thought that
> maybe it would run even if an uncaught exception might occur.  I tried
> to test this thought by generating a deliberate NameError in the "try"
> block and added a print to the "finally" clause.  I got the intended
> NameError with no evidence of the added print printing.  But I thought
> I would ask just to be sure:  If an uncaught exception occurs, will
> the "finally" clause execute?


Yes.

>>> try:
... 1/0
... except ValueError:
... print("not triggered")
... finally:
... print("ALWAYS TRIGGERED")
... 
ALWAYS TRIGGERED
Traceback (most recent call last):
  File "", line 2, in 
ZeroDivisionError: division by zero

If something seems too complex in your real code try to come up with a 
similar setup in the interactive interpreter (or use a minimal demo script 
if that proves impractical).

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-15 Thread Peter Otten
boB Stepp wrote:

> On Sat, Oct 14, 2017 at 4:45 AM, Peter Otten <__pete...@web.de> wrote:
> 
>> If this is a long term project there will be changes in the schema.
>> However, I don't think it is necessary to check for individual tables.
>> You typically start with a few tables
>>
>> create table alpha
>> create table beta
>> create table gamma
>>
>> and later add a few more or change columns
>>
>> alter table alpha
>> create table delta
>>
>> In this example you have three versions of the database
>>
>> version 0: empty
>> version 1: three tables
>> version 2: four tables, one table modified
>>
>> If you add a table for your own metadata you ownly need to store that
>> version number. The necessary steps when you open the database are then
>>
>> - read version from bobs_metadata (if that fails you are at version 0)
>>
>> If you are at version 0 "migrate" to version one:
>>
>> - execute script that creates alpha, beta, gamma, and bobs_metadata, the
>>   latter with one row containing version=1
>>
>> If you are at version 1 migrate to version two:
>>
>> - execute migration script from 1 to 2 modifying alpha, creating delta,
>> and
>>   updating to version=2
>>
>> If you are at version 2:
>>
>> - do nothing, database is already in the state required by your
>> application.
> 
> I am puzzled.  If one is using version control, then what is the
> advantage of this incremental approach in creating and populating the
> database?  Instead, why not just have a single SQL file that generates
> the finished initial state of the db for the current version?  One can
> always use the version control system to roll back to an earlier
> stage.

My idea was presented under the assumption that the there is user data 
entered in version 1 that needs to be preserved when version 2 of the 
application replaces 1.


> I have chickened out and not done a TDD approach yet.  I will probably
> pause here, wait for feedback from this list, and try to figure out
> how I should test what I have so far.  And how do you test SQL scripts
> anyway?

Example: Run the routine to enter a row, then check if it's there and 
contains what you expected. That should fail before the script is run, and 
succeed afterwards.

> 
> Some things I am still pondering:
> 
> 1)  If I adopt the incremental approach to creating and initializing
> the working db, then it seems that the list, "sql_scripts", should not
> be hard-coded into the program.  It seems to me it should be off
> somewhere by itself with perhaps other things that might evolve/change
> over time in its own file where it (and its brethren) are easy to
> locate and update.

I think it should be hardcoded. You don't want to run arbitrary scripts that 
happen to be in a folder, say. Version control can take care of any changes.

> 
> 2)  Likewise, "db_filename", is currently hard-coded in the if block
> to start the program.  I have not decided yet what the end result will
> be, but I might want to allow for the possibility of allowing the user
> (me) to create multiple databases.  

If one user needs multiple databases that /may/ be an indication that you 
are not storing enough information in the database.

Bad: one database per patient. You are using the file system as a meta-
database.

Better: an additional patients table and a column patientid in all tables 
containing patient data.

> Also, when I figure out how to
> test this database stuff, I imagine I will be using a test db for the
> testing, not the actual one.  Again, this argues for not hard-coding
> the database name.
> 
> 3)  I am supposed to be delving into writing classes on this project.
> Should the code so far stay as a function or get incorporated into a
> class?  My original intent was to do a class for the
> BloodPressureReadings table, but I am not at the point of going there
> yet.

Relax. A function is an instance of a class with no state and a __call__ 
method ;)

> 4)  I wish there was a PEP 8 for SQL!  I have several SQL books I have
> consulted, but I have gotten conflicting suggestions for SQL code
> style.  I have tried to adopt something that seems to me to be both
> consistent and reasonable, but is it good enough?
> 
> I await the arrival of the list's wisdom!
> 
> Cheers!


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread boB Stepp
On Sun, Oct 15, 2017 at 12:07 AM, boB Stepp  wrote:

> 
> #!/usr/bin/env python3
>
> """This file starts the blood pressure readings program."""
>
> import sqlite3
>
> def ensure_db(filename):
> """Open the database, "filename", if it exists; otherwise, create a
> database named "filename"."""
>
> db = sqlite3.connect(filename)
> cur = db.cursor()
>
> try:
> sql_cmd = "SELECT VersionNumber FROM CurrentDBVersion"
>
> # First element of returned tuple will be the db version number:
> current_db_version = int(cur.execute(sql_cmd).fetchone()[0])
>
> except sqlite3.OperationalError:
> # This means that the database and the table, "CurrentDBVersion", has
> # not yet been created, implying "version 0".
> current_db_version = 0
>
> finally:
> sql_scripts = ["../database/create_sqlite3_db.sql"]
> for sql_scriptname in sql_scripts[current_db_version:]:
> with open(sql_scriptname) as f:
> cur.executescript(f.read())
>
> return db

I have not used a "finally" block before.  I just had the thought that
maybe it would run even if an uncaught exception might occur.  I tried
to test this thought by generating a deliberate NameError in the "try"
block and added a print to the "finally" clause.  I got the intended
NameError with no evidence of the added print printing.  But I thought
I would ask just to be sure:  If an uncaught exception occurs, will
the "finally" clause execute?

>
> I have chickened out and not done a TDD approach yet.  I will probably
> pause here, wait for feedback from this list, and try to figure out
> how I should test what I have so far.  And how do you test SQL scripts
> anyway?
>
> Some things I am still pondering:

I forgot to add (5):

5)  How should I handle the cursor object?  When I should I close it?
My function returns "db" which I presume keeps the connection to the
database.  But what happens to the cursor object as I have written the
function, since I never closed it?


-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread boB Stepp
On Sat, Oct 14, 2017 at 4:45 AM, Peter Otten <__pete...@web.de> wrote:

> If this is a long term project there will be changes in the schema.
> However, I don't think it is necessary to check for individual tables. You
> typically start with a few tables
>
> create table alpha
> create table beta
> create table gamma
>
> and later add a few more or change columns
>
> alter table alpha
> create table delta
>
> In this example you have three versions of the database
>
> version 0: empty
> version 1: three tables
> version 2: four tables, one table modified
>
> If you add a table for your own metadata you ownly need to store that
> version number. The necessary steps when you open the database are then
>
> - read version from bobs_metadata (if that fails you are at version 0)
>
> If you are at version 0 "migrate" to version one:
>
> - execute script that creates alpha, beta, gamma, and bobs_metadata, the
>   latter with one row containing version=1
>
> If you are at version 1 migrate to version two:
>
> - execute migration script from 1 to 2 modifying alpha, creating delta, and
>   updating to version=2
>
> If you are at version 2:
>
> - do nothing, database is already in the state required by your application.

I am puzzled.  If one is using version control, then what is the
advantage of this incremental approach in creating and populating the
database?  Instead, why not just have a single SQL file that generates
the finished initial state of the db for the current version?  One can
always use the version control system to roll back to an earlier
stage.

> Pseudo-code:
>
> scripts = ["0to1.sql", "1to2.sql"]
> current_version = get_schema_version() # this has to catch the
># OperationalError
> for scriptname in scripts[current_version:]:
> with open(scriptname) as f:
> script = f.read()
> executescript(script)

My current project structure for this program:

blood_pressures/
|.git/
|blood_pressures/
||--__init__.py
||--main.py
|database/
||--__init__.py# Is this really needed in this folder?
||--blood_pressure.db
||--create_sqlite3_db.sql
|tests/
||--__init__.py# Oh, no!  No tests yet!!
.gitignore

The current SQL file, create_sqlite3_db.sql:


-- This file will create version 1 of the database.

CREATE TABLE BloodPressureReadings (
ReadingID INTEGER PRIMARY KEY,
Date TEXT,
Time TEXT,
SystolicBP INTEGER,
DiastolicBP INTEGER,
Comments TEXT);

-- This table is intended to only have one row with one entry:  the current
-- database version.  Whenever the program is started this entry will be checked
-- to determine if the database needs to be updated (or not) to the current
-- version from the earlier SQL database creation files.
CREATE TABLE CurrentDBVersion (
VersionNumber INTEGER);

-- Insert starting version number of database:
INSERT INTO CurrentDBVersion (VersionNumber) VALUES (1);


And my current effort to implement your guidance:


#!/usr/bin/env python3

"""This file starts the blood pressure readings program."""

import sqlite3

def ensure_db(filename):
"""Open the database, "filename", if it exists; otherwise, create a
database named "filename"."""

db = sqlite3.connect(filename)
cur = db.cursor()

try:
sql_cmd = "SELECT VersionNumber FROM CurrentDBVersion"

# First element of returned tuple will be the db version number:
current_db_version = int(cur.execute(sql_cmd).fetchone()[0])

except sqlite3.OperationalError:
# This means that the database and the table, "CurrentDBVersion", has
# not yet been created, implying "version 0".
current_db_version = 0

finally:
sql_scripts = ["../database/create_sqlite3_db.sql"]
for sql_scriptname in sql_scripts[current_db_version:]:
with open(sql_scriptname) as f:
cur.executescript(f.read())

return db

if __name__ == "__main__":
db_filename = "../database/blood_pressure.db"
ensure_db(db_filename)# Not doing anything with returned db yet.


I have chickened out and not done a TDD approach yet.  I will probably
pause here, wait for feedback from this list, and try to figure out
how I should test what I have so far.  And how do you test SQL scripts
anyway?

Some things I am still pondering:

1)  If I adopt the incremental approach to creating and initializing
the working db, then it seems that the list, "sql_scripts", should not
be hard-coded into the program.  It seems to me it should be o

Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread Peter Otten
boB Stepp wrote:

> On Sat, Oct 14, 2017 at 2:11 AM, boB Stepp  wrote:
> 
>> So I get "None" as a result if the target table has not been created
>> yet.  But if I *do* create the table I want:
>>
>> py3: with open('create_sqlite3_db.sql') as f:
>> ... sql = f.read()
>> ...
>> py3: c.executescript(sql)
>> 
>> py3: tb_exists = "select name from sqlite_master where type='table'
>> and name='BloodPressureReadings'"
>> py3: tb_ck = c.execute(tb_exists).fetchone()
>> py3: print(tb_ck)
>> ('BloodPressureReadings',)
>>
>> So it is looking like I can use this technique to determine if I need
>> to create the BloodPressureReadings table or not.  Am I on track here
>> or is there a better technique?
> 
> It just occurred to me after sending the above, does something like
> "sqlite_master" exist for other database programs than sqlite3?  Can I
> abstract out "sqlite_master" and replace it with a variable so that I
> can handle any kind of database?

If this is a long term project there will be changes in the schema.
However, I don't think it is necessary to check for individual tables. You 
typically start with a few tables

create table alpha
create table beta
create table gamma

and later add a few more or change columns

alter table alpha
create table delta

In this example you have three versions of the database

version 0: empty
version 1: three tables
version 2: four tables, one table modified

If you add a table for your own metadata you ownly need to store that 
version number. The necessary steps when you open the database are then

- read version from bobs_metadata (if that fails you are at version 0)

If you are at version 0 "migrate" to version one:

- execute script that creates alpha, beta, gamma, and bobs_metadata, the
  latter with one row containing version=1

If you are at version 1 migrate to version two:

- execute migration script from 1 to 2 modifying alpha, creating delta, and
  updating to version=2

If you are at version 2:

- do nothing, database is already in the state required by your application.

Pseudo-code:

scripts = ["0to1.sql", "1to2.sql"]
current_version = get_schema_version() # this has to catch the
   # OperationalError
for scriptname in scripts[current_version:]:
with open(scriptname) as f:
script = f.read()
executescript(script)


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread Flynn, Stephen (L & P - IT)
Yep - oracle for example has hundreds of tables which hold metadata.


for example (this will look terrible due to the length of it but if you assume 
it's 3 lines; a title line, some underlining for each column and the data 
itself):


SQL> select * from all_tables where owner = 'FLYNNS' and table_name = 'QC11483';

OWNER  TABLE_NAME TABLESPACE_NAME   
 CLUSTER_NAME   IOT_NAME   
STATUS PCT_FREE   PCT_USED  INI_TRANS  MAX_TRANS INITIAL_EXTENT NEXT_EXTENT 
MIN_EXTENTS MAX_EXTENTS PCT_INCREASE  FREELISTS FREELIST_GROUPS LOGGING 
BACKED_UP   NUM_ROWS BLOCKS EMPTY_BLOCKS  AVG_SPACE  CHAIN_CNT AVG_ROW_LEN 
AVG_SPACE_FREELIST_BLOCKS NUM_FREELIST_BLOCKS DEGREE INSTANCES  CACHE 
TABLE_LOCK SAMPLE_SIZE LAST_ANALYZED PARTITIONED IOT_TYPE TEMPORARY 
SECONDARY NESTED BUFFER_POOL ROW_MOVEMENT GLOBAL_STATS USER_STATS DURATION  
  SKIP_CORRUPT MONITORING CLUSTER_OWNER  DEPENDENCIES 
COMPRESSION DROPPED
-- -- 
-- -- 
--  -- -- -- 
-- -- --- --- ---  
-- --- --- - -- --  
-- -- --- - --- 
-- -- - -- --- - --- 
 - - -- ---   
-- ---  -- 
--  --- ---
FLYNNS QC11483USERS 
   
VALID10 1255  65536 
  1  2147483645 NO  N   
   61517   10000  0  0 108  
   0   0  1  1 N ENABLED
  61517 30/08/2017 16 NO   N N NO 
DEFAULT DISABLED YES  NO DISABLED 
YES   DISABLED DISABLEDNO

Executed in 0.141 seconds


There's something similar for SQL Server, DB2, ADDABAS, PostGres,, and so forth

S.


From: Tutor  on behalf of 
boB Stepp 
Sent: 14 October 2017 08:17
To: tutor
Subject: Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

On Sat, Oct 14, 2017 at 2:11 AM, boB Stepp  wrote:

> So I get "None" as a result if the target table has not been created
> yet.  But if I *do* create the table I want:
>
> py3: with open('create_sqlite3_db.sql') as f:
> ... sql = f.read()
> ...
> py3: c.executescript(sql)
> 
> py3: tb_exists = "select name from sqlite_master where type='table'
> and name='BloodPressureReadings'"
> py3: tb_ck = c.execute(tb_exists).fetchone()
> py3: print(tb_ck)
> ('BloodPressureReadings',)
>
> So it is looking like I can use this technique to determine if I need
> to create the BloodPressureReadings table or not.  Am I on track here
> or is there a better technique?

It just occurred to me after sending the above, does something like
"sqlite_master" exist for other database programs than sqlite3?  Can I
abstract out "sqlite_master" and replace it with a variable so that I
can handle any kind of database?


--
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


This email is security checked and subject to the disclaimer on web-page: 
http://www.capita.co.uk/email-disclaimer.aspx
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread Alan Gauld via Tutor
On 14/10/17 06:43, boB Stepp wrote:

> table if that table does not exist.  Alan suggested using
> executescript() to do this.  I misunderstood Alan and thought that
> this would take a filename and execute it.  

c.executescript(sqlFile.read())


-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread srinivas devaki
On Sat, Oct 14, 2017 at 12:41 PM, boB Stepp  wrote:
> py3: c.executescript(sql)
> 
> py3: tb_exists = "select name from sqlite_master where type='table'
> and name='BloodPressureReadings'"
> py3: tb_ck = c.execute(tb_exists).fetchone()
> py3: print(tb_ck)
> ('BloodPressureReadings',)
>
> So it is looking like I can use this technique to determine if I need
> to create the BloodPressureReadings table or not.  Am I on track here
> or is there a better technique?
>

awesome trick. but most of the time applications had to exported out
of sqlite to either mysql or postgresql at which time it would be a
lot of refactoring as this trick uses sqlite internals to check if a
table exists.

fetchone would always return a tuple as we did count in the sql
instruction. so it would be easier to embed in an if statement.

Regards
Srinivas Devaki
Software Developer at Zomato, New Delhi
Phone: +91 9491 383 249
Telegram: @eightnoteight
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread srinivas devaki
SQL has "CREATE TABLE IF NOT EXISTS"

so you change your instructions to
```python
import sqlite3
conn = sqlite3.connect(':memory:')
c = conn.cursor()
c.execute("""
CREATE TABLE IF NOT EXISTS BloodPressureReadings (
ReadingID INTEGER PRIMARY KEY,
Date TEXT,
Time TEXT,
SystolicBP INTEGER,
DiastolicBP INTEGER,
Comments TEXT);
""")
c.execute("SELECT * FROM BloodPressureReadings")
```


On Sat, Oct 14, 2017 at 11:13 AM boB Stepp  wrote:
>
> I want to use Alan's (and others') idea to run a SQL file to create a
> table if that table does not exist.  Alan suggested using
> executescript() to do this.  I misunderstood Alan and thought that
> this would take a filename and execute it.  Instead, it appears that I
> must pass to it a string which is a SQL script.  So after lots of
> fooling around in the interpreter I arrived at:
>
> py3: import sqlite3
> py3: conn = sqlite3.connect(':memory:')
> py3: c = conn.cursor()
> py3: try:
> ... c.execute('select * from BloodPressureReadings')
> ... except sqlite3.OperationalError:
> ... with open('create_sqlite3_db.sql') as f:
> ... sql = f.read()
> ... c.executescript(sql)
> ...
> 
>
> The file 'create_sqlite3_db.sql' contains:
>
> CREATE TABLE BloodPressureReadings (
> ReadingID INTEGER PRIMARY KEY,
> Date TEXT,
> Time TEXT,
> SystolicBP INTEGER,
> DiastolicBP INTEGER,
> Comments TEXT);
>
> So at this point I am only creating an empty table.
>
> The above "works", but my "try" check is awful!  What can I replace it
> with to just see if there is *any* table in the chosen database?  In
> the code Peter supplied in the thread, "How is database creation
> normally handled?", he used in his function, "ensure_db(filename)":
>
> cursor.execute("create table if not exists addresses (name, email);")
>
> which is sweet, but I don't see how I can apply this idea if I insist
> on using a SQL file to create my table(s).
>
> BTW, in the docs at https://docs.python.org/3/library/sqlite3.html I
> found no mention of the actual exception I caught, "OperationalError".
> Should not this be in the docs?
>
> --
> boB
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread boB Stepp
On Sat, Oct 14, 2017 at 2:11 AM, boB Stepp  wrote:

> So I get "None" as a result if the target table has not been created
> yet.  But if I *do* create the table I want:
>
> py3: with open('create_sqlite3_db.sql') as f:
> ... sql = f.read()
> ...
> py3: c.executescript(sql)
> 
> py3: tb_exists = "select name from sqlite_master where type='table'
> and name='BloodPressureReadings'"
> py3: tb_ck = c.execute(tb_exists).fetchone()
> py3: print(tb_ck)
> ('BloodPressureReadings',)
>
> So it is looking like I can use this technique to determine if I need
> to create the BloodPressureReadings table or not.  Am I on track here
> or is there a better technique?

It just occurred to me after sending the above, does something like
"sqlite_master" exist for other database programs than sqlite3?  Can I
abstract out "sqlite_master" and replace it with a variable so that I
can handle any kind of database?


-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-14 Thread boB Stepp
On Sat, Oct 14, 2017 at 1:43 AM, boB Stepp  wrote:

> I am currently trying to make the following work:
>
> py3: tb_exists = c.execute('select name from sqlite_master where 
> type="table"')
>
> so that I can embed this in an if statement.  But it is not behaving
> quite like I hope yet.  So I am still experimenting and Googling ...

I'm tired and not thinking clearly anymore, but I think I have
something to give me the basis of what I want to do.  First, what
happens if the table does *not* exist:

py3: import sqlite3
py3: conn = sqlite3.connect(':memory:')
py3: c = conn.cursor()
py3: tb_exists = "select name from sqlite_master where type='table'
and name='test'"
py3: tb_ck = c.execute(tb_exists).fetchone()
py3: tb_ck
py3: print(tb_ck)
None

So I get "None" as a result if the target table has not been created
yet.  But if I *do* create the table I want:

py3: with open('create_sqlite3_db.sql') as f:
... sql = f.read()
...
py3: c.executescript(sql)

py3: tb_exists = "select name from sqlite_master where type='table'
and name='BloodPressureReadings'"
py3: tb_ck = c.execute(tb_exists).fetchone()
py3: print(tb_ck)
('BloodPressureReadings',)

So it is looking like I can use this technique to determine if I need
to create the BloodPressureReadings table or not.  Am I on track here
or is there a better technique?

-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-13 Thread boB Stepp
On Sat, Oct 14, 2017 at 1:27 AM, srinivas devaki
 wrote:
> SQL has "CREATE TABLE IF NOT EXISTS"
>
> so you change your instructions to
> ```python
> import sqlite3
> conn = sqlite3.connect(':memory:')
> c = conn.cursor()
> c.execute("""
> CREATE TABLE IF NOT EXISTS BloodPressureReadings (
> ReadingID INTEGER PRIMARY KEY,
> Date TEXT,
> Time TEXT,
> SystolicBP INTEGER,
> DiastolicBP INTEGER,
> Comments TEXT);
> """)
> c.execute("SELECT * FROM BloodPressureReadings")

But I do *not* want to create this table from within my python code;
instead, I want to run the table creation commands from a file if the
table does not already exist.  This way I have more flexibility if I
later change to different database products, for testing purposes,
etc.

I am currently trying to make the following work:

py3: tb_exists = c.execute('select name from sqlite_master where type="table"')

so that I can embed this in an if statement.  But it is not behaving
quite like I hope yet.  So I am still experimenting and Googling ...

boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] How to test for the existence of a table in a sqlite3 db?

2017-10-13 Thread boB Stepp
I want to use Alan's (and others') idea to run a SQL file to create a
table if that table does not exist.  Alan suggested using
executescript() to do this.  I misunderstood Alan and thought that
this would take a filename and execute it.  Instead, it appears that I
must pass to it a string which is a SQL script.  So after lots of
fooling around in the interpreter I arrived at:

py3: import sqlite3
py3: conn = sqlite3.connect(':memory:')
py3: c = conn.cursor()
py3: try:
... c.execute('select * from BloodPressureReadings')
... except sqlite3.OperationalError:
... with open('create_sqlite3_db.sql') as f:
... sql = f.read()
... c.executescript(sql)
...


The file 'create_sqlite3_db.sql' contains:

CREATE TABLE BloodPressureReadings (
ReadingID INTEGER PRIMARY KEY,
Date TEXT,
Time TEXT,
SystolicBP INTEGER,
DiastolicBP INTEGER,
Comments TEXT);

So at this point I am only creating an empty table.

The above "works", but my "try" check is awful!  What can I replace it
with to just see if there is *any* table in the chosen database?  In
the code Peter supplied in the thread, "How is database creation
normally handled?", he used in his function, "ensure_db(filename)":

cursor.execute("create table if not exists addresses (name, email);")

which is sweet, but I don't see how I can apply this idea if I insist
on using a SQL file to create my table(s).

BTW, in the docs at https://docs.python.org/3/library/sqlite3.html I
found no mention of the actual exception I caught, "OperationalError".
Should not this be in the docs?

-- 
boB
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor