Monday, December 31, 2012

AngularJS checkbox initialization

With ng-checked=true, though the checkbox's state is checked, the model is not synched with the checkbox's state on initial page load, i.e. Love won't appear and isImportant won't appear on UI: http://jsfiddle.net/Gs594/


<p>Show important: <input ng-model='isImportant' type='checkbox' ng-checked='true'/></p>

<p ng-show='isImportant'>Love</p>

<p>{{isImportant}}</p>


Value initialization should be done on ng-init: http://jsfiddle.net/Gs594/1/

<p>Show important: <input ng-model='isImportant' type='checkbox' ng-init='isImportant=true'/></p>

<p ng-show='isImportant'>Love</p>

<p>{{isImportant}}</p>
​


Love will appear, and true would appear too.


Better yet, initialize models on controller: http://jsfiddle.net/Gs594/2/

<p>Show important: <input ng-model='isImportant' type='checkbox'/></p>

<p ng-show='isImportant'>Love</p>

<p>{{isImportant}}</p>


function SomeController($scope) {
    $scope.isImportant = true;        
}​



That left us with a lingering question, if model initialization would suffice on ng-init and it's ideal to set them on controller, when to use ng-checked then? For the life of me I can't find it in google, and I find ng-checked anathema to AngularJS' single-source-of-truth principle; and in order to facilitate single-source-of-truth principle, two-way binding should work all the time, but in ng-checked case I don't know why it doesn't sync its state to the model.

I'm still finding a use case for ng-checked ツ

Sunday, December 30, 2012

Making your blog full-width

Whereas in my long-time blog http://www.ienablemuch.com/ , just changing class='content' to non-existent class, e.g. class='x_content' can make that blog full width; in this blog that doesn't work, I can't figure out why.


What works is, must change this:

.content-outer, .content-fauxcolumn-outer, .region-inner {
        min-width: $(content.width);
        max-width: $(content.width);
        _width: $(content.width);
      }

To:

.content-outer, .content-fauxcolumn-outer, .region-inner {
        min-width: 100%;
        max-width: 100%;
        _width: 100%;
      }


Sunday, December 9, 2012

Amortization Calculator

The best compliment I'm getting when making an app is when others are saying I know how the business works. Real Estate is one of them, the point person on that project said to me that I know how real estate(or at least the computation side of it) works more than their sales agents

That can be realized more (learning about the business process more than learning the nuts and bolts of programming) if the UI infrastructure doesn't get in the way of your business logic code. AngularJS facilitates that. UI is not "programming" with AngularJS. Your business logic code is devoid of UI concerns


Here's the amortization calculator component of the real estate app I made long time ago(2003, made in VB6) written in AngularJS:




Use this when you want to compute the balance when you have extra payments:


Saturday, December 8, 2012

Saturday, December 1, 2012

Audit trail with Postgresql hstore data type

Making audit trail on Postgres is just a walk in the park with hstore data type.


test=# SELECT 'apple=>1,orange=>6,guava=>8'::hstore;
                  hstore                   
-------------------------------------------
 "apple"=>"1", "guava"=>"8", "orange"=>"6"
(1 row)



So what is hstore? This is the explanation from Postgres documentation:

This module implements the hstore data type for storing sets of key/value pairs within a single PostgreSQL value. This can be useful in various scenarios, such as rows with many attributes that are rarely examined, or semi-structured data. Keys and values are simply text strings.


To enumerate those key value pairs, use the each function:

test=# select * from each(
(SELECT 'apple=>1,orange=>6,guava=>8'::hstore));
  key   | value 
--------+-------
 apple  | 1
 guava  | 8
 orange | 6
(3 rows)


Do a light bulb lit up on your head? Yeah me too, I'm so using that hstore to do an audit trail on Postgres trigger. But before we head to that, please do note note that you cannot reduce an existing table columns to an hstore type directly:

test=# with sample_row as 
(select 'Lennon'::text as lastname, 'John'::text as firstname, 1940 as birth_year) 
select hstore(*) from sample_row;

ERROR:  function hstore() does not exist
LINE 1: ...n'::text as firstname, 1940 as birth_year) select hstore(*) ...
                                                             ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

To reduce all the columns of a table row to one column, just pass the table name as the parameter to hstore:

test=# with sample_row as 
(select 'Lennon'::text as lastname, 'John'::text as firstname, 1940 as birth_year) 
select hstore(sample_row) from sample_row;
                             hstore                              
-----------------------------------------------------------------
 "lastname"=>"Lennon", "firstname"=>"John", "birth_year"=>"1940"
(1 row)

Better yet, give the table an alias:
test=# with sample_row as 
(select 'Lennon'::text as lastname, 'John'::text as firstname, 1940 as birth_year) 
select hstore(p) from sample_row p;
                             hstore                              
-----------------------------------------------------------------
 "lastname"=>"Lennon", "firstname"=>"John", "birth_year"=>"1940"
(1 row)


Now that the table columns is now reduced to an hstore data type. We could enumerate them now using each function:

test=# with sample_row as 
(select 'Lennon'::text as lastname, 'John'::text as firstname, 1940 as birth_year) 
select * from each((select hstore(p) from sample_row p));
    key     | value  
------------+--------
 lastname   | Lennon
 firstname  | John
 birth_year | 1940
(3 rows)


Armed with this knowledge, we could now proceed to make an audit trail for a table.


First, we create the audit trail table:

create extension hstore; 
create sequence group_op;

create table data_trail
(
data_trail_id serial not null primary key,
table_name text not null,
table_op text not null,
group_op bigint not null,
field_name text not null,
current_value text,
old_value text
);

Then create a sample table:
create table person
(
 person_id serial not null primary key,
 lastname text not null,
 firstname text not null,
 nickname text null,
 favorite_number int null
);

group_op is for grouping related operation on a table.


Now let's create the audit trail trigger, the insert trigger is the easiest of the bunch, here's how to handle INSERT audit:

create or replace function log_insert() returns trigger
as
$$
declare s bigint;
begin
 s := nextval('group_op');

 insert into data_trail(table_name, table_op, group_op, field_name, current_value)
 select TG_TABLE_NAME, TG_OP, s, x.key, x.value 
 from each(hstore(new.*)) as x;
 return new;
end;
$$ language 'plpgsql';

I prefer to use the new.* to new, so as to fully-qualify that reserved identifier, you may have a field named new in your table.

To wire that trigger on the table:
create trigger log_insert_trigger
after insert on product
for each row
execute procedure log_insert();

Finally to test:
insert into person(lastname,firstname,nickname, favorite_number) values
('lennon','john winston','john',default),
('mccartney','james paul','paul',default),
('harrison','george',default,default),
('starr','richard','ringo', 10);

Here's the content of person table:
test=# select * from person;
 person_id | lastname  |  firstname   | nickname | favorite_number 
-----------+-----------+--------------+----------+-----------------
         1 | lennon    | john winston | john     |                
         2 | mccartney | james paul   | paul     |                
         3 | harrison  | george       |          |                
         4 | starr     | richard      | ringo    |              10
(4 rows)

Here's the content of data trail:
test=# select * from data_trail;
 data_trail_id | table_name | table_op | group_op |   field_name    | current_value | old_value 
---------------+------------+----------+----------+-----------------+---------------+-----------
             1 | person     | INSERT   |        1 | lastname        | lennon        | 
             2 | person     | INSERT   |        1 | nickname        | john          | 
             3 | person     | INSERT   |        1 | firstname       | john winston  | 
             4 | person     | INSERT   |        1 | person_id       | 1             | 
             5 | person     | INSERT   |        1 | favorite_number |               | 
             6 | person     | INSERT   |        2 | lastname        | mccartney     | 
             7 | person     | INSERT   |        2 | nickname        | paul          | 
             8 | person     | INSERT   |        2 | firstname       | james paul    | 
             9 | person     | INSERT   |        2 | person_id       | 2             | 
            10 | person     | INSERT   |        2 | favorite_number |               | 
            11 | person     | INSERT   |        3 | lastname        | harrison      | 
            12 | person     | INSERT   |        3 | nickname        |               | 
            13 | person     | INSERT   |        3 | firstname       | george        | 
            14 | person     | INSERT   |        3 | person_id       | 3             | 
            15 | person     | INSERT   |        3 | favorite_number |               | 
            16 | person     | INSERT   |        4 | lastname        | starr         | 
            17 | person     | INSERT   |        4 | nickname        | ringo         | 
            18 | person     | INSERT   |        4 | firstname       | richard       | 
            19 | person     | INSERT   |        4 | person_id       | 4             | 
            20 | person     | INSERT   |        4 | favorite_number | 10            | 
(20 rows)

As we can see, all those related inserts can be identified by the group_op.


Now let's try to make an audit trail for UPDATE:
create or replace function log_update() returns trigger
as
$$
declare 
 s bigint;


begin
 s := nextval('group_op');

        
 with changes as
 (
  select n.key, n.value as new_value, o.value as old_value
  from each(hstore(new.*)) as n
  join each(hstore(old.*)) as o using(key)
  where n.value is distinct from o.value 
 )
 insert into data_trail(table_name, table_op, group_op, field_name, current_value, old_value)
 select TG_TABLE_NAME, TG_OP, s, key, new_value, old_value
 from changes

 union

 select TG_TABLE_NAME, TG_OP, s, key, n.value, o.value
 from each(hstore(new.*)) as n
 join each(hstore(old.*)) as o using(key)
 where 
  exists(select * from changes)
  and 
  key in 
   (select column_name 
   from information_schema.key_column_usage
   where constraint_name = 
    (select constraint_name 
    from information_schema.table_constraints 
    where (table_schema,table_name,constraint_type) = (TG_TABLE_SCHEMA,TG_TABLE_NAME,'PRIMARY KEY')
    )
   );
   
  
 return new;
end;
$$ language 'plpgsql';

We only log those columns that changed, and we also include the primary key regardless if the modified row had its primary key value changed or not, hence the need to use the information_schema.key_column_usage.

Then to wire the trigger on person table
create trigger log_update_trigger
after update on person
for each row
execute procedure log_update();

To test if our logic works, issue this command:
update person set lastname = 'lennon', firstname = 'john ono', nickname = 'john', favorite_number = 9 where person_id = 1;

