Gonzalo Fernandez-Victorio, Spaniard, developer and father of twins. From November 2012 living in London. This blog is no longer updated. Visit my new blog at https://gonzalo.f-v.es
Monday, March 29, 2010
More Mantis problems
I have been fighting with PHP, Mantis and SOAP since my last post. Now I think I have discovered a bug when uploading via Mantis SOAP a binary file. It's great being able to debug a PHP application. I hope what I discovered is useful for more people. But I've discovered something quite shocking: I wasn't able to find any good answers to something that must be frequent. I was uploading a binary file sending nulls: 00 00 00 or when base64-encoded: AAAA (in hex 41 41 41 41). And I was getting after downloading "\0" (slash-zero) values (5C 30)
Tuesday, March 9, 2010
Mantis on SQL Server
[Technical post]
I've been busy last couple of days trying to make Mantis work with a Microsoft SQL Server database on a Windows Server 2003. Many people would ask why to use MSSQL instead of Mysql, a much better DBMS, not mention the OS election. I'm not planning to enter in a flame war. I wanted a free bug tracking system that worked with MSSQL. Candidates were Bugzilla, with higly experimental MSSQL support, BugTracker .NET, much settled on the platform but looking a bit amateur, and Mantis, the final election, which promised MSSQL support.
The fact is that it hasn't been a trivial task for me. I'm a Java (former VB.NET) developer, and I've had to fight a lot. Just in case someone else has the same problems, here I write what I've done [edited] to install Mantis 1.2.0:
I've been busy last couple of days trying to make Mantis work with a Microsoft SQL Server database on a Windows Server 2003. Many people would ask why to use MSSQL instead of Mysql, a much better DBMS, not mention the OS election. I'm not planning to enter in a flame war. I wanted a free bug tracking system that worked with MSSQL. Candidates were Bugzilla, with higly experimental MSSQL support, BugTracker .NET, much settled on the platform but looking a bit amateur, and Mantis, the final election, which promised MSSQL support.
The fact is that it hasn't been a trivial task for me. I'm a Java (former VB.NET) developer, and I've had to fight a lot. Just in case someone else has the same problems, here I write what I've done [edited] to install Mantis 1.2.0:
- Install PHP. Some tricks here. First. Use PHP 5.2. PHP 5.3 needs other configuration. Second. I installed in IIS as an ISAPI filter. Third. Install MSSQL extension in the PHP installation. Fourth. You need ntwdblib.dll in ...\system32 folder.
- Unzip Mantis 1.2.0 and install as a new virtual project.
- Link PHP with IIS:No tricks here. I followed this post in Spanish.
- Create de Mantis SQL schema: The installation procedure of Mantis creates the original database (of an ancient version of Mantis) and in the same script upgrades the tables. I don't know the reason why it doesn't work in MSSQL but the fact is it doesn't work. So you have to create the SQL schema on hand. Here is my script:
CREATE TABLE mantis_config_table (
config_id VARCHAR(64) NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
access_reqd INT DEFAULT 0,
type INT DEFAULT 90,
value TEXT NOT NULL,
PRIMARY KEY (config_id, project_id, user_id)
);
CREATE INDEX idx_config ON mantis_config_table (config_id);
CREATE TABLE mantis_bug_file_table (
id INT IDENTITY(1,1) NOT NULL,
bug_id INT DEFAULT 0 NOT NULL,
title VARCHAR(250) DEFAULT '' NOT NULL,
description VARCHAR(250) DEFAULT '' NOT NULL,
diskfile VARCHAR(250) DEFAULT '' NOT NULL,
filename VARCHAR(250) DEFAULT '' NOT NULL,
folder VARCHAR(250) DEFAULT '' NOT NULL,
filesize INT DEFAULT 0 NOT NULL,
file_type VARCHAR(250) DEFAULT '' NOT NULL,
date_added INT DEFAULT 1 NOT NULL,
content IMAGE NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_bug_file_bug_id ON mantis_bug_file_table (bug_id);
ALTER TABLE mantis_bug_file_table ADD
user_id INT DEFAULT 0 NOT NULL;
CREATE TABLE mantis_bug_history_table (
id INT IDENTITY(1,1) NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
bug_id INT DEFAULT 0 NOT NULL,
date_modified INT DEFAULT 1 NOT NULL,
field_name VARCHAR(32) DEFAULT '' NOT NULL,
old_value VARCHAR(128) DEFAULT '' NOT NULL,
new_value VARCHAR(128) DEFAULT '' NOT NULL,
type SMALLINT DEFAULT 0 NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_bug_history_bug_id ON mantis_bug_history_table (bug_id);
CREATE INDEX idx_history_user_id ON mantis_bug_history_table (user_id);
CREATE TABLE mantis_bug_monitor_table (
user_id INT DEFAULT 0 NOT NULL,
bug_id INT DEFAULT 0 NOT NULL,
PRIMARY KEY (user_id, bug_id)
);
CREATE TABLE mantis_bug_relationship_table (
id INT IDENTITY(1,1) NOT NULL,
source_bug_id INT DEFAULT 0 NOT NULL,
destination_bug_id INT DEFAULT 0 NOT NULL,
relationship_type SMALLINT DEFAULT 0 NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_relationship_source ON mantis_bug_relationship_table (source_bug_id);
CREATE INDEX idx_relationship_destination ON mantis_bug_relationship_table (destination_bug_id);
CREATE TABLE mantis_bug_table (
id INT IDENTITY(1,1) NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
reporter_id INT DEFAULT 0 NOT NULL,
handler_id INT DEFAULT 0 NOT NULL,
duplicate_id INT DEFAULT 0 NOT NULL,
priority SMALLINT DEFAULT 30 NOT NULL,
severity SMALLINT DEFAULT 50 NOT NULL,
reproducibility SMALLINT DEFAULT 10 NOT NULL,
status SMALLINT DEFAULT 10 NOT NULL,
resolution SMALLINT DEFAULT 10 NOT NULL,
projection SMALLINT DEFAULT 10 NOT NULL,
eta SMALLINT DEFAULT 10 NOT NULL,
bug_text_id INT DEFAULT 0 NOT NULL,
os VARCHAR(32) DEFAULT '' NOT NULL,
os_build VARCHAR(32) DEFAULT '' NOT NULL,
platform VARCHAR(32) DEFAULT '' NOT NULL,
version VARCHAR(64) DEFAULT '' NOT NULL,
fixed_in_version VARCHAR(64) DEFAULT '' NOT NULL,
build VARCHAR(32) DEFAULT '' NOT NULL,
profile_id INT DEFAULT 0 NOT NULL,
view_state SMALLINT DEFAULT 10 NOT NULL,
summary VARCHAR(128) DEFAULT '' NOT NULL,
sponsorship_total INT DEFAULT 0 NOT NULL,
sticky BIT DEFAULT '0' NOT NULL,
due_date INT DEFAULT 1 NOT NULL,
date_submitted INT DEFAULT 1 NOT NULL,
last_updated INT DEFAULT 1 NOT NULL,
category_id INT DEFAULT 1 NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_bug_sponsorship_total ON mantis_bug_table (sponsorship_total);
CREATE INDEX idx_bug_fixed_in_version ON mantis_bug_table (fixed_in_version);
CREATE INDEX idx_bug_status ON mantis_bug_table (status);
CREATE INDEX idx_project ON mantis_bug_table (project_id);
CREATE TABLE mantis_bug_text_table (
id INT IDENTITY(1,1) NOT NULL,
description TEXT NOT NULL,
steps_to_reproduce TEXT NOT NULL,
additional_information TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE mantis_bugnote_table (
id INT IDENTITY(1,1) NOT NULL,
bug_id INT DEFAULT 0 NOT NULL,
reporter_id INT DEFAULT 0 NOT NULL,
bugnote_text_id INT DEFAULT 0 NOT NULL,
view_state SMALLINT DEFAULT 10 NOT NULL,
date_submitted INT DEFAULT 1 NOT NULL,
last_modified INT DEFAULT 1 NOT NULL,
note_type INT DEFAULT 0,
note_attr VARCHAR(250) DEFAULT '',
PRIMARY KEY (id)
);
CREATE INDEX idx_bug ON mantis_bugnote_table (bug_id);
CREATE INDEX idx_last_mod ON mantis_bugnote_table (last_modified);
CREATE TABLE mantis_bugnote_text_table (
id INT IDENTITY(1,1) NOT NULL,
note TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE mantis_custom_field_project_table (
field_id INT DEFAULT 0 NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
sequence SMALLINT DEFAULT 0 NOT NULL,
PRIMARY KEY (field_id, project_id)
);
CREATE TABLE mantis_custom_field_string_table (
field_id INT DEFAULT 0 NOT NULL,
bug_id INT DEFAULT 0 NOT NULL,
value VARCHAR(255) DEFAULT '' NOT NULL,
PRIMARY KEY (field_id, bug_id)
);
CREATE INDEX idx_custom_field_bug ON mantis_custom_field_string_table (bug_id);
CREATE TABLE mantis_custom_field_table (
id INT IDENTITY(1,1) NOT NULL,
name VARCHAR(64) DEFAULT '' NOT NULL,
type SMALLINT DEFAULT 0 NOT NULL,
possible_values TEXT DEFAULT '' NOT NULL,
default_value VARCHAR(255) DEFAULT '' NOT NULL,
valid_regexp VARCHAR(255) DEFAULT '' NOT NULL,
access_level_r SMALLINT DEFAULT 0 NOT NULL,
access_level_rw SMALLINT DEFAULT 0 NOT NULL,
length_min INT DEFAULT 0 NOT NULL,
length_max INT DEFAULT 0 NOT NULL,
require_report BIT DEFAULT '0' NOT NULL,
require_update BIT DEFAULT '0' NOT NULL,
display_report BIT DEFAULT '0' NOT NULL,
display_update BIT DEFAULT '1' NOT NULL,
require_resolved BIT DEFAULT '0' NOT NULL,
display_resolved BIT DEFAULT '0' NOT NULL,
display_closed BIT DEFAULT '0' NOT NULL,
require_closed BIT DEFAULT '0' NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_custom_field_name ON mantis_custom_field_table (name);
ALTER TABLE mantis_custom_field_table ADD
filter_by BIT DEFAULT '1' NOT NULL;
CREATE TABLE mantis_filters_table (
id INT IDENTITY(1,1) NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
is_public BIT DEFAULT NULL,
name VARCHAR(64) DEFAULT '' NOT NULL,
filter_string TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE mantis_news_table (
id INT IDENTITY(1,1) NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
poster_id INT DEFAULT 0 NOT NULL,
date_posted INT DEFAULT 1 NOT NULL,
last_modified INT DEFAULT 1 NOT NULL,
view_state SMALLINT DEFAULT 10 NOT NULL,
announcement BIT DEFAULT '0' NOT NULL,
headline VARCHAR(64) DEFAULT '' NOT NULL,
body TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE mantis_project_category_table (
project_id INT DEFAULT 0 NOT NULL,
category VARCHAR(64) DEFAULT '' NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
PRIMARY KEY (project_id, category)
);
CREATE TABLE mantis_project_file_table (
id INT IDENTITY(1,1) NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
title VARCHAR(250) DEFAULT '' NOT NULL,
description VARCHAR(250) DEFAULT '' NOT NULL,
diskfile VARCHAR(250) DEFAULT '' NOT NULL,
filename VARCHAR(250) DEFAULT '' NOT NULL,
folder VARCHAR(250) DEFAULT '' NOT NULL,
filesize INT DEFAULT 0 NOT NULL,
file_type VARCHAR(250) DEFAULT '' NOT NULL,
date_added INT DEFAULT 1 NOT NULL,
content IMAGE NOT NULL,
PRIMARY KEY (id)
);
ALTER TABLE mantis_project_file_table ADD
user_id INT DEFAULT 0 NOT NULL;
CREATE TABLE mantis_project_hierarchy_table (
child_id INT NOT NULL,
parent_id INT NOT NULL
);
CREATE TABLE mantis_project_table (
id INT IDENTITY(1,1) NOT NULL,
name VARCHAR(128) DEFAULT '' NOT NULL,
status SMALLINT DEFAULT 10 NOT NULL,
enabled BIT DEFAULT '1' NOT NULL,
view_state SMALLINT DEFAULT 10 NOT NULL,
access_min SMALLINT DEFAULT 10 NOT NULL,
file_path VARCHAR(250) DEFAULT '' NOT NULL,
description TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_project_id ON mantis_project_table (id);
CREATE UNIQUE INDEX idx_project_name ON mantis_project_table (name);
CREATE INDEX idx_project_view ON mantis_project_table (view_state);
CREATE TABLE mantis_project_user_list_table (
project_id INT DEFAULT 0 NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
access_level SMALLINT DEFAULT 10 NOT NULL,
PRIMARY KEY (project_id, user_id)
);
CREATE INDEX idx_project_user ON mantis_project_user_list_table (user_id);
CREATE TABLE mantis_project_version_table (
id INT IDENTITY(1,1) NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
version VARCHAR(64) DEFAULT '' NOT NULL,
date_order INT DEFAULT 1 NOT NULL,
description TEXT NOT NULL,
released BIT DEFAULT '1' NOT NULL,
PRIMARY KEY (id)
);
CREATE UNIQUE INDEX idx_project_version ON mantis_project_version_table (project_id, version);
CREATE TABLE mantis_sponsorship_table (
id INT IDENTITY(1,1) NOT NULL,
bug_id INT DEFAULT 0 NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
amount INT DEFAULT 0 NOT NULL,
logo VARCHAR(128) DEFAULT '' NOT NULL,
url VARCHAR(128) DEFAULT '' NOT NULL,
paid BIT DEFAULT '0' NOT NULL,
date_submitted INT DEFAULT 1 NOT NULL,
last_updated INT DEFAULT 1 NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_sponsorship_bug_id ON mantis_sponsorship_table (bug_id);
CREATE INDEX idx_sponsorship_user_id ON mantis_sponsorship_table (user_id);
CREATE TABLE mantis_tokens_table (
id INT IDENTITY(1,1) NOT NULL,
owner INT NOT NULL,
type INT NOT NULL,
timestamp INT DEFAULT 1 NOT NULL,
expiry INT DEFAULT 1 NOT NULL,
value TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE mantis_user_pref_table (
id INT IDENTITY(1,1) NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
default_profile INT DEFAULT 0 NOT NULL,
default_project INT DEFAULT 0 NOT NULL,
refresh_delay INT DEFAULT 0 NOT NULL,
redirect_delay INT DEFAULT 0 NOT NULL,
bugnote_order VARCHAR(4) DEFAULT 'ASC' NOT NULL,
email_on_new BIT DEFAULT '0' NOT NULL,
email_on_assigned BIT DEFAULT '0' NOT NULL,
email_on_feedback BIT DEFAULT '0' NOT NULL,
email_on_resolved BIT DEFAULT '0' NOT NULL,
email_on_closed BIT DEFAULT '0' NOT NULL,
email_on_reopened BIT DEFAULT '0' NOT NULL,
email_on_bugnote BIT DEFAULT '0' NOT NULL,
email_on_status BIT DEFAULT '0' NOT NULL,
email_on_priority BIT DEFAULT '0' NOT NULL,
email_on_priority_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_on_status_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_on_bugnote_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_on_reopened_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_on_closed_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_on_resolved_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_on_feedback_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_on_assigned_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_on_new_min_severity SMALLINT DEFAULT 10 NOT NULL,
email_bugnote_limit SMALLINT DEFAULT 0 NOT NULL,
language VARCHAR(32) DEFAULT 'english' NOT NULL,
PRIMARY KEY (id)
);
ALTER TABLE mantis_user_pref_table ADD
timezone VARCHAR(32) DEFAULT '' NOT NULL;
CREATE TABLE mantis_user_print_pref_table (
user_id INT DEFAULT 0 NOT NULL,
print_pref VARCHAR(27) DEFAULT '' NOT NULL,
PRIMARY KEY (user_id)
);
CREATE TABLE mantis_user_profile_table (
id INT IDENTITY(1,1) NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
platform VARCHAR(32) DEFAULT '' NOT NULL,
os VARCHAR(32) DEFAULT '' NOT NULL,
os_build VARCHAR(32) DEFAULT '' NOT NULL,
description TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE mantis_user_table (
id INT IDENTITY(1,1) NOT NULL,
username VARCHAR(32) DEFAULT '' NOT NULL,
realname VARCHAR(64) DEFAULT '' NOT NULL,
email VARCHAR(64) DEFAULT '' NOT NULL,
password VARCHAR(32) DEFAULT '' NOT NULL,
date_created INT DEFAULT 1 NOT NULL,
last_visit INT DEFAULT 1 NOT NULL,
enabled BIT DEFAULT '1' NOT NULL,
protected BIT DEFAULT '0' NOT NULL,
access_level SMALLINT DEFAULT 10 NOT NULL,
login_count INT DEFAULT 0 NOT NULL,
lost_password_request_count SMALLINT DEFAULT 0 NOT NULL,
failed_login_count SMALLINT DEFAULT 0 NOT NULL,
cookie_string VARCHAR(64) DEFAULT '' NOT NULL,
PRIMARY KEY (id)
);
CREATE UNIQUE INDEX idx_user_cookie_string ON mantis_user_table (cookie_string);
CREATE UNIQUE INDEX idx_user_username ON mantis_user_table (username);
CREATE INDEX idx_enable ON mantis_user_table (enabled);
CREATE INDEX idx_access ON mantis_user_table (access_level);
INSERT INTO mantis_user_table(username, realname, email, password, date_created, last_visit, enabled, protected, access_level, login_count, lost_password_request_count, failed_login_count, cookie_string) VALUES
('administrator', '', 'root@localhost', '63a9f0ea7bb98050796b649e85481845', 1, 1, '1', '0', 90, 3, 0, 0, '43c90a58b766eca71a4eaec08120f1b51fec152d8f4d2c0cfec26390ed94f575');
ALTER TABLE mantis_bug_history_table ALTER COLUMN old_value VARCHAR(255) NOT NULL;
ALTER TABLE mantis_bug_history_table ALTER COLUMN new_value VARCHAR(255) NOT NULL;
CREATE TABLE mantis_email_table (
email_id INT IDENTITY(1,1) NOT NULL,
email VARCHAR(64) DEFAULT '' NOT NULL,
subject VARCHAR(250) DEFAULT '' NOT NULL,
submitted INT DEFAULT 1 NOT NULL,
metadata TEXT NOT NULL,
body TEXT NOT NULL,
PRIMARY KEY (email_id)
);
CREATE INDEX idx_email_id ON mantis_email_table (email_id);
ALTER TABLE mantis_bug_table ADD
target_version VARCHAR(64) DEFAULT '' NOT NULL;
ALTER TABLE mantis_bugnote_table ADD
time_tracking INT DEFAULT 0 NOT NULL;
CREATE INDEX idx_diskfile ON mantis_bug_file_table (diskfile);
ALTER TABLE mantis_user_print_pref_table ALTER COLUMN print_pref VARCHAR(64) NOT NULL;
ALTER TABLE mantis_bug_history_table ALTER COLUMN field_name VARCHAR(64) NOT NULL;
CREATE TABLE mantis_tag_table (
id INT IDENTITY(1,1) NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
name VARCHAR(100) DEFAULT '' NOT NULL,
description TEXT NOT NULL,
date_created INT DEFAULT 1 NOT NULL,
date_updated INT DEFAULT 1 NOT NULL,
PRIMARY KEY (id, name)
);
CREATE TABLE mantis_bug_tag_table (
bug_id INT DEFAULT 0 NOT NULL,
tag_id INT DEFAULT 0 NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
date_attached INT DEFAULT 1 NOT NULL,
PRIMARY KEY (bug_id, tag_id)
);
CREATE INDEX idx_typeowner ON mantis_tokens_table (type, owner);
CREATE TABLE mantis_plugin_table (
basename VARCHAR(40) NOT NULL,
enabled BIT DEFAULT '0' NOT NULL,
PRIMARY KEY (basename)
);
CREATE TABLE mantis_category_table (
id INT IDENTITY(1,1) NOT NULL,
project_id INT DEFAULT 0 NOT NULL,
user_id INT DEFAULT 0 NOT NULL,
name VARCHAR(128) DEFAULT '' NOT NULL,
status INT DEFAULT 0 NOT NULL,
PRIMARY KEY (id)
);
CREATE UNIQUE INDEX idx_category_project_name ON mantis_category_table (project_id, name);
INSERT INTO mantis_category_table
( project_id, user_id, name, status ) VALUES
( '0', '0', 'General', '0' ) ;
DROP TABLE mantis_project_category_table;
ALTER TABLE mantis_project_table ADD
category_id INT DEFAULT 1 NOT NULL;
INSERT INTO mantis_plugin_table
( basename, enabled ) VALUES
( 'MantisCoreFormatting', '1' );
ALTER TABLE mantis_project_table ADD
inherit_global INT DEFAULT 0 NOT NULL;
ALTER TABLE mantis_project_hierarchy_table ADD
inherit_parent INT DEFAULT 0 NOT NULL;
ALTER TABLE mantis_plugin_table ADD
protected BIT DEFAULT '0' NOT NULL,
priority INT DEFAULT 3 NOT NULL;
ALTER TABLE mantis_project_version_table ADD
obsolete BIT DEFAULT '0' NOT NULL;
CREATE TABLE mantis_bug_revision_table (
id INT IDENTITY(1,1) NOT NULL,
bug_id INT NOT NULL,
bugnote_id INT DEFAULT 0 NOT NULL,
user_id INT NOT NULL,
timestamp INT DEFAULT 1 NOT NULL,
type INT NOT NULL,
value TEXT NOT NULL,
PRIMARY KEY (id)
);
CREATE INDEX idx_bug_rev_id_time ON mantis_bug_revision_table (bug_id, timestamp);
CREATE INDEX idx_bug_rev_type ON mantis_bug_revision_table (type);
CREATE INDEX idx_project_hierarchy_child_id ON mantis_project_hierarchy_table (child_id);
CREATE INDEX idx_project_hierarchy_parent_id ON mantis_project_hierarchy_table (parent_id);
CREATE INDEX idx_tag_name ON mantis_tag_table (name);
CREATE INDEX idx_bug_tag_tag_id ON mantis_bug_tag_table (tag_id);
INSERT INTO mantis_config_table ( value, type, access_reqd, config_id, project_id, user_id ) VALUES ('182', 1, 90, 'database_version', 0, 0 ); - Create a config_inc.php file: No tricks here. You have to enter database connection data. Mine is more complicated but I guess something like this could do the trick:
<?php
$g_hostname = '***';
$g_db_type = 'mssql';
$g_database_name = '***';
$g_db_username = '***';
$g_db_password = '***';
?> - The final trick: Don't ask me why (and don't ask me how I discovered), but the fact is that you have to edit the file ...\library\adodb\adodb.inc.php, and change the sentence
define('ADODB_FETCH_ASSOC',2);
todefine('ADODB_FETCH_ASSOC',0);
Thursday, September 3, 2009
God help us
It turns out that I was wrong when I wrote last week's post. Well, maybe I came to a rather good end result but for the wrong reasons:
The first reason would decrease the predicted deficit. The second reason would increase the predicted deficit. It turns out that last predictions (from "Banco de España" which is Spanish Central Bank) deficit will be in the range 11-12%. I predicted 11.3%.
Right result for bad reasons
I'll try to redo my calculations and repost my results. I'm starting to be scared about Spanish situation after this report,this rebuttal, and this rebuttal to the rebuttal.
- Income data from May 2009 (and probably June) was tricky because taxes returns were accelerated so that people could vote with their money back in the pocket.
- Data for income and expenses was only for the national services. But in Spain we have nearly federal organization, so local and regional services must be taken into account. That means actual incomes and expenses are higher than predicted.
The first reason would decrease the predicted deficit. The second reason would increase the predicted deficit. It turns out that last predictions (from "Banco de España" which is Spanish Central Bank) deficit will be in the range 11-12%. I predicted 11.3%.
Right result for bad reasons
I'll try to redo my calculations and repost my results. I'm starting to be scared about Spanish situation after this report,this rebuttal, and this rebuttal to the rebuttal.
Thursday, August 27, 2009
Lies, damn lies and statistics
Disclaimer. I'm not an economist or a statician, and I don't have any governmental internal information. I'm only a spaniard.
I've just read a piece of news about Moody's considering Spanish outlook stable. Although I don't foresee a default's risk, I completely disagree. I think Spanish conditions are deteriorating very fast. I recommend reading this article on Moody's decision.
Anyway, I remembered reading that in recent months Government's income and expenses figures have been alarming. Usually, when I get contradicting information I tend to go to the original source. In this case I went to this official paper containing income and expenses. The report is in Spanish, and considers two methods for calculating data. One would be in terms of cash flow, and the other in terms of obligations. It shows data up to June 2009. I went to pages 22 and 23, and compared this year cash flow data with data from 2006 to 2008, so that I could figure out total non financial income and non financial expenses for this year.
Expenses seems to be rather predictable. For the past year month by month one can see similar expenses in terms of the total expenses amount for the whole year. This year seems odd, but I don't thing I'll miss if I write that total expenses for the whole year would be in the range of 180 billion euros (180,000 million euros).
However, when looking at incomes, one can see the problem. And the problem is that incomes figures have crashed. To the point that from April to June, income was 470 million euros, which is roughly 1/20th the amount in recent years for that period. I don't see it recovering in coming months, so I wouldn't expect more than 60 billion euros.
Subtracting expenses from incomes, I get a total deficit for the year of 120 billion euros. Which means that expenses are three times the incomes.
Hey. I wish I could spent 3 times what I earn.
Anyway, what's more shocking for me is that usually we don't get deficit as a part of expenses, but as a part of GDP. If I divide 120 billion by 1060 billion (total Spanish GDP), I get 11,3%. The usual prediction you can get it's in the range of 10%, so probably my figures are wrong (see disclaimer above).
But then I thought "What deficit would Spain have if incomes were 0?". 180 billion divided by 1060 billion. I get 17%.
Deficit as percentage of GDP has no value for me as a citizen. Because I cannot evaluate how good or bad is the figure.
I've just read a piece of news about Moody's considering Spanish outlook stable. Although I don't foresee a default's risk, I completely disagree. I think Spanish conditions are deteriorating very fast. I recommend reading this article on Moody's decision.
Anyway, I remembered reading that in recent months Government's income and expenses figures have been alarming. Usually, when I get contradicting information I tend to go to the original source. In this case I went to this official paper containing income and expenses. The report is in Spanish, and considers two methods for calculating data. One would be in terms of cash flow, and the other in terms of obligations. It shows data up to June 2009. I went to pages 22 and 23, and compared this year cash flow data with data from 2006 to 2008, so that I could figure out total non financial income and non financial expenses for this year.
Expenses seems to be rather predictable. For the past year month by month one can see similar expenses in terms of the total expenses amount for the whole year. This year seems odd, but I don't thing I'll miss if I write that total expenses for the whole year would be in the range of 180 billion euros (180,000 million euros).
However, when looking at incomes, one can see the problem. And the problem is that incomes figures have crashed. To the point that from April to June, income was 470 million euros, which is roughly 1/20th the amount in recent years for that period. I don't see it recovering in coming months, so I wouldn't expect more than 60 billion euros.
Subtracting expenses from incomes, I get a total deficit for the year of 120 billion euros. Which means that expenses are three times the incomes.
Hey. I wish I could spent 3 times what I earn.
Anyway, what's more shocking for me is that usually we don't get deficit as a part of expenses, but as a part of GDP. If I divide 120 billion by 1060 billion (total Spanish GDP), I get 11,3%. The usual prediction you can get it's in the range of 10%, so probably my figures are wrong (see disclaimer above).
But then I thought "What deficit would Spain have if incomes were 0?". 180 billion divided by 1060 billion. I get 17%.
Deficit as percentage of GDP has no value for me as a citizen. Because I cannot evaluate how good or bad is the figure.
Thursday, August 20, 2009
New Year's resolutions ... in August
I've been on holidays, and I've had some spare time to stop and think.
Last couple of months have been special. Some events have affected profoundly.
One of those events has been the death of a collegue. Antonio was a young man. At least young for me, since he was in his early 40's, only a few years older than me. Antonio was a nice guy. I remember him laughing a lot of times. Antonio was smart, talented, and on a technical level he always had a different perspective too. As it turns out, it wasn't enough for him.
The second event was reading this inspiring post about how easy is to let your life flow. While reading that article I felt like as I was looking at my life. I work better under presure. I want to point a couple of examples. One, while studying International Baccalaureate. I worked a lot, learnt a lot and enjoy a lot. I felt alive. The other was while preparing the competitive examination to become a Civil Servant. My two daughters were one year old. My wife took care of them while I managed to study (a lot) after work, concentrating in the preparation while in the same house there were two little girls playing (and screaming ;D). But when there's nothing challenging, life flows.
I have a wonderful family that gives me a reason to live. I love my wife. I love my daughters. I don't feel depressed.
But I feel that, most of the time, life flows and I'm carried rather walking. And I want to be walking. And I need new challenges.
The start of a new scholar year is a good time to plan them. They won't be huge challenges. But by writing them here I hope I can achieve them.
So here are they:
I'll try to post my progress on these challenges in Twitter. Although the blog posting is easier to check here.
Last couple of months have been special. Some events have affected profoundly.
One of those events has been the death of a collegue. Antonio was a young man. At least young for me, since he was in his early 40's, only a few years older than me. Antonio was a nice guy. I remember him laughing a lot of times. Antonio was smart, talented, and on a technical level he always had a different perspective too. As it turns out, it wasn't enough for him.
The second event was reading this inspiring post about how easy is to let your life flow. While reading that article I felt like as I was looking at my life. I work better under presure. I want to point a couple of examples. One, while studying International Baccalaureate. I worked a lot, learnt a lot and enjoy a lot. I felt alive. The other was while preparing the competitive examination to become a Civil Servant. My two daughters were one year old. My wife took care of them while I managed to study (a lot) after work, concentrating in the preparation while in the same house there were two little girls playing (and screaming ;D). But when there's nothing challenging, life flows.
I have a wonderful family that gives me a reason to live. I love my wife. I love my daughters. I don't feel depressed.
But I feel that, most of the time, life flows and I'm carried rather walking. And I want to be walking. And I need new challenges.
The start of a new scholar year is a good time to plan them. They won't be huge challenges. But by writing them here I hope I can achieve them.
So here are they:
- Books. I used to read a lot of books. I love reading. But I haven't been doing recently. Today I've received a list of essential novels and I've discovered I haven't read a lot of them. So I'm planning to read at least 20 books of that list I haven't read yet until August 2010. That doesn't look too much. But I want to set some number.
- Blog. I like blogging, but I don't think I have too many interesting things to say. However, I want to practice my English. And I think this is an excellent way to do it. That's why I'm going to try to post once a week until August 2010.
- Software developing. I like software developing, but in my current position I do a more managerial work. So I'm going to develop at home. The problem with this resolution is that it's not easy to quantify. Should I read new techniques?. I already do. Should I write X lines of code?. Oh c'mon. I'm not such a moron. So this resolution is to use three hours a week to develop something, probably some kind of web application to scratch a personal itch.
I'll try to post my progress on these challenges in Twitter. Although the blog posting is easier to check here.
Thursday, August 13, 2009
Netbook Operating Systems
A few months ago I got a new Acer Aspire One A110. It's an Atom N270 with 512 MB RAM and 8GB SSD hard disk and 8.9'' screen. It came with a personalized version of a Linux distribution called Linpus Lite based in Fedora 8. Since the first day I've been testing several Netbook OS and I wanted to share my thoughts about it.
The bottom line is that I like Moblin for the speed, Ubuntu Netbook Remix for the software and look and feel, Jolicloud looks promising... but I'll keep using Linpus, while waiting to Google Chrome OS.
What I want? An operating system that ...
Nothing too strange for a Netbook, I bet.
- The original distribution, (as I've said) is a personalized version of Linpus Lite. It boots very fast, and works smoothly. However, it's locked, and configuration and installation of new software (or updating of existing) is daunting. Fortunately Acer put a repository with new packages, although it's still not enough.
- The first OS I tested was Ubuntu Netbook Remix. It's a distribution based in Ubuntu 9.04. It has some interesting things, like a menu/desktop interface more usable in small screen netbooks than traditional Ubuntu or Linpus. It also had access to the full Ubuntu repository. However, it took twice or three times more time to boot than Linpus. And it seemed sluggish.
- Following I tested Moblin. It boots very fast, and works pretty well. The first version I tested was a bit unpolished, but it's being updated pretty fast. However has two things that I personally don't like. The first one is that Moblin seems to encourage a particular way of working. For example it has a specific place for a specific twitter client. And the same for the browser. "What if I want another browser or if I don't use Twitter?". The second thing is that sometimes is difficult to close and application because top menu gets unfolded. To sum up it's very fast, but not designed for me.
- I also tried to test Live Android OS. It worked pretty well on a VirtualBox under Windows 7. However I couldn't make it boot on my Acer, and it seems a known bug. Of course it's an early port to i386 architecture.
- Next I tested Jolicloud. It's a new Operating System, and tested only under invitation. It seems based in Ubuntu Netbook Remix, and has two very interesting concepts. The first one is that in the installation process you have to select the model of the netbook. That seems to make a personalized version of the operating system perfectly adjusted to the model. The second interesting thing is a great catalog of applications some of them web applications, some of them client-only. The good thing is that for the user is indifferent. Besides those concepts, being based in Ubuntu Netbook Remix have the same problems than the original. Slow boot and slow operation. Also, the installed web applications seem based in Prism, and I don't feel comfortable clicking links there because it has to start a new browser.
- Last I tested Xubuntu. Xubuntu works better than Ubuntu Netbook Remix, but boots slow. Also I installed the governor dock applet. If selected powersave, sometimes it went jerky. If selected ondemand battery disappeared. For the record Chrome with plugins is still unstable in Linux.
- I also installed Windows XP in my brother-in-law's netbook, the same brand and model. It could run WXP, but again it seemed slow.
The bottom line is that I like Moblin for the speed, Ubuntu Netbook Remix for the software and look and feel, Jolicloud looks promising... but I'll keep using Linpus, while waiting to Google Chrome OS.
What I want? An operating system that ...
- ... can boot and launch a browser very quick.
- ...tries to save battery. Bonus point if I can remove an USB stick while suspended without crashing.
- ... runs fast
- ... apart from a browser, has already installed (or one-click away) Flash Plugin PDF viewer, and a media player. Bonus point for an Office suite.
Nothing too strange for a Netbook, I bet.
Tuesday, May 26, 2009
What can I do for my country
And so, my fellow Americans: ask not what your country can do for you—ask what you can do for your country.
J.F. Kennedy
A couple of weeks ago Jose Manuel Campa was nominated new Secretary of Economy in Spain. The position was being held by David Vegara, but he had expressed his intention to leave the job when his former boss Pedro Solbes was removed from the Ministry position.
That seems something uninteresting even for Spaniards. Not the kind of post I should write in this blog. And certainly with no apparent connection with the quote at the beginning.
But the fact is that I find this piece of news rather inspiring.
Jose Manuel Campa is a Bussiness School teacher, respected academic, and a successful professional. He seems wealthy enough, and Spanish Secretaries don't make more than say $110000/year (which for the record is much more than I earn, but seems pretty low if compared even with people managing a medium-sized company, not to say a whole European country)
And the more puzzling part of this story is that current Spanish administration seems to have an economic leftist view, whereas Jose Manuel Campa seems to have more rightist views. The Government is more "liberal" (in the American meaning), and he seems more "conservative". His views seem quite the opposite of current government views. He even signed a petition advocating for a change in labor market, something that is very controversial in Spanish politics.
And the job is going to be an "ugly" one. The whole world is under economic turmoil, but Spain seems to have an even more difficult position, because of a number of reasons. First, for 15 years we've been building houses, and now don't know how to do anything else. Second, we don't have control over interest rate (we depend on ECB who set rates on whole Europe). And although our banks didn't buy American subprime mortgages, they DO have loans to housing developers, with land of little to no value as collateral, and now those loans are starting to default. Also, we have 4 million people unemployed, and 100k more each month, for a total population of 44 million. And last but not least, current government did take a bunch of measures, but without a long term goal, hoping that in two years World will be better and Spain will recover. In conclusion, in the coming months, Secretary of Economy is going to be a hard position, giving bad news, and proposing tough measures.
So Mr. Campa won't earn more money (in fact, probably less). He already had a respected position. He'll have to fight every measure, every law, and every budget. And he'll be the bad guy in a government ready to give money everyone until money disappear.
Many people in the Spanish financial sector think that he won't last in the position.
Then, why did he accept the job?.
Maybe he wants to be well known. Maybe he's going to lose money a couple of years, then make much more.
Or...
... maybe he has asked himself what can he do for his country.
Subscribe to:
Posts (Atom)