CK knows Wayne

PostgreSQL schemas and ruby on rails

Published at by Christian Kruse, updated at 16/04/2012, 01:40pm
Filed under: postgresql, psql, pg, schema, ruby, rails

For a new project I'm working on I wanted to use PostgreSQL schemas for a cleaner database structure. Schemas in PostgreSQL are asically a kind of namespace. You can store data types, tables, function, etc in a schema and names across schemas do not clash.

Just a word before: schemas in Rails are not supported very well. Therefore you cannot use the model generator, you have to write model and migration by yourself. First, create a file db/migrations/0001_create_my_relation.rb. In this file, we write the code to generate the database schema. It needs a class inheriting from ActiveRecord::Migration with the two methods up and down. The class name has to be the camel cased version of the file name, e.g. for 0001_create_my_relation.rb the class name would be CreateMyRelation:

class CreateMyRelation < ActiveRecord::Migration
  def up
  end

  def down
  end
end

The method up creates the database structure, the method down reverts the changes.

As I said, support for schemas is poor. So we have to create it directly using SQL:

class CreateMyRelation < ActiveRecord::Migration
  def up
    execute "CREATE SCHEMA myschema"
  end

  def down
    execute "DROP SCHEMA myschema"
  end
end

For the table generation itself we can use ruby, again:

class CreateMyRelation < ActiveRecord::Migration
  def up
    execute "CREATE SCHEMA myschema"
    create_table 'myschema.my_relations' do |t|
      t.string :test_field
      t.timestamps
    end
  end

  def down
    drop_table 'myschema.my_relations'
    execute "DROP SCHEMA myschema"
  end
end

If we run rails db:migrate, we have a working database migration creating a table myschema.my_relations. Caution: note the quotes around 'myschema.my_relations', using a symbol (:name) does not work in this case since the dot is an operator in Ruby.

Now we have to create the model. This is very easy, just create a file app/models/my_relations.rb containing a class MyRelations inheriting from ActiveRecord::Base:

class MyRelation < ActiveRecord::Base
  set_table_name 'myschema.my_relation'
end

Note the set_table_name line. We have to set the table name manually because Rails is not able to handle schemas automatically.

No comments, yet

GnuPG with PHP

Published at by Christian Kruse, updated at 16/02/2012, 12:03am
Filed under: gnupg, gpg, php

For a spare time project I'm working on I wanted to send GPG encrypted and/or signed emails. Since I use PHP for this project, it seemed natural to use the GnuPG PECL.