We only change the firstname and favorite number, the lastname and nickname stayed the same:

Then check the audit trail:
test=# select * from data_trail;
 data_trail_id | table_name | table_op | group_op |   field_name    | current_value |  old_value   
---------------+------------+----------+----------+-----------------+---------------+--------------
             1 | person     | INSERT   |        1 | lastname        | lennon        | 
             2 | person     | INSERT   |        1 | nickname        | john          | 
             3 | person     | INSERT   |        1 | firstname       | john winston  | 
             4 | person     | INSERT   |        1 | person_id       | 1             | 
             5 | person     | INSERT   |        1 | favorite_number |               | 
             6 | person     | INSERT   |        2 | lastname        | mccartney     | 
             7 | person     | INSERT   |        2 | nickname        | paul          | 
             8 | person     | INSERT   |        2 | firstname       | james paul    | 
             9 | person     | INSERT   |        2 | person_id       | 2             | 
            10 | person     | INSERT   |        2 | favorite_number |               | 
            11 | person     | INSERT   |        3 | lastname        | harrison      | 
            12 | person     | INSERT   |        3 | nickname        |               | 
            13 | person     | INSERT   |        3 | firstname       | george        | 
            14 | person     | INSERT   |        3 | person_id       | 3             | 
            15 | person     | INSERT   |        3 | favorite_number |               | 
            16 | person     | INSERT   |        4 | lastname        | starr         | 
            17 | person     | INSERT   |        4 | nickname        | ringo         | 
            18 | person     | INSERT   |        4 | firstname       | richard       | 
            19 | person     | INSERT   |        4 | person_id       | 4             | 
            20 | person     | INSERT   |        4 | favorite_number | 10            | 
            21 | person     | UPDATE   |        5 | person_id       | 1             | 1
            22 | person     | UPDATE   |        5 | favorite_number | 9             | 
            23 | person     | UPDATE   |        5 | firstname       | john ono      | john winston
(23 rows)

As we can see, person_id #1's lastname and nickname columns are not logged even they are included in the UPDATE command. This is a desirable functionality on audit trail trigger as most ORMs merely set every fields of the table regardless if the table class' column(s) was changed or not.

And also, try to re-issue the same update command above, nothing will be logged on your audit trail table. The update trigger above was designed to handle that scenario.


Finally for the delete trigger:
create or replace function log_delete() returns trigger
as
$$
declare s bigint;
begin
 s := nextval('group_op');
 insert into data_trail(table_name, table_op, group_op, field_name, current_value)
 select TG_TABLE_NAME, TG_OP, s, x.key, x.value 
 from each(hstore(old.*)) as x
 where x.key in 
  (select column_name 
  from information_schema.key_column_usage
  where constraint_name = 
   (select constraint_name 
   from information_schema.table_constraints 
   where (table_schema,table_name,constraint_type) = (TG_TABLE_SCHEMA,TG_TABLE_NAME,'PRIMARY KEY')
   )
  );

 return old;
end;
$$ language 'plpgsql';


create trigger log_delete_trigger
after delete on person
for each row
execute procedure log_delete();

We just logged the key of the deleted row. All else are excluded. To test, issue this command:
delete from person where person_id = 1;

Output:
test=# select * from data_trail;
 data_trail_id | table_name | table_op | group_op |   field_name    | current_value |  old_value   
---------------+------------+----------+----------+-----------------+---------------+--------------
             1 | person     | INSERT   |        1 | lastname        | lennon        | 
             2 | person     | INSERT   |        1 | nickname        | john          | 
             3 | person     | INSERT   |        1 | firstname       | john winston  | 
             4 | person     | INSERT   |        1 | person_id       | 1             | 
             5 | person     | INSERT   |        1 | favorite_number |               | 
             6 | person     | INSERT   |        2 | lastname        | mccartney     | 
             7 | person     | INSERT   |        2 | nickname        | paul          | 
             8 | person     | INSERT   |        2 | firstname       | james paul    | 
             9 | person     | INSERT   |        2 | person_id       | 2             | 
            10 | person     | INSERT   |        2 | favorite_number |               | 
            11 | person     | INSERT   |        3 | lastname        | harrison      | 
            12 | person     | INSERT   |        3 | nickname        |               | 
            13 | person     | INSERT   |        3 | firstname       | george        | 
            14 | person     | INSERT   |        3 | person_id       | 3             | 
            15 | person     | INSERT   |        3 | favorite_number |               | 
            16 | person     | INSERT   |        4 | lastname        | starr         | 
            17 | person     | INSERT   |        4 | nickname        | ringo         | 
            18 | person     | INSERT   |        4 | firstname       | richard       | 
            19 | person     | INSERT   |        4 | person_id       | 4             | 
            20 | person     | INSERT   |        4 | favorite_number | 10            | 
            21 | person     | UPDATE   |        5 | person_id       | 1             | 1
            22 | person     | UPDATE   |        5 | favorite_number | 9             | 
            23 | person     | UPDATE   |        5 | firstname       | john ono      | john winston
            24 | person     | DELETE   |        6 | person_id       | 1             | 
(24 rows)



Finally, it maybe already obvious, but it's worth noting to point out that the above trigger is not tied to one table only:

create table product
(
 product_id serial not null primary key,
 product_name text not null,
 product_description text not null
);


create trigger log_insert_trigger
after insert on product
for each row
execute procedure log_insert();


create trigger log_update_trigger
after update on product
for each row
execute procedure log_update();



create trigger log_delete_trigger
after delete on product
for each row
execute procedure log_delete();



insert into product(product_name, product_description) values
('keyboard','interface between you and the machine'),
('mouse','interface between you and Angry Bird');


Output on audit trail:
            13 | person     | INSERT   |        3 | firstname           | george                                | 
            14 | person     | INSERT   |        3 | person_id           | 3                                     | 
            15 | person     | INSERT   |        3 | favorite_number     |                                       | 
            16 | person     | INSERT   |        4 | lastname            | starr                                 | 
            17 | person     | INSERT   |        4 | nickname            | ringo                                 | 
            18 | person     | INSERT   |        4 | firstname           | richard                               | 
            19 | person     | INSERT   |        4 | person_id           | 4                                     | 
            20 | person     | INSERT   |        4 | favorite_number     | 10                                    | 
            21 | person     | UPDATE   |        5 | person_id           | 1                                     | 1
            22 | person     | UPDATE   |        5 | favorite_number     | 9                                     | 
            23 | person     | UPDATE   |        5 | firstname           | john ono                              | john winston
            24 | person     | DELETE   |        6 | person_id           | 1                                     | 
            25 | product    | INSERT   |        7 | product_id          | 5                                     | 
            26 | product    | INSERT   |        7 | product_name        | keyboard                              | 
            27 | product    | INSERT   |        7 | product_description | interface between you and the machine | 
            28 | product    | INSERT   |        8 | product_id          | 6                                     | 
            29 | product    | INSERT   |        8 | product_name        | mouse                                 | 
            30 | product    | INSERT   |        8 | product_description | interface between you and Angry Bird  | 
(30 rows)

Thursday, November 29, 2012

Can your RDBMS do a convenient audit trail?

Can your RDBMS do this?

create table person
(
 person_id serial not null primary key,
 lastname text not null,
 firstname text not null,
 nickname text null,
 favorite_number int null
);


insert into person(lastname,firstname,nickname, favorite_number) values
('lennon','john winston','john',default),
('mccartney','james paul','paul',default),
('harrison','george',default,default),
('starr','richard','ringo', 10);

select skeys(hstore(p.*)) as field, svals(hstore(p.*)) as value from person p;



Output:

      field      |    value     
-----------------+--------------
 lastname        | lennon
 nickname        | john
 firstname       | john winston
 person_id       | 2
 favorite_number | 
 lastname        | mccartney
 nickname        | paul
 firstname       | james paul
 person_id       | 3
 favorite_number | 
 lastname        | harrison
 nickname        | 
 firstname       | george
 person_id       | 4
 favorite_number | 
 lastname        | starr
 nickname        | ringo
 firstname       | richard
 person_id       | 5
 favorite_number | 10
(20 rows)

hstore can be used as a convenient mechanism for audit trail

http://www.sqlfiddle.com/#!1/d5729/1


Saturday, November 24, 2012

Detect kissing and overlapping points in Highcharts

formatter: function() {
    
   // console.log(this);

   // Michael Buen is here                    
 
 var search = this.series.chart.series[0].data;

 var a = this.point;

 var overlapCount = 0;                    
 for(var i in search) {
        
  var b = search[i];
  var d = getDistance(a, b);
  
  // choose an overlap threshold
  var kiss = 5 * 2;
  var halfOverlap = 5;
  var fullOverlap = 2.5; 
  if (d <= kiss) {
   ++overlapCount;
  }
        
 }
 
      
 return this.x +' cm, '+ this.y +' kg' + a.plotX + ' <br/><b>Overlaps:</b> ' + overlapCount;
}



function getDistance(point1,point2)
{
  var xs = 0;
  var ys = 0;
  xs = point2.plotX - point1.plotX;
  xs = xs * xs;
  ys = point2.plotY - point1.plotY;
  ys = ys * ys;
  return Math.sqrt( xs + ys );
}



Live code: http://jsfiddle.net/HxTjK/

Monday, October 29, 2012

AngularJS: Write Less Code, Go Have Girlfriend Sooner

Programming is a craft that is notorious for not being too conducive for having a relationship. Aside from it having the stigma for being too geeky, it is notorious for siphoning all your precious time that could be otherwise spent on some important things in life, like being able to leave work on time and get the chance (before you can even get the chance, you have to get the time first) to date the girl you're dreaming of; or if you already are a family man, spend quality time with your family.


Let's look at sample code that could be shortened if we are using a good framework. First, the longer code:

http://jsfiddle.net/3Xtnd/

Countries <select id='TravelToCountryId'></select>
<br/>
Cities <select id='TravelToCityId'></select>​

...

