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
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
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
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
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
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
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
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!
We've got 28C3 tickets. See ya there! :-)
No comments, yet
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:
- 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.
- 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.