After two evenings of work I'd like to try to summarize my experiences: first of all, error handling is very basic. You don't get very meaningful error messages (in fact, you don't get any error messages until you call gnupg_seterrormode($gpg, GNUPG_ERROR_WARNING)…). Error messages like „get_key failed“ are not very obvious.

Also nice to know (and not obvious): you have to set the environment variable GNUPGHOME to the full path to your keyring files. E.g. if your keyring is stored in /var/www/easterhegg.ch/.gnupg/, you have to specify the GNUPGHOME variable as follows: putenv("GNUPGHOME=/var/www/easterhegg.ch/.gnupg/");

All in all, the API is usable but error handling seems very basic.

No comments, yet

Valgrind again: strlen() redirection

Published at by Christian Kruse, updated at 31/01/2012, 08:39pm
Filed under: valgrind, gcc, strlen, redirect

I ran into another problem with Valgrind:

valgrind:  Fatal error at startup: a function redirection 
valgrind:  which is mandatory for this platform-tool combination 
valgrind:  cannot be set up.  Details of the redirection are:    
valgrind:                                                        
valgrind:  A must-be-redirected function                        
valgrind:  whose name matches the pattern:      strlen          
valgrind:  in an object with soname matching:   ld-linux-x86-64.so.2 
valgrind:  was not found whilst processing                          
valgrind:  symbols from the object with soname: ld-linux-x86-64.so.2 
valgrind:                                                            
valgrind:  Possible fixes: (1, short term): install glibc's debuginfo 
valgrind:  package on this machine.  (2, longer term): ask the packagers 
valgrind:  for your Linux distribution to please in future ship a non- 
valgrind:  stripped ld.so (or whatever the dynamic linker .so is called) 
valgrind:  that exports the above-named function using the standard 
valgrind:  calling conventions for this platform. 
valgrind: 
valgrind:  Cannot continue -- exiting now.  Sorry. 

I already was familiar with this problem and I knew using FEATURES="nostrip" and a re-emerge of sys-libs/glibc should help. But after doing that the problem was not gone. After some research I found out that with -O2 the GCC inlines strlen(). It is a code optimization, but in this case it causes valgrind to stop working. The solution is somewhat messy: you have to create a portage overlay of sys-libs/glibc and patch files/eblits/common.eblit: find the line containing append-flags -O2 -fno-strict-aliasing and append -fno-builtin-strlen. Then re-emerge glibc (do not forget to run ebuild glibc-ver.ebuild digest) and everything should work.

No comments, yet

Why not to strip binaries

Published at by Christian Kruse, updated at 31/01/2012, 07:32am
Filed under: linux, strip, binary, stack, trace

Some distros strip binaries. That means, they remove debug symbols and such. They do this to spare disk space. Of course sparing disk space is a perfectly valid goal, but it comes on a cost. It means you can't get any useful debug information. All stack traces look somewhat like this:

0xb7f25410 in ??? ()
#0  0xb7f25410 in ??? ()
#1  0xb741b45b in ?? () from /lib/libpthread.so.0

This says nothing. It's simply useless and makes debugging magic. Therefore, you should not strip binaries on your distro. It just saves you a few megabytes. A few well invested megabytes. On Gentoo you can set FEATURES="nostrip" in /etc/make.conf. Have also a look at the Meningful Backtraces article on gentoo.org.

No comments, yet

Source based distros and valgrind

Published at by Christian Kruse, updated at 30/01/2012, 03:13pm
Filed under: gentoo, exherbo, source based, valgrind, avx

This weekend I changed my Linux notebook back to Gentoo. After getting back to work a weird error occured when working with Valgrind on a self written C++ program: when running a program with valgrind, I get the following message and the program terminates:

vex amd64->IR: unhandled instruction bytes: 0xC5 0xFB 0x10 0x44 0x24 0xF8 0xC3
0x90
==7616== valgrind: Unrecognised instruction at address 0x795bf13.
==7616==    at 0x795BF13: __mpn_construct_double (mpn2dbl.c:41)
==7616==    by 0x795449A: ____strtod_l_internal (strtod_l.c:1566)
==7616==    by 0x5075C5F: CForum::JSON::Parser::getNextToken(char const*, char const*, CForum::JSON::Parser::Token&) (json_parser.cc:225)
==7616==    by 0x50762D5: CForum::JSON::Parser::readValue(boost::shared_ptr*, char const*, char const*) (json_parser.cc:321)
==7616==    by 0x50760AC: CForum::JSON::Parser::readObject(boost::shared_ptr, char const*, char const*) (json_parser.cc:300)
==7616==    by 0x5076386: CForum::JSON::Parser::readValue(boost::shared_ptr*, char const*, char const*) (json_parser.cc:326)
==7616==    by 0x4E491E6: CForum::JSON::Parser::parse(char const*, unsigned long, boost::shared_ptr&) (json_parser.hh:140)
==7616==    by 0x4E490CA: CForum::JSON::Parser::parse(char const*, boost::shared_ptr&) (json_parser.hh:136)
==7616==    by 0x4E45E00: JSONTest::testParser() (json_test.cc:40)

// [… snip …]

After creating a bug report, I found out that this is because valgrind does not yet handle the AVX instruction set, a CPU instruction set to handle vector data more efficient. This instructions are generated by GCC with -march=native set. Since I use this compiler flag on every source based distribution I use, this is a serious problem.

To avoid this problem, you have to specify -march=nocona, as described in the meta bug report for AVX support.

No comments, yet

Exherbo Linux

Published at by Christian Kruse, updated at 30/01/2012, 03:05pm
Filed under: exherbo, linux, paludis

This weekend I tried out Exherbo Linux. It was recommend by a friend of mine, so I gave it a try.

First of all: Exherbo Linux has a great mascot. I really like it, and I like that a distribution is brave enough to use it as a mascot ;-)