$(function() { 
    
    // Models
    
    var countries = 
    [
        { 
            CountryId: 1, CountryName: 'Philippines',
            Cities :
            [
                { CityId: 1, CityName: 'Manila' },
                { CityId: 2, CityName: 'Makati' },
                { CityId: 3, CityName: 'Quezon' },            
            ]            
        },
        { 
            CountryId: 2, CountryName: 'Canada',
            Cities:
            [
                { CityId: 4, CityName: 'Toronto' },
                { CityId: 5, CityName: 'Alberta' },
                { CityId: 6, CityName: 'Winniepeg' },
            ]           
            
        },
        { 
            CountryId: 3, CountryName: 'China',
            Cities:
            [
                { CityId: 7, CityName: 'Beijing' },
                { CityId: 8, CityName: 'Shanghai' }
            ]           
        },    
    ];    
           
    
    // Controller that live two lives,
    // can't focus well on model :-)
    
    
    // Populate then wire event...
    
    var country = $('#TravelToCountryId');
    var city = $('#TravelToCityId');
    
    
    $.each(countries, function() {
        var option = $('<option />').val(this.CountryId).text(this.CountryName);
        country.append(option);
    });
    
    $(country).change(function() {
        filterCitiesByCountry();
    });
    
    // ...Populate then wire event
    
    
    // Init..
    var initialCountryId = countries[1].CountryId; 
    $(country).val(initialCountryId);
    filterCitiesByCountry();    
    // ...Init
    
    function filterCitiesByCountry() {
        var selectedCountryId = country.val();
        
        
        // filter works on all browsers, except <= IE8
        var countryObj = countries.filter(function(v) {
            return v.CountryId == selectedCountryId;
        })[0];
        

        var cities = countryObj.Cities;
                
        city.empty();
        
        $.each(cities, function() {
            var option = $('<option/>').val(this.CityId).text(this.CityName);
            
            city.append(option);
        });

        
    } // filterCitiesByCountry()
         
    
});      



Then let's use a framework that facilitates declarative programming and allows separation of concerns. Let's use an MVC framework for JavaScript, let's use AngularJS. Following is the equivalent AngularJS code, there's nothing in the code that deals directly with the UI. You'll notice that the code don't have anything that imperatively populates the HTML, most are done declaratively, thus making your code shorter. Barring HTML tags, jQuery approach took 88 lines of code, while AngularJS took 56 lines only. Lesser code, lesser to debug when something goes wrong, lesser time coding, lesser development time.

http://jsfiddle.net/nDw2Z/

<div ng-controller='TravelController' ng-init='init()'>
Countries 
    <select ng-model='TravelToCountryId'     
    ng-options='i.CountryId as i.CountryName for i in countries' 
    
    ng-init='filterCitiesByCountry()'
    ng-change='filterCitiesByCountry()'></select>
    
<br/>
Cities 
    <select ng-model='TravelToCityId'
    ng-options='i.CityId as i.CityName for i in citiesFromSelectedCountry'></select>
</div>

...

function TravelController($scope) {
    
    // Models
    
    $scope.countries = 
    [
        { 
            CountryId: 1, CountryName: 'Philippines',
            Cities :
            [
                { CityId: 1, CityName: 'Manila' },
                { CityId: 2, CityName: 'Makati' },
                { CityId: 3, CityName: 'Quezon' },            
            ]            
        },
        { 
            CountryId: 2, CountryName: 'Canada',
            Cities:
            [
                { CityId: 4, CityName: 'Toronto' },
                { CityId: 5, CityName: 'Alberta' },
                { CityId: 6, CityName: 'Winnipeg' },
            ]           
            
        },
        { 
            CountryId: 3, CountryName: 'China',
            Cities:
            [
                { CityId: 7, CityName: 'Beijing' },
                { CityId: 8, CityName: 'Shanghai' }
            ]           
        },    
    ];    
    
    $scope.TravelToCountryId = null;
    $scope.TravelToCityId = null;
    
    
    // Controller's actions
    
    $scope.init = function() {
        $scope.TravelToCountryId = $scope.countries[1].CountryId;    
    };
        
    
    $scope.filterCitiesByCountry = function() {
               
        var cities = $scope.citiesFromSelectedCountry = $scope.countries.filter(function(v){
            return v.CountryId == $scope.TravelToCountryId; 
        })[0].Cities;
        
        $scope.TravelToCityId = cities[0].CityId;                
        
    };
                
}

The user decided that the program could be more appealing and user-friendly by making the country selection done via radio button since there are only few of them to select from. This user requirement necessitates changing your code as the dropdown list and radio button have different mechanism to carry information; on dropdown list it comes from option tags, and on radio button it is directly on input's value attribute. Dropdown list's mechanism for setting the default value is a mere .val(valueHere), while radio button need to find the object and then set its checked attribute.


http://jsfiddle.net/KhANV/

Countries <div id='divTravelToCountryId'></div>
<br/>
Cities <select id='TravelToCityId'></select>​

...

$(function() { 
    
    // Models
    
    var countries = 
    [
        { 
            CountryId: 1, CountryName: 'Philippines',
            Cities :
            [
                { CityId: 1, CityName: 'Manila' },
                { CityId: 2, CityName: 'Makati' },
                { CityId: 3, CityName: 'Quezon' },            
            ]            
        },
        { 
            CountryId: 2, CountryName: 'Canada',
            Cities:
            [
                { CityId: 4, CityName: 'Toronto' },
                { CityId: 5, CityName: 'Alberta' },
                { CityId: 6, CityName: 'Winnipeg' },
            ]           
            
        },
        { 
            CountryId: 3, CountryName: 'China',
            Cities:
            [
                { CityId: 7, CityName: 'Beijing' },
                { CityId: 8, CityName: 'Shanghai' }
            ]           
        },    
    ];    
           
    
    
    // Controller that live two lives,
    // can't focus well on model :-)
    
    // Populate then wire event...
    
    var divCountry = $('#divTravelToCountryId');
    
        
    $.each(countries, function() {
        
        var option = $(
            '<input type="radio" ' + 
            ' id="TravelToCountryId"' + 
            ' name="TravelToCountryId" />').val(this.CountryId);
        
        divCountry.append(option).append(' ' + this.CountryName).append('<br/>');
        
    });
    
    var country = $('input[name=TravelToCountryId]');
    var city = $('#TravelToCityId');
    
    
    $(country).change(function() {     
        filterCitiesByCountry();
    });
    
    // ...Populate then wire event
    
    
    // Init...
    var initialCountryId = countries[1].CountryId;     
    $(country).filter('[value="' + initialCountryId + '"]').prop('checked',true);        
    filterCitiesByCountry();
    // ...Init
    
            
    function filterCitiesByCountry() {
                
        var selectedCountryId = $(country).filter(':checked').val();
                   
        
        // filter works on all browsers, except <= IE8
        var countryObj = countries.filter(function(v) {
            return v.CountryId == selectedCountryId;
        })[0];
        

        var cities = countryObj.Cities;
                
        city.empty();
        
        $.each(cities, function() {
            var option = $('<option/>').val(this.CityId).text(this.CityName);
            
            city.append(option);
        });
        
    }
       
});      
​

Now let's try it on AngularJS: http://jsfiddle.net/ZjehV/

<div ng-controller='TravelController' ng-init='init()'>

Countries     
    <div ng-repeat='i in countries'>
    <input type=radio ng-model='$parent.TravelToCountryId'  
    name='TravelToCountryId'        
    ng-init='filterCitiesByCountry()'
    ng-change='filterCitiesByCountry()' value='{{i.CountryId}}' />&nbsp;{{i.CountryName}}
    </div>    
        
<br/>
Cities <select id='TravelToCityId'
    ng-model='TravelToCityId'
    ng-options='i.CityId as i.CityName for i in citiesFromSelectedCountry'
    ></select>
    
</div>
​
...

function TravelController($scope) {
    
    // Models
    
    $scope.countries = 
    [
        { 
            CountryId: 1, CountryName: 'Philippines',
            Cities :
            [
                { CityId: 1, CityName: 'Manila' },
                { CityId: 2, CityName: 'Makati' },
                { CityId: 3, CityName: 'Quezon' },            
            ]            
        },
        { 
            CountryId: 2, CountryName: 'Canada',
            Cities:
            [
                { CityId: 4, CityName: 'Toronto' },
                { CityId: 5, CityName: 'Alberta' },
                { CityId: 6, CityName: 'Winnipeg' },
            ]           
            
        },
        { 
            CountryId: 3, CountryName: 'China',
            Cities:
            [
                { CityId: 7, CityName: 'Beijing' },
                { CityId: 8, CityName: 'Shanghai' }
            ]           
        },    
    ];    
    
    $scope.TravelToCountryId = null;
    $scope.TravelToCityId = null;
    
    
    // Controller's actions
    
    $scope.init = function() {
        $scope.TravelToCountryId = $scope.countries[1].CountryId;    
    };
        
    
    $scope.filterCitiesByCountry = function() {
               
        var cities = $scope.citiesFromSelectedCountry = $scope.countries.filter(function(v){
            return v.CountryId == $scope.TravelToCountryId; 
        })[0].Cities;
        
        $scope.TravelToCityId = cities[0].CityId;        
                
    };
            
}
​


Let's measure the level of effort that was spent between the two when you accomodate changes in user requirement. jQuery's lines of code have increased from 88 to 97, while AngularJS stays the same, 56. So what changed on those 56 lines? Zero, zilch, nada. When you come to think of it, even your user request another changes on your UI, be they wanted to select from ul+li, table+td, div+a and whatnot, there should be no changes on your code to make that happen. Your code should be able to reflect only how your business operates, it should be devoid of idiosyncrasies of whatever UI choice imposes.


As an exercise, please try to convert jQuery version to use radio buttons too for city selection. Here's the AngularJS changes: http://jsfiddle.net/DL74y/, it has no changes on code, only the tags were changed.


With AngularJS or any decent MVC framework for javascript, you'll be able to accomplish more with lesser amount of effort. With AngularJS, your code can work exclusively on how your business operates, it doesn't have to pay attention on how the UI will be presented and used. User interface is a very fickle business, and you don't want your code to be impacted too much whenever some change is requested.



A minor aside on AngularJS, you cannot directly use ng-model='TravelToCountryId' when it's inside an ng-repeat, as different TravelToCountryId will be allocated on each element repetition, think of variable inside a loop. To prevent that from happening, make sure to reference the parent scope of TravelToCountryId, you can do that by prefixing the variable name with $parent.



