Saturday, September 12, 2015

MySQL under the hood hurts

Recently I've been poking around MySQL, i've forgot how it's when someone makes a lot of decisions for you, e.g. that a column of type TIMESTAMP should have a default value set to CURRENT_TIMESTAMP or that on each row write it should be automatically updated to CURRENT_TIMESTAMP, and btw did you know, that NOW() and CURRENT_TIMESTAMP are not equal (check this)?

The simplest way to discover what MySQL have done for you is to either read the documentation (which is kind of long) or:

SHOW CREATE TABLE table;
This will print you the full command necessary to recreate the table in the same state as it's currently:
CREATE TABLE `table` (
  `user_id` int(11) DEFAULT NULL,
  `user_name` varchar(255) DEFAULT NULL,
  `tags` text,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `state` int(11) DEFAULT '0',
  `date_of_publication` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `auth_fb_share` tinyint(1) DEFAULT NULL,
  CONSTRAINT `table_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`),
) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8

But why is it a problem?
Because by default CURRENT_TIMESTAMP inserts the value with timezone shift, but without the information about time zone. Let's say it's 2015-09-09 21:23 +02:00. The TIMESTAMP keeps the data as UTC (+00:00). The proper value should be: 2015-09-09 19:23.
But the CURRENT_TIMESTAMP will insert the data as: 2015-09-09 21:23 skipping time zone information.
This causes a shift of X hours depending what's a server timezone is.

Thursday, July 30, 2015

Go: a list of structure field names

package main

import (
 "fmt"
 "reflect"
)

type User struct {
 Name     string
 Age      int
 Password string
}

func GetFieldNames(s interface{}) []string {
 t := reflect.TypeOf(s)
 if t.Kind() == reflect.Ptr {
  t = t.Elem()
 }
 if kind := t.Kind(); kind != reflect.Struct {
  fmt.Printf("not a struct kind: %s", kind)
  return nil
 }
 var ret []string
 for i := 0; i < t.NumField(); i++ {
  field := t.Field(i)
  ret = append(ret, field.Name)
 }
 return ret
}

func main() {
 u := User{}
 fmt.Println(GetFieldNames(u))
 fmt.Println(GetFieldNames(&u))
}
At Go Playground: http://play.golang.org/p/6LDoCIKFeH
The function returns a slice of strings. Each is a name of a field. If a pointer is an argument the underlying type's field names are returned. The function ended up in: github.com/orian/utils/reflect. A documentation is browsable at: https://gowalker.org/github.com/orian/utils/reflect.
A short explanation:
  • First get a reflect.Type of a given argument s
  • If s' kind is a pointer, get a descriptor of underlying type.
  • If underlying type is not a struct, return error..
  • Iterate over fields, add field names and return the result slice.

Wednesday, July 1, 2015

TIL: clicked element reference in JavaScript console

I had a break from WebDev for around 2 years. I'm rediscovering things now. Today I've learnt: $0
  • Right click on the element of interest in your browser and select 'inspect element'. You should see the browser debugger with the element you clicked on highlighted.
  • The debugger allows you to access the currently selected element in the console as $0 variable.

Thursday, June 11, 2015

TIL: never depend on the order of evaluation of sub-expressions in a stream

The code below may result in a 6 different execution orders. It will surprise and hurt you, so don't do that ;-)
std::cout << wizard.CastSpell("abracadabra") << wizard.DrinkPotion("Rosanke") << wizard.Mana();
More info can be found:

Monday, June 1, 2015

Endless extracting of tar.bz2 archive

Funny story. Over a year ago I've backed up a project directory to tar.bz2 archive. Today I've decided to check what's inside. I've encountered a frozen window of 'extract here' option from file context menu.

I've killed the extract process and rerun it from a terminal:
tar -xvvf archive.tar.bz2
After few normal lines i've seen smth (in fact thousands of such lines):
hrwxr-x--- user/group       0 2013-02-06 23:20 workspace/a/b/a/b/f.go link to workspace/a/b/f.go
hrwxr-x--- user/group       0 2013-02-06 23:20 workspace/a/b/a/b/a/b/f.go link to workspace/a/b/a/b/f.go
This clued me, that probably the archive kept the symbolic links. After Googling and reading tar manual I had this idea: let's remove a symlink from an archive:
tar --delete -f archive.tar workspace/a/b/a
This worked just well :-)