Exherbo Linux is a source based rolling release distro. It is in many parts very similar to Gentoo. It uses Paludis as a packet manager, which was created to replace Gentoo's emerge and portage. Therefore I liked their approach. Also you have to do a lot of work by hand to install it on your box. So there are really many things like in Gentoo.

What I didn't like: the lack of documentation and tutorials. Yeah, I know about the freedom of choice and all, but some tutorials and documentation would have been very nice. It took me nearly a whole day to learn about Dracut, the way it handles full disk encryption and keys on external media, and I had to dig to the source to understand it. Also the quality of the packages is sometimes poor, worse than in Gentoo. You have to be willing to repair things by hand if you want to use it.

All in all: a nice approach. I like it. But the lack of documentation is really a serious problem. You have to be willing to invest a lot of time to learn things by yourself if you want to use it.

No comments, yet

MS SQL Server: German date/time values

Published at by Christian Kruse, updated at 16/12/2011, 01:52pm
Filed under: mssql, german, date, time

When working with the MS SQL Server Enterprise Manager and german date/time values, I often geht the error message „Ihr Eintrag kann nicht in keinen gültigen Datum-Zeit-Wert konvertiert werden” (can't convert value to a valid date-time-value), even when using the display format if the database (dd.mm.yyyy), the ANSI date format (yyyy-mm-dd) or the american date format (mm/dd/yyyy).

The Solution is very simple: use the german date format, but without the periods. Instead use the slash: dd/mm/yyyy. Yet another fucked-up thing I don't like with the MS SQL Server.

No comments, yet

MSSQL with PHP: smalldatetime

Published at by Christian Kruse, updated at 10/11/2011, 10:17am
Filed under: mssql, php, smalldatetime, bug, crash

A few days ago I got a SIGSEGV when querying the MSSQL server with PHP. There was nothing special with the query, just a normal SELECT statement, even without WHERE limitations. After examining it a little bit I found out, that it depended on the columns I selected. When I left out some specific columns in the SELECT, everything was ok.

First I thought that it depends on the values of the columns, but I couldn't really figure out a systematic. So only one conclusion is left: it is the column type. PHP crashes when querying a column with the smalldatetime type. After some research I found, that it depends on the configuration parameter mssql.datetimeconvert. If it is turned on, PHP crashes. If it is turned off, everything works fine. So for now, all my PHP scripts working with MSSQL Server begin like this:

if(ini_get('mssql.datetimeconvert')) {
	echo "---------- WARNING! TURN OFF mssql.datetimeconvert! It causes PHP to crash on smalldatetime fields!\n";
	echo "We're turning it off now for this script, but you should do it globally!\n";
	ini_set('mssql.datetimeconvert',"off");
}

Hope that helps.

Hey, two comments!

28C3

Published at by Christian Kruse, updated at 06/11/2011, 10:27pm
Filed under: ccc, 28c3

We've got 28C3 tickets. See ya there! :-)

No comments, yet

Easy machine readable date formats with MS SQL Server

Published at by Christian Kruse, updated at 20/09/2011, 10:41am
Filed under: ms, sql, server, date, datetime, machine, readable

The last few hours I was looking for a method to make the date and datetime data types easier machine readable and more predictable in string representation. There are two things you have to do:

  1. The first thing is to select the correct language environment, just to be sure. I my case this is english: SET LANGUAGE english. This ensures, that the „natueral representation“ is always the same.
  2. The second thing is: you have to type cast the date/datetime field via CONVERT(): CONVERT(char(19),DateTimeField,120) AS DateTimeField for datetime fields and CONVERT(char(10),DateField,103) AS DateField for date-only fields.

Kind of fucked up, but if you have to use MS SQL Server you are used to fucked-up solutions.

Hey, two comments!

You can find older postings in the archive.