The actual slogan of AngularJS: Write less code, go have beer sooner.

Sunday, October 28, 2012

jQuery filter, promotes DRY principle

You have this:

<input type='radio' name='TravelToCountryId' value='PH'> Philippines
<input type='radio' name='TravelToCountryId' value='CA'> Canada
<input type='radio' name='TravelToCountryId' value='ZH'> China​​​​​​​​

...

var country = $('input[name=TravelToCountryId]');
    
$(country).change(function() {     
    alert($(this).val());
});





You want to set the default(say Canada) using this:

$('input[name=TravelToCountryId][value=CA]').prop('checked',true);


Though that works, but as an astute developer you are, you feel that you are violating DRY principle and noticed that you can re-use the country object.


To re-use, use filter function. filter and find functions are almost synonym, however don't confuse them, find is for getting the descendant elements of existing elements, filter is for getting the elements from existing elements based on filter.


Do this:

$(country).filter('[value=CA]').prop('checked',true);​

Tuesday, October 9, 2012

Set focus on input upon click on ng-repeat

Live test: http://jsfiddle.net/epAxT/5/


Model and Controller:

function TestController($scope) {
        
    // Models
    $scope.messages = 
    [
    { Message: 'Life is what happens to you...', By: 'John Lennon' },
    { Message: 'If you can\'t explain...', By: 'Albert Einstein' },
    { Message: 'The answer to life...', By: 'Douglas Adams' }
    ];
    
    
    $scope.currentMessage = null;
    
    // Controller's actions
    
    $scope.setCurrentMessage = function(msg) {
        $scope.currentMessage = msg;
    };

    $scope.isCurrentMessage = function(msg) {
        return msg == $scope.currentMessage;
    };
    
    $scope.addMessage = function() {
        var msg = {Message: 'blah', By: 'Anonymous'};
        $scope.currentMessage = msg;
        $scope.messages.push(msg);
    };
    
}
    
    


    
    
var appGreat = angular.module('AppGreat', []);

appGreat.directive('toFocus', function ($timeout) {
    return function (scope, elem, attrs) {
        scope.$watch(attrs.toFocus, function (newval) {
            if (newval) {
                $timeout(function () {
                    elem[0].focus();
                }, 0, false);
            }
        });
    };
});
​


View:
<br/>
<div ng-app='AppGreat' ng-controller='TestController'>
    
    <table>
        <thead>
            <tr>
                <th>Message</th><th>By</th>
            </tr>
        </thead>
        <tbody>
            <tr ng-repeat='m in messages'>
                <td width='200px'>
                    <div ng-hide='isCurrentMessage(m)' 
                         ng-click='setCurrentMessage(m)'>
                        {{m.Message}}
                    </div>
                    <div ng-show='isCurrentMessage(m)'>
                        <input ng-model='m.Message'
                               to-focus='isCurrentMessage(m)'
                               style='width: 100%' />
                    </div>
                    
                    
                </td>
                
                <td>
                    <div ng-hide='isCurrentMessage(m)' 
                         ng-click='setCurrentMessage(m)'>
                        {{m.By}}
                    </div>
                    <div ng-show='isCurrentMessage(m)'>
                        <input ng-model='m.By'/>                        
                    </div>
                </td>
            </tr>
        </tbody>
    </table>
    
    
    <input type='button' ng-click='addMessage()' value='Add Message'/>
    
</div>       ​

Friday, September 21, 2012

My first visualization of math

Following code rotates a triangle:

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
 
class Renderer implements GLEventListener 
{
    private GLU glu = new GLU();
 
    float  i = 0;
    
    public void display(GLAutoDrawable gLDrawable) 
    {
        i += 0.05f;
        
        final GL2 gl = gLDrawable.getGL().getGL2();
        
        
        gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
        gl.glLoadIdentity();
        
        
        gl.glTranslatef(0f, 0.0f, -6.0f);
        
        
        double rotCos = Math.cos(i);
        double rotSine = Math.sin(i);
          
          
          
        gl.glBegin(GL2.GL_TRIANGLES);       

        {
            double pointX = 0;
            double pointY = 1.0f; 
            double pointZ = 0f;
            
            double pointNewX = pointX * rotCos + pointY * rotSine;
            double pointNewY = -(pointX * rotSine) + pointY * rotCos;
            double pointNewZ = 0;
            
                    
            gl.glVertex3d(pointNewX , pointNewY , pointNewZ);   
        }
        
 
        
        {
            double pointX = -1f;
            double pointY = -1f;
            double pointZ = 0f;
            
            double pointNewX = pointX * rotCos + pointY * rotSine;
            double pointNewY = -(pointX * rotSine) + pointY * rotCos;
            double pointNewZ = 0;
            
            gl.glVertex3d(pointNewX , pointNewY , pointNewZ);       
        }
       
        
        
        
        {
            double pointX = 1f;
            double pointY = -1f;
            double pointZ = 0f;
            
            double pointNewX = pointX * rotCos + pointY * rotSine;
            double pointNewY = -(pointX * rotSine) + pointY * rotCos;
            double pointNewZ = 0;
            
            gl.glVertex3d(pointNewX , pointNewY , pointNewZ);       
        }
       
        
        
        gl.glEnd();
        
        

    }
 
 
    public void displayChanged(GLAutoDrawable gLDrawable, boolean modeChanged, boolean deviceChanged) 
    {
        System.out.println("displayChanged called");
    }
 
    public void init(GLAutoDrawable gLDrawable) 
    {
        System.out.println("init() called");
        GL2 gl = gLDrawable.getGL().getGL2();
        gl.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        gl.glShadeModel(GL2.GL_FLAT);
    }
 
    public void reshape(GLAutoDrawable gLDrawable, int x, int y, int width, int height) 
    {
        
        System.out.println("reshape() called: x = "+x+", y = "+y+", width = "+width+", height = "+height);
        final GL2 gl = gLDrawable.getGL().getGL2();
 
        if (height <= 0) // avoid a divide by zero error!
        {
            height = 1;
        }
 
        final float h = (float) width / (float) height;
 
        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL2.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(45.0f, h, 1.0, 20.0);
        gl.glMatrixMode(GL2.GL_MODELVIEW);
        gl.glLoadIdentity();
    }
 
 
    public void dispose(GLAutoDrawable arg0) 
    {
        System.out.println("dispose() called");
    }
}


Finally made sense of those bracketed expressions, thanks Wikipedia!

http://en.wikipedia.org/wiki/Rotation_(mathematics)

Saturday, August 25, 2012

Is AngularJS very easy that there are very few blogs documenting it?

This app demonstrates how easy it is to structure your model with AngularJS and the UI automatically follow what happens to model seamlessly.

Live demo: http://jsfiddle.net/bpvjL/6/


HTML:

<div ng-app>
  <h2>Todo</h2>
  <div ng-controller="TodoCtrl">


    <ul class="unstyled">
      <li ng-repeat="todo in todos" >       
          <span class="isactive-{{activeTodo == todo}}" ng-click="changeActive(todo)" >
              <a href="#" style="none">{{todo.text}}</a>
          </span>
      </li>
    </ul>
      
      

    <form ng-submit="addTodo()">
      <input type="text" ng-model="todoText"  size="30"
             placeholder="add new todo here">
      <input class="btn-primary" type="submit" value="add">
    </form>
          
      <ul>
      <li ng-repeat="step in activeTodo.steps">
          {{$index + 1}} {{step.text}}
      </li>   
      </ul>

    <form ng-submit="addStep()">
      <input type="text" ng-model="stepText"  size="30"
             placeholder="add new step to: {{activeTodo.text}}">
      <input class="btn-primary" type="submit" value="add">
    </form>
          
  </div>
</div>
​


Javascript:

function TodoCtrl($scope) {
  $scope.todos = [
    {text:'learn angular',
     steps : [
         { text : 'learn' },
         { text : 'to' },           
         { text : 'build' }                    
     ]},
    {text:'build an angular app',
     steps : [ 
         { text : 'build' },         
         { text : 'and' }, 
         { text : 'they' }, 
         { text : 'will' }, 
         { text : 'come' }
     ]}
  ];
    
  $scope.activeTodo = $scope.todos[0];
  

  $scope.addTodo = function() {
        var todo = {text:$scope.todoText, steps: []};
        $scope.todos.push(todo);
        $scope.todoText = '';
        $scope.activeTodo = todo;
  };
    
  $scope.changeActive = function(active) {
        $scope.activeTodo = active;
  };


  $scope.addStep = function() {
        $scope.activeTodo.steps.push({text:$scope.stepText});
        $scope.stepText = '';
  };
    

}

​


CSS:

<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
<script src="http://code.angularjs.org/angular-1.0.1.min.js"></script>
<style>
.isactive-true {
    background: YELLOW;
}

Tuesday, August 7, 2012

jQuery selector nuances

​<select name="Beatle" id="Beatle"​​​​​​​​​​​​​​​​​​​​​​​>
    <option id=9>John</option>
    <option id=8>Paul</option>
    <option id=7 selected>George</option>
    <option id=6>Ringo</option>
</select>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​


<script>
 var selectedText = "";

 selectedText = $('#Beatle').text();
 alert('Not Correct: ' + selectedText);

 selectedText = $('option:selected','#Beatle').text();
 alert('Correct: ' + selectedText);

 selectedText = $('#Beatle:selected').text();
 alert('Not correct: ' + selectedText);

 selectedText = $('#Beatle :selected').text();
  alert('Correct: ' + selectedText);

});
</script>


Live test: http://jsfiddle.net/5XAYh/

Monday, August 6, 2012

Manual model and view synchronization with JavaScript

When you don't use an MVC javascript framework that can do two-way databinding, you are left on your own to synchronize the state between the model and the view.


Live test: http://jsfiddle.net/E7F7D/33/

<table id='dataHere' border='1'>
<thead>
    <!-- ID presence on HTML is optional --> 
    <!--<th style='visibility: collapse'>Id</th>-->
    
    <th>Lastname</th><th>Firstname</th><th>Asset</th><th>Actions</th>
</thead>
<tbody>
</tbody>
    
    
</table>

<hr/>

    <input type="button" id="viaModel" value="test via model"/>

    <input type="button" id="viaDom" value="test via DOM"/>
        
    <div id="debugLog">
     </div>


