@@ -86,7 +86,7 @@ def create_menu(self):
86
86
self .menu_help .add_command (label = 'about' ,
87
87
command = lambda : messagebox .showinfo (message = """
88
88
\n Sqlite_py_manager : a graphic SQLite Client in 1 Python file
89
- \n version 2014-06-09b : 'The magic 8th PEP '
89
+ \n version 2014-06-09c : 'Touch of Zen '
90
90
\n (https://github.com/stonebig/baresql/blob/master/examples)""" ))
91
91
92
92
def create_toolbar (self ):
@@ -134,9 +134,9 @@ def new_db(self, filename=''):
134
134
self .database_file = filename
135
135
if os .path .isfile (filename ):
136
136
if messagebox .askyesno (
137
- message = 'Confirm Destruction of previous Datas ?' ,
138
- icon = 'question' , title = 'Destroying' ):
139
- os .remove (filename )
137
+ message = 'Confirm Destruction of previous Datas ?' ,
138
+ icon = 'question' , title = 'Destroying' ):
139
+ os .remove (filename )
140
140
self .conn = Baresql (self .database_file )
141
141
self .actualize_db ()
142
142
@@ -223,24 +223,25 @@ def actualize_db(self):
223
223
# delete existing tree entries before re-creating them
224
224
for node in self .db_tree .get_children ():
225
225
self .db_tree .delete (node )
226
- # create initial node
226
+ # create top node
227
227
id0 = self .db_tree .insert (
228
228
"" , 0 , "Database" ,
229
229
text = (self .database_file .replace ("\\ " , "/" )).split ("/" )[- 1 ],
230
230
values = (self .database_file , "" ))
231
- # add master_table, Tables, Views, Trigger, Index
232
- for category in ['master_table' , 'table' , 'view' , 'trigger' , 'index' ,
231
+ # add Database Objects, by Category
232
+ for categ in ['master_table' , 'table' , 'view' , 'trigger' , 'index' ,
233
233
'pydef' ]:
234
- self .add_thingsnew (id0 , category )
235
- # redo for attached databases
236
- for att_db in self .add_thingsnew (id0 , 'attached_databases' ):
237
- # create initial node for attached table
234
+ self .feed_dbtree (id0 , categ )
235
+ # for attached databases
236
+ for att_db in self .feed_dbtree (id0 , 'attached_databases' ):
237
+ # create another top node
238
238
id0 = self .db_tree .insert (
239
239
"" , 'end' , att_db + "(Attached)" ,
240
240
text = att_db + " (attached database)" , values = (att_db , "" ))
241
- # add attached db's master_table, Tables, Views, Trigger, and Index
241
+ # add attached Database Objects, by Category
242
242
for categ in ['master_table' , 'table' , 'view' , 'trigger' , 'index' ]:
243
- self .add_thingsnew (id0 , categ , att_db )
243
+ self .feed_dbtree (id0 , categ , att_db )
244
+ # update time of last refresh
244
245
self .db_tree .heading ('#0' , text = (
245
246
datetime .datetime .now ().strftime ('%Y-%m-%d %H:%M:%S' )))
246
247
@@ -403,7 +404,7 @@ def get_tk_icons(self):
403
404
xlzceksqu6ET7JwtLRrhwNt+1HdDUQAAOw==
404
405
'''
405
406
}
406
- return {k : PhotoImage (data = v ) for k , v in icons .items ()}
407
+ return {k : PhotoImage (data = v ) for k , v in icons .items ()}
407
408
408
409
def createToolTip (self , widget , text ):
409
410
"""create a tooptip box for a widget."""
@@ -439,40 +440,44 @@ def close(event):
439
440
widget .bind ("<Enter>" , enter )
440
441
widget .bind ("<Leave>" , close )
441
442
442
- def add_thingsnew (self , root_id , what , attached_db = "" ):
443
- """add a sub-tree to database tree pan"""
444
- tables = get_things (self .conn , what , attached_db )
445
- # level 1 : create the "what" node (as not empty)
443
+ def feed_dbtree (self , root_id , category , attached_db = "" ):
444
+ """feed database treeview for category, return list of leaves names"""
446
445
447
- def id (t ): return ('"%s".' % t .replace ('"' , '""' )) if t != "" else t
448
- attached = id (attached_db )
446
+ # prepare re-formatting functions for fields and database names
447
+ def f (t ): return ('"%s"' % t .replace ('"' , '""' )) if t != "" else t
448
+
449
+ def db (t ): return ('"%s".' % t .replace ('"' , '""' )) if t != "" else t
450
+ attached = db (attached_db )
451
+
452
+ # get Category list of [unique_name, name, definition, sub_category]
453
+ tables = get_leaves (self .conn , category , attached_db )
449
454
if len (tables ) > 0 :
455
+ # level 1 : create the "category" node (as Category is not empty)
450
456
idt = self .db_tree .insert (
451
- root_id , "end" ,
452
- "%s%s" % (attached , what ),
453
- text = "%s (%s)" % (what , len (tables )), values = ("" , "" ))
454
- # level 2 : print object creation, and '(Definition)' if Table/View
455
- for tab in tables :
456
- definition = tab [2 ]
457
+ root_id , "end" , "%s%s (node)" % (attached , category ),
458
+ text = "%s (%s)" % (category , len (tables )), values = ("" , "" ))
459
+ for t_id , t_name , definition , sub_cat in tables :
460
+ # level 2 : print object creation, and '(Definition)' if fields
457
461
sql3 = ""
458
- if tab [ 3 ] != '' :
462
+ if sub_cat != '' :
459
463
# it's a table : prepare a Query with names of each column
460
- colnames = [col [1 ] for col in tab [3 ]]
461
- columns = [col [0 ] for col in tab [3 ]]
464
+ sub_c = get_leaves (self .conn , sub_cat , attached_db , t_name )
465
+ colnames = [col [1 ] for col in sub_c ]
466
+ columns = [col [1 ] + ' ' + col [2 ] for col in sub_c ]
462
467
sql3 = 'select "' + '" , "' .join (colnames )+ '" from ' + (
463
- '%s"%s" ' % (attached , tab [ 1 ] ))
468
+ '%s%s ' % (attached , f ( t_name ) ))
464
469
idc = self .db_tree .insert (
465
- idt , "end" , "%s%s" % (attached , tab [ 0 ] ),
466
- text = tab [ 1 ] , tags = ('run' ,), values = (definition , sql3 ))
470
+ idt , "end" , "%s%s" % (attached , t_id ),
471
+ text = t_name , tags = ('run' ,), values = (definition , sql3 ))
467
472
if sql3 != "" :
468
473
self .db_tree .insert (
469
- idc , "end" , ("%s%s.%s" % (attached , tab [ 1 ] , - 1 )),
474
+ idc , "end" , ("%s%s.%s" % (attached , t_name , - 1 )),
470
475
text = ['(Definition)' ], tags = ('run' ,),
471
476
values = (definition , "" ))
472
477
# level 3 : Insert a line per column of the Table/View
473
- for c in range (len (columns )):
478
+ for c in range (len (sub_c )):
474
479
self .db_tree .insert (
475
- idc , "end" , ( "%s%s.%s " % (attached , tab [ 1 ] , c ) ),
480
+ idc , "end" , "%s%s" % (sub_c [ c ][ 0 ] , c ),
476
481
text = columns [c ], tags = ('run_up' ,), values = ('' , '' ))
477
482
return [i [1 ] for i in tables ]
478
483
@@ -1046,57 +1051,45 @@ def export_csvqr(actions):
1046
1051
export_csv_dialog (query , "Export Query" , actions )
1047
1052
1048
1053
1049
- def get_things (conn , what , attached_db = "" , tbl = "" ):
1050
- """'what' objects : [objectCode, objectName, Definition, [Lvl - 1]]"""
1051
- # dico = what : what qry, result id, result text, result crea, 'what' below
1052
- # or what : other 'what' specification to use in thi dictionnary
1053
- dico = {
1054
- 'index' : 'trigger' ,
1055
- 'trigger' : (
1056
- """SELECT '{0:s}' || name, name, coalesce(sql,'--auto') sql
1057
- FROM {0:s}sqlite_master WHERE type='{1:s}' ORDER BY name""" ,
1058
- '{0:s}' , '{1:s}' , '{2:s}' , '' ),
1059
- 'master_table' : (
1060
- """SELECT '{0:s}sqlite_master', 'sqlite_master', '--auto'
1061
- UNION
1062
- SELECT '{0:s}'||name, name, sql FROM {0:s}sqlite_master
1063
- WHERE type='table' AND name LIKE 'sqlite_%'
1064
- ORDER BY name""" ,
1065
- '{0:s}' , '{1:s}' , '{2:s}' , 'fields' ),
1066
- 'table' : 'view' ,
1067
- 'view' : ("""SELECT '{0:s}' || name, name, sql FROM {0:s}sqlite_master
1068
- WHERE type='{1:s}' AND NOT
1069
- (type='table' AND name LIKE 'sqlite_%') ORDER BY name""" ,
1070
- '{0:s}' , '{1:s}' , '{2:s}' , 'fields' ),
1071
- 'fields' : ("PRAGMA {0:s}TABLE_INFO([{2:s}])" ,
1072
- '{1:s} {2:s}' , '{1:s}' , '' , '' ),
1073
- 'attached_databases' : ("PRAGMA database_list" , '{1:s}' , '{1:s}' ,
1074
- "ATTACH DATABASE '{2:s}' as '{1:s}'" , '' ),
1075
- 'pydef' : ("#N/A" , '{0:s}' , '{0:s}' , '{1:s}' , '' )}
1076
-
1077
- def id (t ): return ('"%s".' % t .replace ('"' , '""' )) if t != "" else t
1078
-
1079
- attached = id (attached_db )
1080
- order = dico [what ]
1081
- if isinstance (order , type ('e' )): # indirection
1082
- order = dico [order ]
1083
- Tables = []
1084
- if what == "pydef" : # pydef request is not sql
1085
- resu = [[k , v ['pydef' ]] for k , v in conn .conn_def .items ()]
1054
+ def get_leaves (conn , category , attached_db = "" , tbl = "" ):
1055
+ """returns a list of 'category' objects in attached_db
1056
+ [objectCode, objectLabel, Definition, 'sub-level']
1057
+ """
1058
+ # create formatting shortcuts
1059
+ def f (t ): return ('"%s"' % t .replace ('"' , '""' )) if t != "" else t
1060
+
1061
+ def d (t ): return ('%s.' % t ) if t != "" else t
1062
+
1063
+ # Initialize datas
1064
+ Tables , db , tb = [], d (attached_db ), f (tbl )
1065
+
1066
+ if category == "pydef" : # pydef request is not sql, answer is direct
1067
+ Tables = [[k , k , v ['pydef' ], '' ] for k , v in conn .conn_def .items ()]
1068
+ elif category == 'attached_databases' :
1069
+ # get all attached database, but not the first one ('main')
1070
+ resu = list ((conn .execute ("PRAGMA database_list" ).fetchall ()))[1 :]
1071
+ for c in resu :
1072
+ instruct = "ATTACH DATABASE %s as %s" % (f (c [2 ]), f (c [1 ]))
1073
+ Tables .append ([c [1 ], c [1 ], instruct , '' ])
1074
+ elif category == 'fields' :
1075
+ resu = conn .execute ("PRAGMA %sTABLE_INFO(%s)" % (db , tb )).fetchall ()
1076
+ Tables = [[db + tb + "." + f (c [1 ]), c [1 ], c [2 ], '' ] for c in resu ]
1077
+ elif category in ('index' , 'trigger' , 'master_table' , 'table' , 'view' ):
1078
+ # others are 1 sql request that generates directly Tables
1079
+ if category in ('index' , 'trigger' ):
1080
+ sql = """SELECT '{0}' || name, name, coalesce(sql,'--auto') , ''
1081
+ FROM {0}sqlite_master WHERE type='{1}' ORDER BY name"""
1082
+ elif category == 'master_table' :
1083
+ sql = """SELECT '{0}sqlite_master', 'sqlite_master', '--auto'
1084
+ , 'fields' UNION SELECT '{0}'||name, name, sql, 'fields'
1085
+ FROM {0}sqlite_master
1086
+ WHERE type='table' AND name LIKE 'sqlite_%' ORDER BY name"""
1087
+ elif category in ('table' , 'view' ):
1088
+ sql = """SELECT '{0}' || name, name, sql , 'fields'
1089
+ FROM {0}sqlite_master WHERE type = '{1}' AND NOT
1090
+ (type='table' AND name LIKE 'sqlite_%') ORDER BY name"""
1091
+ Tables = list (conn .execute (sql .format (db , category , tbl )).fetchall ())
1086
1092
1087
- else :
1088
- # others are sql request
1089
- resu = conn .execute (order [0 ].format (attached , what , tbl )).fetchall ()
1090
- # result must be transformed in a list, and attached db 'main' removed
1091
- resu = list (resu ) if what != 'attached_databases' else list (resu )[1 :]
1092
- # generate tree list for this 'what' category level :
1093
- # [objectCode, objectName, Definition, [Level below] or '']
1094
- for rec in resu :
1095
- result = [order [i ].format (* rec ) for i in range (1 , 5 )]
1096
- if result [3 ] != '' :
1097
- resu2 = get_things (conn , result [3 ], attached_db , result [1 ])
1098
- result [3 ] = resu2
1099
- Tables .append (result )
1100
1093
return Tables
1101
1094
1102
1095
0 commit comments