Saturday, April 11, 2009

CakePHP 1.2 on Leopard 10.5.6

<VirtualHost www.cakeblog.dev>
DocumentRoot "/Users/USERNAME/Sites/cakeblog"
ServerName cakeblog.dev
ServerAlias www.cakeblog.dev
<Directory "/Users/USERNAME/Sites/cakeblog/">
Options FollowSymLinks
AllowOverride All
</Directory>
</VirtualHost>


The line you add to /etc/hosts should be:

127.0.0.1   www.cakeblog.dev 



The tutorial is pretty accurate about how to set up PHP and MySQL.

Thursday, January 29, 2009

consultant attitudes all programmers should have

I have been doing programming as a consultant a little over a year and half. While working last year, I realized that there are a couple attitudes that most consultants have that I think all programmers would do well to adopt, or at least think about.

* First off, make sure your code is written in such a way to be easily readable and well-commented. The programmer reading the code and trying to figure it out 6 months later may be you! This will also made the code easier to maintain and debug.

* Document as you go. This relates to the previous point. There's never time to document a project after it is done, but if you do a few minutes a day as you are developing, it won't be so bad.

* Keep an ongoing list of features you want to add and bugs you want to fix.

* Realize you won't be working on any specific program forever. You should have a plan for handing the work you've done off to someone else. People get promoted, transferred to other projects, get better jobs, get laid off, and sometimes get hit by a bus (see last item).

* Always make sure you are learning new things and coming up with ideas on how to do things better.

* Know who your customer is & be sure your work is serving them. As a consultant, your customer is your client. As an employee, your customer is your employer, your boss, or whoever is going to be the end user of the program you are creating.

* Last of all: everyone says you should document things & share information so if you get hit by a bus, people will know what they need to know to continue the project. This point is brought up often enough, programmers should generally just avoid buses, just to be safe. Take the subway or train instead. No one talks about programmers being hit by them.

Friday, November 21, 2008

Perl references to return values

Today I was working on some Perl code that needs to take an array returned from one function, make a reference to that array, and pass the reference to another function. It seemed like a simple enough thing to do. I've been doing Perl programming for seven years. After trying a few things and hitting failure, I pulled out the O'Reilly book Programming Perl and read the chapters on references and on subroutines. You can make references to anything: scalars, arrays, file handles, subroutines. But it seemed you can't just take a sub-routine's return value and make a reference to it.

A little poking around on Google turned up an indication that I'm not missing something. There may not be a way to do exactly what I'm trying to do according to a post on Perlmonks.org. So instead of making a reference to a sub-routine's return value, you have to make a reference to a copy of the return value.

Here is the code that demonstrates this:

#!/usr/bin/perl
#From a post on caffeinemakesmesleepy.blogspot.com
# Demonstrate how to take an array return from one function and pass a reference to it into another.

#[] around return_array function makes a reference to a copy of the return value of that function.
# you need the () after return_array or "return_array" gets passed into take_array_ref
take_array_ref([return_array()]);

sub return_array {
my @ret;
push (@ret, 'FOO');
push (@ret, 'BAR');
return @ret;
}

sub take_array_ref {
my $ref = shift;
my $i = 0;
foreach my $value (@$ref) {
$i++;
print "Element #$i: $value\n";
}
}

Saturday, October 25, 2008

Perl Test::More trick

Recently I was working on a rather large Perl module and writing unit tests for it. I had some tests already completely done and trying to debug another chunk of code & tests. It was hard with debugging on to see what was going on. I just wanted to see one set of tests and nothing from the other sets. At first I commented out the blocks of code that ran the tests I didn't care about. Then I realized there was an easier way.

Say you have a test that starts with something like:

sub my_batch_of_tests : Test(6) {


Easy way to disable these: turn the above line to something like

sub my_batch_of_tests { # : Test(6)


When you do run_tests() on this test module, it won't run this block of tests because this function will no longer register as a test.


NOTE: this tip assumes you are using Test::More and Test::Class and have it set up so all your tests are in a module and you have a script that loads that module and does ->run_tests on the module with your tests.

Wednesday, October 1, 2008

SQL - you can't compare NULL to anything

Here is a little mind-bender for any of you who are programmers who routinely work with SQL. Write a little code that checks to see if NULL equals NULL. It returns false. Now write code to see if NULL is not equal NULL. It will return false too. Now repeat with NULL and any value. NULL equals 42 returns false, NULL is not equal 42 returns false. * What in the world is going on here?

Here's what I found when I ran into this issue before. What we're seeing here is the impact of NULL being a mathematical concept. SQL is built on many mathematical concepts. The concept of NULL is an unknown value. Since NULL is an unknown value, it may be 42, it may be Fred. We simply don't know. So comparing anything at all to NULL (even comparing NULL to itself) will *ALWAYS* return false. This is why you need to specify IS NULL or IS NOT NULL if you want to see if something is or isn't NULL.

* I experienced this issue most recently working with Oracle, but it will work with any SQL database such as MySQL, PostgreSQL, and Microsoft SQL Server.

Friday, September 5, 2008

Using Windows environment variables

This post will be a little more basic than most things I write here. I'm used to using MacOS/X on the desktop and Linux on the server side. So when I have to use Windows for one reason or another it sometimes takes me a bit to figure things out.

Today I was helping a co-worker with Oracle Application Express (APEX for short) and the install directions said to run "cd $ORACLE_HOME/apex" and then run some commands. The cd command didn't work because Windows does environment variables different than Unix operating systems.

This article covers it in more detail but in short Windows indicates environment variables by putting a % (percent sign) before and after the variable. Variables are not case sensitive.

You can show them by running "echo %ENV_NAME%" and set them on the command line by running "ENV_NAME = new_value". You can make the setting part of your login profile by right-clicking on "My Computer", then click Properties, then Advanced, and then Environment Variables. This is for XP, the location may be different on Vista or other versions of Windows.

Saturday, June 7, 2008

MySQL++ meets Leopard on an Intel Mac

A friend of mine is learning C++ and also wants to learn MySQL. I decided to go ahead and show him how to connect MySQL to a database in C++. Once I started, I realized I've never done this with MySQL, only with PostgreSQL. Oh well, how different could it be???

I decided to install on my Mac Mini which is running MacOS/X 10.5 Leopard. Installing the latest stable version of MySQL from source was cake. I got the sample C program working with no problems and then I looked for how to hookup C++ to MySQL. MySQL itself does not come with a C++ API, only C. The C++ bindings are provided by a project called MySQL++. This is when the problems started.

First off, it gave me some errors about not being able to find some functions. This was the actual error:

./lib/mystring.cpp: In member function ‘int mysqlpp::String::compare(const std::string&) const’:
./lib/mystring.cpp:67: error: no matching function for call to ‘max(unsigned int, size_t)’
./lib/mystring.cpp: In member function ‘int mysqlpp::String::compare(const char*) const’:
./lib/mystring.cpp:81: error: no matching function for call to ‘max(unsigned int, size_t)’
./lib/mystring.cpp: In member function ‘int mysqlpp::String::compare(const std::string&) const’:
./lib/mystring.cpp:67: error: no matching function for call to ‘max(unsigned int, size_t)’
./lib/mystring.cpp: In member function ‘int mysqlpp::String::compare(const char*) const’:
./lib/mystring.cpp:81: error: no matching function for call to ‘max(unsigned int, size_t)’


A little googling around turns up this message on the MySQL++ mailing list. Apparently the way things were coded, this "max" function works perfectly fine on 32 bit processors, but not 64 bit. The fix is to change 1 line of the lib/mystring.h file in the source from "typedef unsigned int size_type;" to "typedef size_t size_type;". It sounds like this fix will be in the next release of MySQL++ and then no one will have to worry about it.

Another note here - the library for MySQL++ isn't libmysql++ or mysql++ as one may expect. It is mysqlpp. Just as well, special characters tend to mess things up sometimes.

The other problem I ran into was this error when trying to compile the sample program from the MySQL++ documentation:

ld: in /usr/local/lib, can't map file, errno=22
collect2: ld returned 1 exit status


This turned out to be one of those silly mistakes that causes a big problem. In specified the linker path, I had put

-L /usr/local/lib

When I changed it to

-L/usr/local/lib

it worked fine. This seems like something the GNU development utilities should be able to be smart enough to handle.