<script>
    var people = [
        { Id: 1, Lastname: 'Lennon', Firstname: 'John', Asset: 40090.1296 },
        { Id: 2, Lastname: 'McCartney', Firstname: 'Paul', Asset: 38000.34 },
        { Id: 3, Lastname: 'Harrison', Firstname: 'George', Asset: 37000.56 },
        { Id: 4, Lastname: 'Starr', Firstname: 'Ringo', Asset: 40000.78 },
        
        { Id: 5, Lastname: 'Buendia', Firstname: 'Ely', Asset: 40000.93 },
        { Id: 6, Lastname: 'Marasigan', Firstname: 'Raymund', Asset: 39000.12 },
        { Id: 7, Lastname: 'Zabala', Firstname: 'Buddy', Asset: 39000.13 },
        { Id: 8, Lastname: 'Adoro', Firstname: 'Marcus', Asset: 39000.14344 }    
        
        ];
    
    
    var tbl = $('#dataHere');
    
    $('#viaModel').click(function() {
        var dl = $('#debugLog');
        dl.html('Model-based approach. Data are in their pristine state');
        $.each(people, function() {
            var person = this;
            
            dl.append(person.Id + '-->' + person.Lastname + ', ' + person.Firstname + ': ' + this.Asset + '<p/>');
        });
    });
    
    $('#viaDom').click(function() {
        try {
            var dl = $('#debugLog');
            var tbl = $('#dataHere');
    
            dl.html('Using DOM approach for stashing and extracting data, the Id won\'t be available unless we stash it on HTML');
            
            
    
            var trs = $('tbody > tr', tbl);
    
    
            $.each(trs, function() {
                var tr = this;
                var tds = $('td', tr);
        
                // Alas! ID won't be available if you didn't put it in td tag or whatnot.
                // If we use DOM approach for stashing our data, 
                // we have to stash ID on the HTML itself, 
                // this is called Smart UI approach, this is abhored, 
                // as the code is tightly coupled to UI/presentation layer.
                
        
                var tdLastname = $(tds[0]);
                var tdFirstname = $(tds[1]);                       
                var tdAsset = $(tds[2]);
                
                
                
                var lastname = tdLastname.text();
                var firstname = tdFirstname.text();
                // another problem with Smart UI approach is the data gets mangled
                
                var asset = tdAsset.text().replace('Php ','').replace(',','');
                
                dl.append(lastname + ', '+ firstname + ': ' + asset);                
                
                
            })
                
            dl.append('And data gets mangled and truncated too. Check the rounding-offs');
        
        } catch(e) {
            alert(e);
        }
                       
    });
    
    
    $.each(people, function() {
        var person = this;
        
        var trPerson = $('<tr/>');
    
        
        // optional
        // var tdId = $('<td/>').css('visibility','collapse');
        
        var tdLastname = $('<td/>');
        var tdFirstname = $('<td/>');
        var tdAsset = $('<td/>');
        var tdActions = $('<td/>');
        
        var aEditAction = $('<a/>').prop('href','#').text('Edit');
        var aDeleteAction = $('<a/>').prop('href','#').text('Delete');
        
       
        // optional
        // tdId.text(this.Id);
        
        tdLastname.text(this.Lastname);
        tdFirstname.text(this.Firstname);
        tdAsset.text(formatMoney(this.Asset, 2, 'Php ', ',','.'));
    
        
        aEditAction.click(function() {
            // alert('Will edit ' + person.Id + ' ' + person.Lastname);
            
            
            var ln = prompt('Enter value', person.Lastname);
            person.Lastname = ln == null ? person.Lastname : ln;
            
            tdLastname.text(person.Lastname);
        });        
        
     
        
        aDeleteAction.click(function() {
            if (confirm('Will delete ' + person.Id + ' ' + person.Lastname)) {   
                
                people.splice(people.indexOf(person),1);
                
                trPerson.remove();
            }
        });
        
            
    
        
        trPerson
            // .append(tdId) // optional
            .append(tdLastname).append(tdFirstname)
            .append(tdAsset).append(tdActions);
        
        tdActions.append(aEditAction).append('|').append(aDeleteAction);
    
      
          
        tbl.append(trPerson);
    
            
    });
    
     // alert(8);
        // alert(formatMoney(92334.55, 2,'Php ',',','.'));
        
    // http://www.josscrowcroft.com/2011/code/format-unformat-money-currency-javascript/
    function formatMoney(number, places, symbol, thousand, decimal) {
        number = number || 0;
        places = !isNaN(places = Math.abs(places)) ? places : 2;
        symbol = symbol !== undefined ? symbol : "$";
        thousand = thousand || ",";
        decimal = decimal || ".";
        var negative = number < 0 ? "-" : "",
            i = parseInt(number = Math.abs(+number || 0).toFixed(places), 10) + "",
            j = (j = i.length) > 3 ? j % 3 : 0;
        return symbol + negative + (j ? i.substr(0, j) + thousand : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousand) + (places ? decimal + Math.abs(number - i).toFixed(places).slice(2) : "");
    }
</script>

Monitoring perfect attendance. Consecutive calendar date query

Postgresql implementation for Monitoring perfect attendance


create table tx
(
i serial not null primary key,
n varchar(10), d date,
constraint ux_tx unique(n,d)
);

insert into tx(n,d) values
('john','2012-7-3'),
('john','2012-7-5'),
('john','2012-7-6'),
('john','2012-7-9'),
('john','2012-7-12'),
('john','2012-7-13'),
('john','2012-7-16'),
('john','2012-7-17'),
('john','2012-7-18'),
('john','2012-7-20'),
('john','2012-7-30'),
('john','2012-7-31'),

('paul','2012-7-3'),
('paul','2012-7-5'),
('paul','2012-7-18'),
('paul','2012-7-19'),
('paul','2012-7-20'),
('paul','2012-7-23'),
('paul','2012-7-24'),
('paul','2012-7-25'),
('paul','2012-7-26'),
('paul','2012-7-27'),
('paul','2012-7-30'),
('paul','2012-7-31'),
('paul','2012-8-1'),
('paul','2012-8-3'),
('paul','2012-8-6'),
('paul','2012-8-7');

create table holiday(d date);

insert into holiday(d) values
('2012-7-4');


-- Monday logic sourced here: http://www.ienablemuch.com/2010/12/finding-previous-day-of-week.html




with first_date as
(
--  select dateadd( ww, datediff(ww,0,min(d)), 0 ) as first_date -- get the monday of the earliest date

select previous_date_of_day(min(d), 1) as first_date 
from tx 
)
,shifted as
(
 select
  tx.n, tx.d, 
     
  (tx.d - fd.first_date) - ( (tx.d - fd.first_date) / 7 * 2 ) as diff
   
 from tx
 cross join first_date fd
 union
 select
  xxx.n, h.d, 
   
  
  (h.d - fd.first_date) - ((h.d - fd.first_date) / 7 * 2) as diff
  
 from holiday h 
 cross join first_date fd
 cross join (select distinct n from tx) as xxx
)
,grouped as
(
 select
  *
  , diff - row_number() over(partition by n order by d) as grp
 from shifted
)
select
     
    -- remove staging columns from the output...
    -- * 
     
    -- ...just output what the user will see:
    d, n
     
 ,dense_rank() over (partition by n order by grp) as nth_streak
 ,count(*) over (partition by n, grp) as streak
from grouped
where d not in (select d from holiday)  -- remove the holidays



Get the previous day of the date if the day is not exactly on that date:
create or replace function previous_date_of_day(the_date date, dow int) returns date
as
$$
select
    case when extract(dow from $1) < $2 then
        $1 - ( extract(dow from $1) + (7 - $2) )::int
    else
        $1 - ( extract(dow from $1) - $2)::int
    end;
$$ language 'sql';

Sunday, August 5, 2012

AngularJS dropdown list

How not to do dropdown list:

 
<select ng-model="anotherLocationId">
    <option ng-repeat="location in locations" value="{{location.LocationId}}">{{location.LocationName}}</option>
</select>  


Although that can also populate the dropdown list, the UI won't be able to respond to initial model value. When you use that, even anotherLocationId has value, the dropdown will still show you blank item on its initial load.


Should do this instead:


<select ng-model="locationId" ng-options="item.LocationId as item.LocationName for item in locations"></select>



Complete code:


View
<div ng-controller="TheController" ng-app>

Location:     
<select ng-model="locationId" ng-options="item.LocationId as item.LocationName for item in locations"></select>
   
    <p/>
 
Another Location:    
<select ng-model="anotherLocationId">
    <option ng-repeat="location in locations" value="{{location.LocationId}}">{{location.LocationName}}</option>
</select>    
    
    <hr/>
    
    Location: {{locationId}} <br/>
    Another Location: {{anotherLocationId}}
    
    
</div>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​


Model
​function TheController($scope) {
    
    $scope.locations = [
        {LocationId : 7, LocationName : 'Philippines' },       
        {LocationId : 8, LocationName : 'Canada' },
        {LocationId : 9, LocationName : 'China' } ];

    $scope.locationId = 8;
    $scope.anotherLocationId = 8;
}​

Live test: http://jsfiddle.net/ELkn6/1/


Here's how to add empty value with ng-options. The second dropdown, which uses ng-repeat instead of ng-options, won't have a way to receive null value.


<div ng-app="demoApp" ng-controller="MainController as c">
<select ng-model="c.locationId" ng-options="item.LocationId as item.LocationName for item in c.locations">
  <option value>All</option>
</select>
   
    <p/>
 
Another Location:    
<select ng-model="c.locationCode">
    <option value>Unknown value</option>    
    <option>Doesn't work, ng-model can't receive null</option>    
    <option ng-value="null">Doesn't work, ng-model can't receive null too</option>
    <option value=''>Like null, empty string is a good value to denote all. However, empty string won't work on data type like number or date</option>
    <option value="ALL">Literal ALL, not a good value, as it can be a valid country code value, any code value for that matter</option>
    <option ng-repeat="location in c.locations" value="{{location.locationCode}}">{{location.LocationName}}</option>
</select>    

<hr/>

