This bugged me for a long time, and just today I googled for a solution. And it's darn simple! To set a new default column size, size them while holding the Option (Alt) key. Open a new Finder window, et voila: default size changed!
There are lots of these little tricks in Mac OS (and I'm sure in other desktop GUIs). Fun to find one each day!
Sometimes something hits me, and I'm lucky to survive so I can write it down. The following was written on a tram in Kraków (Poland). It's probably not beautiful, it's just how I felt. We had a splendid night out however.
Very depressing! Careful!
A depressing chore.
Sometime the world did go insane,
Sometime someone pushed it down the drain,
Sometimes blood colors the rain,
and it never looked the same
Now breathing became a chore,
and the air is on sale in-store,
every done year feels like keeping a score
Sometime men got a brain,
Sometime someone outsmarted a flame,
Sometimes making it better is just in vain,
as long as we stay humane
Now that we walk no more,
and all life is getting sore,
there is no point keeping the score
anymore.
For the DIY folks out there!
You're installing MySQL using the Generic Linux Binary tar ball? If you do, you'll need to create a system user and group using useradd and groupadd. However, you would like to use the standard system IDs. No problem, Red Hat defines their standard system users and groups in their manual respectively as 27 and 27.
Here are the commands to create the system user mysql and its group mysql:
shell> groupadd -r -g 27 mysql
shell> useradd -u 27 -g 27 -r -d /var/lib/mysql -s /bin/bash mysql
To me a LONG would be an integer. MySQL, however, defines it as a synonym for MEDIUMTEXT. So careful porting those projects to or from MySQL!
mysql> CREATE TABLE a (id LONG);
mysql> SHOW CREATE TABLE a\G
..
Create Table: CREATE TABLE `a` (
`id` mediumtext
) ENGINE=MyISAM DEFAULT CHARSET=latin1
A bug has been opened for documenting, but it is actually documented here.
This weekend I've been busy porting MySQL Connector/Python to Python 3.1 in a new experimental branch. It is quite a challenge and I was advised to actually rewrite the whole thing for Py3K. However, after crawling through the TypeErrors and other exceptions I figured I did good with porting the code. It helps to re-factor some ancient, weird lines of code and learns me the new goodies coming with Python v3.1.
Status: examples are somehow working, but not all unittests. So we are like 60% away from having MySQL under Python 3.1.
I must say that I love Python 3.1! Especially the Text and Data concept! The major caveat is that we'll have to maintain 2 branches since it's totally incompatible with previous Python versions.
So how we are going to name Python 2K and 3K branches? Shall we pack both Python v2.x and v3.x in the same package and let the setup tools decide what to install? I'm favoring this, so there is no "What shall I download?" confusion.
Universal Python Eggs anyone?
Past weekend we got a customer request asking what the execution numbers shown in the statusbar of MySQL Query Browser really mean. Digging in the source and checking with developers, we got it explained and now hopefully documented for future generations.
Lets execute a SELECT-statement using MySQL Query Browser (in Windows):
SELECT * FROM django_admin_log d;
2664 rows fetched in 0,0659s (0,0016s)
N rows fetched in F sec (Q sec), where
- N = number of rows fetched
- F = number of seconds it took for the GUI tool to fetch andprocess the query result (fetch_time)
- Q = the number of seconds it took the MySQL server to executethe query (query_time)
F will be mostly bigger than Q. However if the query is complex and resultset is for example only 1 row, then Q might be bigger than F.
Replication channel failover is discussed in the MySQL manual and it is quite easy to implement. When the primary replication channel fails, all you need to do is some SQL queries, do a CHANGE MASTER TO, issue a START SLAVE and it should be replicating again.
This fail-over procedure is also very useful if you are upgrading the Master MySQL Cluster mysqld processes doing binary logging. For this you do not need a (controlled) fail-over to the Slave Cluster. You simply point the SQL Node reading events from the Master to another mysqld and switch back when the upgrade is done.
The MySQL manual describes what to do, here is a summary in a few point:
- Stop the Slave SQL Node
- Get the last epoch on this Slave SQL Node
- Using this epoch, get the binary log file and position on the new Master SQL Node
- On the Slave SQL Node, use CHANGE MASTER TO with the file and log position from previous point
- Start the Slave SQL Node, and it should work
Few notes:
- You need to have 2 SQL nodes on the Master MySQL Cluster which are configured to do binary logging. If you haven't, please do ASAP.
- It's good to temporize between steps 2 and 3, like 10 seconds.
- Yes, SQL Node is in this case a mysqld process./li>
The following Python functions are just examples, but hopefully they useful for somebody (full script not provided but it is using MySQL Connector/Python!):
def _get_last_epoch(slave):
c = slave.cursor()
stmt = "SELECT MAX(epoch) AS lastepoch "\
"FROM mysql.ndb_apply_status"
c.execute(stmt)
row = c.fetchone()
c.close()
return row[0]
def _get_binary_log_info(master, lastEpoch):
c = master.cursor()
stmt = "SELECT SUBSTRING_INDEX(File, '/', -1),"\
"Position "\
"FROM mysql.ndb_binlog_index "\
"WHERE epoch > %s "\
"ORDER BY epoch ASC LIMIT 1"
c.execute(stmt, (lastEpoch,))
row = c.fetchone()
c.close()
return row
def _change_master(slave,masterHost=None,
masterPort=None,
logFile=None,logPos=None):
stmtArgs = []
params = []
if masterHost:
stmtArgs.append('MASTER_HOST=%s')
params.append(masterHost)
if masterPort:
stmtArgs.append('MASTER_PORT=%s')
params.append(masterPort)
if logFile:
stmtArgs.append('MASTER_LOG_FILE=%s')
params.append(logFile)
if logPos:
stmtArgs.append('MASTER_LOG_POS=%s')
params.append(logPos)
c = slave.cursor()
stmt = "CHANGE MASTER TO %s" % ', '.join(stmtArgs)
c.execute(stmt, tuple(params))
c.close()
Update 2010-02-26: Updating the text a bit; correcting Python code.
Today I have been updating the MySQL entry on the Python wiki. It wasn't incorrect, but very, very outdated and gave a false impression about MySQL's (or Sun's..) DBMS. It is more inline with the PostgreSQL entry now, and I think also fair. Maybe the Firebird folks might update their wiki page too?
This is a call to other projects out there. If you have a MySQL entry page in your wiki, please be sure to reflect the features that were added during the past years.
In my previous blog post I explained how to enable Python in the MySQL Workbench GRT Shell. This blog explains how to run a simple Python script using Workbench. You don't need to change any preferences to make this work.
Save the following little script to a file called wbscript.py. It will print the tables in the first schema of the first model opened.
import grt
model = grt.root.wb.doc.physicalModels[0]
for tab in model.catalog.schemata[0].tables:
print "Table: `%s`" % (tab.name)
To see the output of the script make sure that:
- you have a model open (with at least 1 table)
- the Output Window is visible: View > Advanced > Output Window
- make the Output option active in the Output Window (defaults to Messages)
In Workbench, chose Tools > Run Workbench Script and locate the script. Open it and it will run immediately (successfully, hopefully!). The output should be something like this (name of table could be something else):
Executing script /Users/geert/Projects/mysql/wbscript.py...
Table: `t1`
Script finished.
Running Workbench scripts is easy, but more awesome would be to make your own plug-in! This is however a different beast that I'll hopefully cover in next posts.
Yesterday, 7 Oct 2009, MySQL Workbench 5.2.4-alpha was released. What interests me in particular is that Workbench 5.2 brings support for writing plugins using Python. Before it was only possible using LUA.
Workbench comes with GRT (Generic RunTime) shell which allows you to access objects at runtime. It's pretty neat, but how you enable it to use Python? Here is how:
- Open the Workbench Preferences dialog
- In the General section, set Interactive GRT Shell Language to Python.
- Restart Workbench
- Go to View > Advanced and choose CRT Shell.
It's a bit of a chore writing in that shell as you can't copy/paste (at least not in MacOS, workaround is to drag!). Here are a few commands you can do there (or check on the Workbench team blog). Make sure you have at least one Model open, and one table defined.
>>> import grt
>>> model = grt.root.wb.doc.physicalModels[0]
>>> for tab in model.catalog.schemata[0].tables:
... print "Table: `%s`" % (tab.name)
...
Table: `t1`
Using the GRT shell it makes it possible to test first some lines of code. I do personally like it, although the shell feels still a bit buggy, but usable.
Today we had a bug report that one of the tests failed. The as-keyword was used in exception handling, which is only supported since Python v2.6.
Currently, MySQL Connector/Python should work with Python v2.4 and greater, but not Python v3.x. The Connector/Python README said we supported v2.3, but that's not the case (anymore) since decorators are used, e.g. @classmethod.
I'll have to pull the trigger, but I think it's safe to say that we're only going to support Python v2.4 and greater. For Python v3 we'll probably have to make an additional branch and release later on. I still have to check what the impact is.
If anyone has compelling reasons why we still should support Python v2.3 or earlier, please let us know. Also, tips on making it backward compatible are welcome.
Currently, the status of compatibility is as follows (output of shell script):Checking Python v2.3.. Failed!
Checking Python v2.4.. Success!
Checking Python v2.5.. Success!
Checking Python v2.6.. Success!
Checking Python v3.0.. Failed!
Checking Python v3.1.. Failed!
This weekend I'm pushing more code which makes MySQL Connector/Python more and ultimately fully compliant with the Python Database API v2.0 specification, aka PEP 249. I wrote my own unittests for this, but later I stumbled upon already made cases form which I'm stealing some ideas.
shell> ./unittests.py -t pep249
Connection object has close()-method ... ok
Connection object has commit()-method ... ok
Connection object has cursor()-method ... ok
Connection object has rollback()-method ... ok
..
----------------------------------------------------------------------
Ran 45 tests in 0.314s
Tests are great!
Bug reports are very much welcome on Launchpad! Especially compatibility problems with MySQLdb.
Maybe a backend using Connector/Python 1.0 might go into Django as an alternative to MySQLdb? Who knows!
I'll save my company ±100 EUR every month, but how I'll get online? Well, for phone I'm using pre-paid in 3 countries without these insane contracts. So no iPhone anymore, or I have to find 600 EUR to buy one not locked-in. In the countries I can be online (in Germany forbidden, see below), I'll use pre-paid 3G connection.
In Germany you get taxed if you use Internet, have a mobile phone, or just a navigation system in the car by an organization called GeZ: legal maffia. So basically, I'm not going to have anything 'online' in Germany anymore.