Location Id: {{c.locationId}}, Is Empty: {{c.locationId == null}}<br/>
Location Code: {{c.locationCode}}, Is Empty: {{c.locationCode == null}}

</div>

----



angular.module('demoApp', [])
 .controller('MainController', MainController);

function MainController() {
  
    this.locations = [
        {LocationId : 7, locationCode : 'CAD', LocationName : 'Canada' },       
        {LocationId : 8, locationCode : 'PHL', LocationName : 'Philippines' },
        {LocationId : 9, locationCode : 'CHN', LocationName : 'China' } 
    ];

    this.locationId = 8;
    this.locationCode = 'PHL';    
        
}



Live test: https://jsfiddle.net/d38ypmx0/


Happy Coding!


Saturday, July 28, 2012

I know it can be done pretty easily with Postgresql

Upon seeing this question in stackoverflow:


I want to make a SELECT and bring the info from a column and his values. I know that I need to access *information_schema* then I need to make another SELECT inside with the *column_name* in the specific row to acess that value.
SELECT column_name,
DATA_TYPE,
CHARACTER_MAXIMUM_LENGTH,
(? ... SELECT COLUMN_NAME FROM MYTABLE ... ?)
FROM information_schema.columns
WHERE table_name = 'MYTABLE'
ORDER BY ordinal_position

How to change the COLUMN_NAME with the column in the row to get the result?



I quickly discern that it can done pretty easily with Postgres, and sans the brittle string manipulation to boot.


To cut to the chase, here's the code:

create table beatles(firstname text,middlename text,lastname text, age int);

insert into beatles(firstname,middlename,lastname,age)
values('John','Winston','Lennon',40);



select c.column_name, x.arr[c.ordinal_position]
from information_schema.columns c
cross join ( select avals (hstore(b)) as arr from (select * from beatles) as b  ) x
where c.table_schema = 'public' and c.table_name = 'beatles'
order by c.ordinal_position




Output:
| COLUMN_NAME |     ARR |
-------------------------
|   firstname |    John |
|  middlename | Winston |
|    lastname |  Lennon |
|         age |      40 |    

Live demo: http://www.sqlfiddle.com/#!1/dea17/1

Friday, July 13, 2012

Using Postgresql, treat columns as dictionary

Why is Postgresql so lovely?

CREATE EXTENSION hstore;

select (each(hstore(r))).* from (select * from pg_tables limit 1)  as r;

select (each(hstore(r))).key, (each(hstore(r))).value from (select * from pg_tables limit 1)  as r;

select z.key, z.value from ( select (each(hstore(r))).*  from (select * from pg_tables limit 1)  as r ) as z;

Nuff said

Related answer: http://stackoverflow.com/questions/11469059/postgresql-return-entire-row-as-array/11472794#11472794

Sunday, May 27, 2012

The specified Tomcat installation directory does not exist

If you encountered this error on Eclipse:

The specified Tomcat installation directory does not exist.

Check for CATALINA_HOME value on commandline. Type set on commandline, you can then see the value of CATALINA_HOME, mine is /Library/Tomcat/Home

Go to Eclipse's Preferences. Go to Server > Runtime Environments. Then click Add, then select Apache Tomcat, click Next; on Tomcat installation directory, click Browse..., then paste /Library/Tomcat/Home to the Open dialog textbox; if you are using OS X press command+shift+G first, then paste /Library/Tomcat/Home in the Go to the folder's textbox, then click Go, then click Open

Then click Finish, then click OK

You can now create Dynamic Web Project

Wednesday, May 23, 2012

Why I like Postgresql? It has first-class boolean

What would you rather read. This?

select personId
from personDailyDiet
group by personId
having count(case when fruit = 'apple' then 1 end) = count(*)


Or this?

select personId
from personDailyDiet
group by personId
having every(fruit = 'apple');

And every automatically short-circuit if it find a row that doesn't meet the condition. Not only it is readable, it is fast too.

EVERY is an alias for bool_and, you can use bool_and to make your query sounds computer-sciencey ;-)
select personId
from personDailyDiet
group by personId
having bool_and(fruit = 'apple');


It's unfortunate that ANY keyword is already taken, the bool_or could be aliased as ANY.

bool_and = EVERY
bool_or = no english-like keyword

Running total. Here and now

Moved to: http://www.ienablemuch.com/2012/05/running-total-here-and-now.html

Friday, May 18, 2012

Operator Precedence 101

#include <stdio.h>
 
int main() {
 
 
    int a = 1;
    int b = 0;
 
    // Following two statements returns the same output
    printf("\nhah %d", a != 0 & b != 0); // returns 1
    printf("\nhah %d", a != 0 && b != 0); // returns 1
 
    // Despite the common misconception that the statement 1 when written explicitly
    // is this...
    printf("\nmeh %d", (a != (0 & b)) != 0); // returns 0
    // ..., statement 1's AND(&) operator still retain the same operator precedence as its short-circuit cousin(&&)
 
 
    printf("\n");
 
    const int ALT_KEY = 2;
    int input = 1;
     
    // should return 0, it returns 0:
    printf("\nhah %d", (input & ALT_KEY) == ALT_KEY);
 
    // despite the expectation that this "should" return 0, this doesn't return 0:
    printf("\nmeh %d", input & ALT_KEY == ALT_KEY);
 
    // So it means, despite the introduction of short-circuit operator,
    // the non-short-circuit logical/bitwise operator (&,|) still retain their 
    // operator precedence.
    // Hence, the unparenthesized expression (input & ALT_KEY == ALT_KEY), when written explicitly is still evaluated as:
    printf("\nhah %d", input & (ALT_KEY == ALT_KEY) ); // returns 1
 
    // Similar with operator precedence of logical operator:
    printf("\nhah %d", input && ALT_KEY == ALT_KEY ); // returns 1
     
    // Logical operator when written explicitly
    printf("\nhah %d", input && (ALT_KEY == ALT_KEY) ); // returns 1
     
 
 
    printf("\n");
}


You might notice that I mentioned the phrase still retain two times. There was a time that there was no short-circuit operators, && and ||. Programmers uses & and | for logical expression. Despite the introduction of their short-circuit equivalent, the non-short-circuit logical/bitwise operator precedence was not changed, the non-short-circuit operators' precedence are still equivalent with the short-circuit ones.


Long before, when I'm making a DOS(hahah showing my age) program to detect a hotkey, I tried it this way first:

   if (input & ALT_KEY == ALT_KEY) {
      printf("You pressed the shortcut combo!");
   }


Expecting it to evaluate the same with arithmetic operator precedence:
   if (a + b == C) {
      printf("True true");
   }


But alas, C is not free with old cruft, it still has B-ness in it. So you must write it this way:
   if ( (input & ALT_KEY) == ALT_KEY ) {
      printf("You pressed the shortcut combo!");
   }


If the unparenthesized expression(input & ALT_KEY == ALT_KEY) is written explicitly, it is this:
   if ( input & (ALT_KEY == ALT_KEY) ) {
      printf("You pressed the shortcut combo!");
   }

Disappointing isn't it? Not symmetrical with arithmetic operator precedence.


Backward compatibility at its finest: http://cm.bell-labs.com/cm/cs/who/dmr/chist.html

Output:
hah 0
hah 0
meh 1

hah 0
meh 1
hah 1
hah 1
hah 1

See the live example: http://ideone.com/allR6

Thursday, May 17, 2012

Java said, C# said. Scope consistency

Whereas in Java, this illegal code would become legal when you move the int i = 20 before the last line, in C# it is still illegal


class TestLoop{
   public static void main(String[] args){
 

        int i = 20;                 
        
        for (int i = 0; i < 10; i++) System.out.print(i + " ");  
        for (int i = 10; i > 0; i--) System.out.print(i + " ");  


        System.out.print(i + " ");   // last line
   }
}


Moving int i = 20; after those loops that uses the same variable name i would become legal in Java; whereas in C#, it is still illegal:

class TestLoop{
   public static void main(String[] args){
 
        
        for (int i = 0; i < 10; i++) System.out.print(i + " ");  
        for (int i = 10; i > 0; i--) System.out.print(i + " ");  

        int i = 20;                 

        System.out.print(i + " ");   // last line
   }
}

Wednesday, May 16, 2012

C# said, Java said. I'm a B

Checking the type on C#

class A {}
class B : A {}
class C : B {}
class D : C {}

class TestInheritance {
    public static void Main(string[] args) { 
        object o = new C();

        if (o is B)
            System.Console.WriteLine("I'm a B");

        if (o.GetType() == typeof(B))
            System.Console.WriteLine("I'm the B");


        if (o is C)
            System.Console.WriteLine("I'm a C");

        if (o.GetType() == typeof(C))
            System.Console.WriteLine("I'm the C");

    }
}


Checking the type on Java

class A {}
class B extends A {}
class C extends B {}
class D extends C {}

class TestInheritance {
    public static void main(String[] args) { 
        Object o = new C();

        if (o instanceof B)
            System.out.println("I'm a B");

        if (o.getClass() == B.class)
            System.out.println("I'm the B");


        if (o instanceof C)
            System.out.println("I'm a C");      

        if (o.getClass() == C.class)
            System.out.println("I'm the C");

    }
}


Both languages has this output:
I'm a B
I'm a C
I'm the C

Monday, May 14, 2012

Java, moving furnitures around is a no-no. Refactoring-happy fellow be warned

class A { void m() { System.out.println("outer"); }}

public class TestInners {

 public static void main(String[] args) {
  new TestInners().go();
 }

 void go() {  
  new A().m();

  class A { void m() { System.out.println("inner"); } }  
 }

 class A { void m() { System.out.println("middle"); } }
}

You might have assumed the output is inner, since the class is in the same scope as the method. I don't know what are the Java language designers are thinking, it's more intuitive to choose the inner regardless of what line the class is declared. Java has some quirks on rules for resolving classes scope and accessibility, and this is one of those.

That code output is middle.


Move the class A at first line of go(), the output is inner:

void go() { 
 class A { void m() { System.out.println("inner"); } }  
 
 new A().m();
}

Sunday, May 13, 2012

Java said, C# said. Static nested class


Java's static nested class, is mostly used for scoping needs:

// package-level is the default, there's no keyword to explicitly say so. This is analogous to C#'s internal
class Car {

    public int i = 7;

    Car() {
        Tire t = new Tire("Goodyear");
        Tire x = new Tire("Firemint");

        x.run();
        t.run();


    }

    private static class Tire {


        // package-level is the default. package-level is analogous to C#'s internal
        private String _s;

        // package-level is the default. there's no keyword to explicitly say so
        Tire(String s) {
            _s = s;
        }

        void run() {
            System.out.println("Hello " + _s);

            // cannot access i:
            // System.out.println(i);
        }
    }
}

The equivalent in C# :

// internal is the default, no need to explicitly say so
class Car {
    public int i = 7;
    
    // private is the default, explicitly say internal. analogous to java's package-level
    internal Car() {
        
        var t = new Tire("Goodyear");
        var x = new Tire("Firemint");


        x.Run();
        t.Run();

    }
    
    
    // internal is the default, explicit say private
    private class Tire {
        // private is the default no need to explicitly say so
        string _s; 
        
        // private is the default, explicitly say internal. analogous to java's package-level
        internal Tire(string s) {
            _s = s;
        }
        
        internal void Run() {
            Console.WriteLine ("Hello " + _s);
            
            // cannot access i:
            // Console.WriteLine (i);

        }
    }
}

Friday, May 11, 2012

Accepting types from lowerbound(derived) to up(super) in Java generics

I wish Java had implemented generics first, so C# could copy this feature


import java.util.List;

import java.util.ArrayList;




public class Test {


    public static void main(String[] args) {

        // test addLot
        {
            List<Asset> assets = new ArrayList<Asset>();
            addLot(assets);

            List<Lot> lots = new ArrayList<Lot>();
            addLot(lots);

            List<CommercialLot> commercialLots = new ArrayList<CommercialLot>();
            // you cannot do this, compile-time error:
            // addLot(commercialLots);
        }

        // test addCommercialLot
        {
            List<Asset> assets = new ArrayList<Asset>();
            addCommercialLot(assets);

            List<Lot> lots = new ArrayList<Lot>();
            addCommercialLot(lots);

            List<CommercialLot> commercialLots = new ArrayList<CommercialLot>();
            addCommercialLot(commercialLots);
        }

    }

    public static void addLot(List<? super Lot> lots) {

        // you cannot do this, compile-time error:
        // lots.add(new Asset());

        // you can do this:
        lots.add(new Lot());

        // and so is this
        lots.add(new CommercialLot());

        ////////

        for(Asset a : (List<Asset>) lots) {
        }

        for(Lot l : (List<Lot>) lots) {
        }

        // you cannot do this, compile-time error:
        /*for(CommercialLot c : (List<CommercialLot>) lots) {
        } */
    }

    public static void addCommercialLot(List<? super CommercialLot> commercialLots) {

        // you cannot do this, compile-time error:
        // commercialLots.add(new Asset());

        // you cannot do this, compile-time error:
        // commercialLots.add(new Lot());

        // but of course, you can do this:
        commercialLots.add(new CommercialLot());

        ////////

        for(Asset a : (List<Asset>) commercialLots) {
        }

        for(Lot l : (List<Lot>) commercialLots) {
        }

        for(CommercialLot c : (List<CommercialLot>) commercialLots) {
        }
    }
}

class Asset {
}

class Lot extends Asset  {
}

class CommercialLot extends Lot {
}



Live test: http://ideone.com/dbgCU


The disadvantage of this approach though is it necessitates adding a new method with lowerbounded parameter whenever there's a new class that subclass the superclass. For alternative approach, read this: http://www.anicehumble.com/2012/05/c-said-java-said-oop-for-generics.html


Thursday, May 10, 2012

C# said, Java said. OOP for generics

C# said

using System.Collections.Generics;

class Program {

    public static void Main (string[] args) {
    
        IList<Animal> animals = new List<Animal>();
        AddAnimal(animals);
        foreach (Animal animal in animals) {
            Console.WriteLine (animal);
        }
    
        IList<Dog> dogs = new List<Dog>();
        AddAnimal(dogs);
        foreach (Animal animal in dogs) {
            Console.WriteLine (animal);
        }
        
    }
    
    public static void AddAnimal<T>(IList<T> animals) where T : Animal, new() {
                
        foreach(Animal a in animals) {
        }
                
        T x = new T();
        animals.Add(x);
    }   

}


class Animal {
}

class Dog : Animal {
}

class Plant {
}

Java said

import java.util.*;

public class Program {
    public static void main(String[] args) 
        throws InstantiationException, IllegalAccessException 
    {

        List<Animal> animals = new ArrayList<Animal>();
        addAnimal(animals, Animal.class);
        for (Animal animal : animals) {
            System.out.println (animal);
        }
    
        List<Dog> dogs = new ArrayList<Dog>();
        addAnimal(dogs, Dog.class);
        for (Animal animal : dogs) {
            System.out.println (animal);
        }

    }
    
    
    public static <T extends Animal> void addAnimal(
        List<T> animals, Class<T> clz)
        throws InstantiationException, IllegalAccessException
    {

        for(Animal a : animals) {
        }

        T x = clz.newInstance();
        animals.add(x);
        
    }
        
}

class Animal {
}

class Dog extends Animal {
}

class Plant {
}

The notable difference is between their instantiation of the generic's type. Whereas in C# you just say new T(), the same thing can't be done as straightforward as it be in Java. As Java generics employs type erasure, you need to explicitly pass to the function the type you want to instantiate.


The extends on our sample Java generics code is called upperbound wildcard, mostly used for getting values

The super on generics is called lowerbound wildcard, mostly used for putting values.


Though in our example, we use extends for both getting value and putting value. In order to put the value, we pass(a necessity on Java,Java erases the type of generic's parameter T) the class' type to the function.




To read something about get-put principle: http://www.ibm.com/developerworks/java/library/j-jtp07018/index.html


Another approach for using the generic on method parameter(e.g. good for collection) is to use lowerbounded generic parameters, read it at: http://www.anicehumble.com/2012/05/lowerbound-generics-in-java.html

Tuesday, May 8, 2012

C# said, Java said. Constraining generic's type

C# version:

public class InterfaceDemo {
    public static void Main(string[] args) { 
        
        Geek john = new Geek("John");
        Geek paul = new Geek("Paul");

        Hipster george = new Hipster("George");
        Hipster ringo = new Hipster("Ringo");

        var geekPersonalitiesIntroducer = new PersonalitiesIntroducer<Geek>();  
        var hipsterPersonalitiesIntroducer = new PersonalitiesIntroducer<Hipster>();

        geekPersonalitiesIntroducer.Introduce(paul,john);
        hipsterPersonalitiesIntroducer.Introduce(ringo,george);

        // won't work, you can only introduce geeks to each other.
        // error can be caught during compile-time:
        // geekPersonalitiesIntroducer.Introduce(paul,george);

        // won't work, you can only introduce hipsters to each other.
        // error can be caught during compile-time:
        // hipsterPersonalitiesIntroducer.Introduce(ringo,john);

    } 
}


interface IGreetable<T> {
    string Hello(T another);
}


class Geek : IGreetable<Geek> {

    string _name;
    public Geek(string name) {
        _name = name;
    }


    public string Hello(Geek another) {
        return "Howdy, " + another + ". I'm " + _name;
    }   


    override public string ToString() {
        return _name;
    }
}


class Hipster : IGreetable<Hipster> {
    
    string _name;
    public Hipster(string name) {
        _name = name;       
    }

    
    public string Hello(Hipster another) {
        return "Hola, " + another + ". I'm " + _name;
    }   


    override public string ToString() {
        return _name;
    }   
}


class PersonalitiesIntroducer<T> where T : IGreetable<T> {

    public void Introduce(T thisPerson, T toThatPerson) {
        
        System.Console.WriteLine(thisPerson + " meet " + toThatPerson);
        System.Console.WriteLine(thisPerson.Hello(toThatPerson));
        System.Console.WriteLine();
    }
}


Java version:

public class InterfaceDemo {
    public static void main(String[] args) {

        Geek john = new Geek("John");
        Geek paul = new Geek("Paul");

        Hipster george = new Hipster("George");
        Hipster ringo = new Hipster("Ringo");

        PersonalitiesIntroducer<Geek> geekPersonalitiesIntroducer = new PersonalitiesIntroducer<Geek>();
        PersonalitiesIntroducer<Hipster> hipsterPersonalitiesIntroducer = new PersonalitiesIntroducer<Hipster>();

        geekPersonalitiesIntroducer.introduce(paul,john);
        hipsterPersonalitiesIntroducer.introduce(ringo,george);

        // won't work, you can only introduce geeks to each other.
        // error can be caught during compile-time:
        // geekPersonalitiesIntroducer.introduce(paul,george);

        // won't work, you can only introduce hipsters to each other.
        // error can be caught during compile-time:
        // hipsterPersonalitiesIntroducer.introduce(ringo,paul);

    }
}


interface Greetable<T> {
    String hello(T another);
}


class Geek implements Greetable<Geek> {

    String _name;
    public Geek(String name) {
        _name = name;
    }


    public String hello(Geek another) {
        return "Howdy, " + another + ". I'm " + _name;
    }


    @Override public String toString() {
        return _name;
    }
}


class Hipster implements Greetable<Hipster> {

    String _name;
    public Hipster(String name) {
        _name = name;
    }


    public String hello(Hipster another) {
        return "Hola, " + another + ". I'm " + _name;
    }


    @Override public String toString() {
        return _name;
    }
}


class PersonalitiesIntroducer<T extends Greetable<T>> {

    public void introduce(T fromPerson, T toAnotherPerson) {

        System.out.println(fromPerson + " meet " + toAnotherPerson);
        System.out.println(fromPerson.hello(toAnotherPerson));
        System.out.println();
    }
}

Output:

Paul meet John
Howdy, John. I'm Paul

Ringo meet George
Hola, George. I'm Ringo

The only part where Java and C# significantly differs(if at all) in these codes are in constraining the generic's type.

Contrast C#'s code:

class PersonalitiesIntroducer<T> where T : IGreetable<T> {

    public void Introduce(T thisPerson, T toThatPerson) {
  
        System.Console.WriteLine(thisPerson + " meet " + toThatPerson);
        System.Console.WriteLine(thisPerson.Hello(toThatPerson));
        System.Console.WriteLine();
    }
}

To Java's code:

class PersonalitiesIntroducer<T extends Greetable<T>> {

    public void introduce(T fromPerson, T toAnotherPerson) {

        System.out.println(fromPerson + " meet " + toAnotherPerson);
        System.out.println(fromPerson.hello(toAnotherPerson));
        System.out.println();
     }
}


C#'s syntax for constraining the generic type has more affinity with how the generics-using class will be used(instantiated). So you say in C# (and Java too):

PersonalitiesIntroducer<Geek> pi = new PersonalitiesIntroducer<Geek>(); // same syntax on both Java and C
// In C#, you can shorten it to:
var pi = new PersonalitiesIntroducer<Geek>(); 
// In Java 7, you can shorten it to:
PersonalitiesIntroducer<Geek> pi = new PersonalitiesIntroducer<>();

Though in Java, the class declaration is like this:
class PersonalitiesIntroducer<T extends Greetable<T>> 

You will not say in Java:
PersonalitiesIntroducer<Geek extends Greetable<Geek>> pi = new PersonalitiesIntroducer<Geek extends Greetable<Geek>>();

In Java, you instantiate generics the same way as C#.

Minor syntactic differences aside, C# and Java are very similar. You could even replace the Java code in movie Independence Day with C# and people won't even notice it

C# said, Java said: Generic instantiation

C# said

public class GenericDemo {
    public static void Main(string[] args) {
        First f = Everybody.Want<First>();
        System.Console.WriteLine(f);
    }
}


class Everybody {
    public static T Want<T>() where T : new() {
        return new T();
    }
}


class First {
 override public string ToString() {
  return "Hello";
 }
}

Java said

public class GenericDemo {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException  {
       First f = Person.Wants(First.class);
       System.out.println(f);
    }
}


class Person {
    public static <T> T Wants(Class<T> t) throws IllegalAccessException, InstantiationException {
        return t.newInstance();
    }
}


class First {
 @Override public String toString() {
  return "Hello";
 }
}

Capping negative numbers to zero

select 
   ( col1 + abs(col1) ) / 2 as capped_to_zero
from tbl

is faster than:


select 
   case when col1 >= 0 then col1 else 0 end as capped_to_zero
from tbl


Monday, May 7, 2012

Java generic type erasure advantages and disadvantages

Java's type erasure on its generics allows the components produced on generics-using JVM be instantly available on non-generics JVM


An example, let's say we have a Greetable interface

interface Greetable<T> {
   String hello(T another);
}

On non-generics-capable Java, e.g. developers using JVM 1.4 or earlier, shall see Greetable's hello method's parameter as:



Type erasure has some problems though. Let's say you have two classes Geek and Hipster that implements the same interface, yet they can be friendly only among their own kind, this is where type erasure can be a problem. Read on.


class Hipster implements Greetable<Hipster>
{
    String _name;

    Hipster(String name) {
        _name = name;
    }

    @Override
    public String toString() {
        return _name;
    }

    @Override
    public String hello(Hipster another) {
        return "Hi I'm " + _name + ", hola mi amigo " + another + "!";
    }

}

class Geek implements  Greetable<Geek>
{
    String _name;

    Geek(String name) {
        _name = name;
    }

    @Override
    public String toString() {
        return _name;
    }

    @Override
    public String hello(Geek another) {
        return "Hi I'm " + _name + ", charie " + another + "!";
    }
}

You can see that both of them implements method hello, yet their accepted parameter is confined only to their own kind. This is where generics shine, error(type mismatches) can be caught during compile-time, not when it is costly to fix an error(during runtime)

Given this:

Hipster george = new Hipster("George");
Geek paul = new Geek("Paul");


Then you do this:
george.hello(paul); // compile error

That will not be allowed by the compiler, that will result to compile-time error. You use generics if you want to enforce types compatibility. Compiler can catch this error

// this is allowed. Hipster is derived from Greetable
Greetable<hipster> george = new Hipster("Pete"); 


Geek paul = new Geek("Paul");


// but this will not be allowed.
george.hello(paul); 


george.hello method signature is hello(Hipster another);. Paul is not a Hipster, he's a Geek, hence the compiler can catch that Paul doesn't matched George's friend preference of Hipster.


With type erasure, type mismatches are not caught by the compiler:


// this is allowed. Hipster is derived from Greetable
Greetable george = new Hipster("George"); 

george.hello(paul); // this will be allowed by the compiler. yet this will throw an exception during runtime

With type erasure, the type on george's hello method became an untyped one, it has method signature of hello(Object another). This has the consequence of the compiler not being able to catch type mismatches for you, hence the type incompatibility just arises during runtime only, the runtime will throw an exception; which is bad, it's better to fix errors earlier.

Thursday, May 3, 2012

SQL COUNT: A Computer Program Does What You Tell It To Do, Not What You Want It To Do

Given this data:

test=# select * from ios_app order by app_code, date_released;
.ios_app_id | app_code | date_released | price  
------------+----------+---------------+--------
          1 | AB       | 2010-01-01    | 1.0000
          3 | AB       | 2010-01-03    | 3.0000
          4 | AB       | 2010-01-04    | 4.0000
          2 | TR       | 2010-01-02    | 2.0000
          5 | TR       | 2010-01-05    | 5.0000
(5 rows)

And this data:
test=# select * from android_app order by app_code, date_released;
.android_app_id | app_code | date_released |  price  
----------------+----------+---------------+---------
              1 | AB       | 2010-01-06    |  6.0000
              2 | AB       | 2010-01-07    |  7.0000
              7 | MK       | 2010-01-07    |  7.0000
              3 | TR       | 2010-01-08    |  8.0000
              4 | TR       | 2010-01-09    |  9.0000
              5 | TR       | 2010-01-10    | 10.0000
              6 | TR       | 2010-01-11    | 11.0000
(7 rows)

I made this query...

select x.app_code, 
 count(i.date_released) as ios_release_count, 
 count(a.date_released) as android_release_count
from app x
left join ios_app i on i.app_code = x.app_code
left join android_app a on a.app_code = x.app_code
group by x.app_code
order by x.app_code


...and I wanted that to display this...

.app_code | ios_release_count | android_release_count 
----------+-------------------+-----------------------
 AB       |                 3 |                     2
 MK       |                 0 |                     1
 PM       |                 0 |                     0
 TR       |                 2 |                     4
(4 rows)


...but why it displays this?

.app_code | ios_release_count | android_release_count 
----------+-------------------+-----------------------
 AB       |                 6 |                     6
 MK       |                 0 |                     1
 PM       |                 0 |                     0
 TR       |                 8 |                     8
(4 rows)


Why ios_release_count says 6 when it should be 3 instead?

The same with TR, why its ios_release_count displays 8 when it should be 2 instead?

Do you notice something? The incorrect result 6 on your query is a multiplication of ios_release_count of 3 and android_release_count of 2. Likewise with result 8 on your query, it is a multiplication of ios_release_count of 2 and android_release_count of 4.


To visualize, try to remove the grouping and count aggregation on your query...

select x.app_code, i.date_released as ios_release_date, a.date_released as android_release_date
from app x
left join ios_app i on i.app_code = x.app_code
left join android_app a on a.app_code = x.app_code
order by x.app_code, ios_release_date, android_release_date;


This will be the results of your query:


.app_code | ios_release_date | android_release_date 
----------+------------------+----------------------
 AB       | 2010-01-01       | 2010-01-06
 AB       | 2010-01-01       | 2010-01-07
 AB       | 2010-01-03       | 2010-01-06
 AB       | 2010-01-03       | 2010-01-07
 AB       | 2010-01-04       | 2010-01-06
 AB       | 2010-01-04       | 2010-01-07
 MK       |                  | 2010-01-07
 PM       |                  | 
 TR       | 2010-01-02       | 2010-01-08
 TR       | 2010-01-02       | 2010-01-09
 TR       | 2010-01-02       | 2010-01-10
 TR       | 2010-01-02       | 2010-01-11
 TR       | 2010-01-05       | 2010-01-08
 TR       | 2010-01-05       | 2010-01-09
 TR       | 2010-01-05       | 2010-01-10
 TR       | 2010-01-05       | 2010-01-11
(16 rows)


You notice something? the ios_release_date keeps on repeating. The reason why? For every AB row, it get paired with two rows on android. How many rows are there in AB? Three, right? So when you multiply three by two, you get 6, so that's where the count of 6 comes from! Likewise for every TR row in ios, there's four rows on android; there are two TR rows in ios. You multiply two by four, you get 8!


So it's time to correct the query.

With the advent of CTE, flattening the results is way neater and you can give them their own name; afterwards, you can join them to the master table:

with ios_app_release_count_list as
(
 select app_code, count(date_released) as ios_release_count
 from ios_app
 group by app_code
)
,android_release_count_list as
(
 select app_code, count(date_released) as android_release_count 
 from android_app 
 group by app_code  
)
select 
 x.app_code, 
 coalesce(i.ios_release_count,0) as ios_release_count, 
 coalesce(a.android_release_count,0) as android_release_count
from app x
left join ios_app_release_count_list i on i.app_code = x.app_code
left join android_release_count_list a on a.app_code = x.app_code
order by x.app_code;

Here's the output for that:

.app_code | ios_release_count | android_release_count 
----------+-------------------+-----------------------
 AB       |                 3 |                     2
 MK       |                 0 |                     1
 PM       |                 0 |                     0
 TR       |                 2 |                     4
(4 rows)

It's already correct, isn't it?


CTE lets you divide-and-conquer the problem pretty well, make a query of something, make a good name for it, then join it to master table.

So with absence of CTE, this is how your query shall be written like:

select x.app_code, 
 coalesce(i.ios_release_count,0) as ios_release_count, 
 coalesce(a.android_release_count,0) as android_release_count
from app x
left join
(
 select app_code, count(date_released) as ios_release_count
 from ios_app
 group by app_code
) i on i.app_code = x.app_code
left join
(
 select app_code, count(date_released) as android_release_count 
 from android_app 
 group by app_code   
) a on a.app_code = x.app_code
order by x.app_code

It's not as intuitive and neat as the CTE approach. Nevertheless, it works!