Some /very minor and inconclusive/ testing shows that simply changing that field to a date (and doing /nothing else/, such as changing the fm_IDL.xml) MIGHT be enough to squash this forever. HOWEVER, lots of testing would be required, and it may be that we will, indeed, need to teach lots of other parts of the system about the DATE type. That, of course, is the most correct solution, and the source of the above referenced "good bit of development work" that Michael Peters pasted from ESI's internal support system.
To wit:
# select '2011-09-01 12:44:16.602564-04'::date;
date
------------
2011-09-01
(1 row)
This shows that we should be able to pass a timestamptz to Postgres and it will cast appropriately. I have not tested the other direction (in particular, cstore, which uses libdbd-pg to do some timezone mangling), though.
Someone wanting to test this could issue something along the lines of:
BEGIN;
DROP VIEW action.all_circulation;
DROP VIEW reporter.demographic;
DROP VIEW auditor.actor_usr_lifecycle;
ALTER TABLE actor.usr ALTER dob TYPE date USING dob::date;
CREATE VIEW reporter.demographic AS
SELECT u.id, u.dob,
CASE
WHEN u.dob IS NULL THEN 'Adult'::text
WHEN age(u.dob) > '18 years'::interval THEN 'Adult'::text
ELSE 'Juvenile'::text
END AS general_division
FROM actor.usr u;
CREATE VIEW action.all_circulation AS
SELECT aged_circulation.id, aged_circulation.usr_post_code, aged_circulation.usr_home_ou, aged_circulation.usr_profile, aged_circulation.usr_birth_year, aged_circulation.copy_call_number, aged_circulation.copy_location, aged_circulation.copy_owning_lib, aged_circulation.copy_circ_lib, aged_circulation.copy_bib_record, aged_circulation.xact_start, aged_circulation.xact_finish, aged_circulation.target_copy, aged_circulation.circ_lib, aged_circulation.circ_staff, aged_circulation.checkin_staff, aged_circulation.checkin_lib, aged_circulation.renewal_remaining, aged_circulation.grace_period, aged_circulation.due_date, aged_circulation.stop_fines_time, aged_circulation.checkin_time, aged_circulation.create_time, aged_circulation.duration, aged_circulation.fine_interval, aged_circulation.recurring_fine, aged_circulation.max_fine, aged_circulation.phone_renewal, aged_circulation.desk_renewal, aged_circulation.opac_renewal, aged_circulation.duration_rule, aged_circulation.recurring_fine_rule, aged_circulation.max_fine_rule, aged_circulation.stop_fines, aged_circulation.workstation, aged_circulation.checkin_workstation, aged_circulation.checkin_scan_time, aged_circulation.parent_circ
FROM action.aged_circulation
UNION ALL
SELECT DISTINCT circ.id, COALESCE(a.post_code, b.post_code) AS usr_post_code, p.home_ou AS usr_home_ou, p.profile AS usr_profile, date_part('year'::text, p.dob)::integer AS usr_birth_year, cp.call_number AS copy_call_number, cp.location AS copy_location, cn.owning_lib AS copy_owning_lib, cp.circ_lib AS copy_circ_lib, cn.record AS copy_bib_record, circ.xact_start, circ.xact_finish, circ.target_copy, circ.circ_lib, circ.circ_staff, circ.checkin_staff, circ.checkin_lib, circ.renewal_remaining, circ.grace_period, circ.due_date, circ.stop_fines_time, circ.checkin_time, circ.create_time, circ.duration, circ.fine_interval, circ.recurring_fine, circ.max_fine, circ.phone_renewal, circ.desk_renewal, circ.opac_renewal, circ.duration_rule, circ.recurring_fine_rule, circ.max_fine_rule, circ.stop_fines, circ.workstation, circ.checkin_workstation, circ.checkin_scan_time, circ.parent_circ
FROM action.circulation circ
JOIN asset.copy cp ON circ.target_copy = cp.id
JOIN asset.call_number cn ON cp.call_number = cn.id
JOIN actor.usr p ON circ.usr = p.id
LEFT JOIN actor.usr_address a ON p.mailing_address = a.id
LEFT JOIN actor.usr_address b ON p.billing_address = b.id;
Some /very minor and inconclusive/ testing shows that simply changing that field to a date (and doing /nothing else/, such as changing the fm_IDL.xml) MIGHT be enough to squash this forever. HOWEVER, lots of testing would be required, and it may be that we will, indeed, need to teach lots of other parts of the system about the DATE type. That, of course, is the most correct solution, and the source of the above referenced "good bit of development work" that Michael Peters pasted from ESI's internal support system.
To wit:
# select '2011-09-01 12:44:16. 602564- 04'::date;
date
------------
2011-09-01
(1 row)
This shows that we should be able to pass a timestamptz to Postgres and it will cast appropriately. I have not tested the other direction (in particular, cstore, which uses libdbd-pg to do some timezone mangling), though.
Someone wanting to test this could issue something along the lines of:
BEGIN;
DROP VIEW action. all_circulation ; demographic; actor_usr_ lifecycle;
DROP VIEW reporter.
DROP VIEW auditor.
ALTER TABLE actor.usr ALTER dob TYPE date USING dob::date;
CREATE VIEW auditor. actor_usr_ lifecycle AS access_ level, usr.photo_url, usr.prefix, usr.first_ given_name, usr.second_ given_name, usr.family_name, usr.suffix, usr.alias, usr.day_phone, usr.evening_phone, usr.other_phone, usr.mailing_ address, usr.billing_ address, usr.home_ou, usr.dob, usr.active, usr.master_account, usr.super_user, usr.barred, usr.deleted, usr.juvenile, usr.usrgroup, usr.claims_ returned_ count, usr.credit_ forward_ balance, usr.last_xact_id, usr.alert_message, usr.create_date, usr.expire_date, usr.claims_ never_checked_ out_count history. audit_id AS "?column?", actor_usr_ history. audit_time, actor_usr_ history. audit_action, actor_usr_ history. id, actor_usr_ history. card, actor_usr_ history. profile, actor_usr_ history. usrname, actor_usr_ history. email, actor_usr_ history. passwd, actor_usr_ history. standing, actor_usr_ history. ident_type, actor_usr_ history. ident_value, actor_usr_ history. ident_type2, actor_usr_ history. ident_value2, actor_usr_ history. net_access_ level, actor_usr_ history. photo_url, actor_usr_ history. prefix, actor_usr_ history. first_given_ name, actor_usr_ history. second_ given_name, actor_usr_ history. family_ name, actor_usr_ history. suffix, actor_usr_ history. alias, actor_usr_ history. day_phone, actor_usr_ history. evening_ phone, actor_usr_ history. other_phone, actor_usr_ history. mailing_ address, actor_usr_ history. billing_ address, actor_usr_ history. home_ou, actor_usr_ history. dob, actor_usr_ history. active, actor_usr_ history. master_ account, actor_usr_ history. super_user, actor_usr_ history. barred, actor_usr_ history. deleted, actor_usr_ history. juvenile, actor_usr_ history. usrgroup, actor_usr_ history. claims_ returned_ count, actor_usr_ history. credit_ forward_ balance, actor_usr_ history. last_xact_ id, actor_usr_ history. alert_message, actor_usr_ history. create_ date, actor_usr_ history. expire_ date, actor_usr_ history. claims_ never_checked_ out_count actor_usr_ history;
SELECT (-1), now() AS audit_time, '-' AS audit_action, usr.id, usr.card, usr.profile, usr.usrname, usr.email, usr.passwd, usr.standing, usr.ident_type, usr.ident_value, usr.ident_type2, usr.ident_value2, usr.net_
FROM actor.usr
UNION ALL
SELECT actor_usr_
FROM auditor.
CREATE VIEW reporter. demographic AS
SELECT u.id, u.dob,
CASE
WHEN u.dob IS NULL THEN 'Adult'::text
WHEN age(u.dob) > '18 years'::interval THEN 'Adult'::text
ELSE 'Juvenile'::text
END AS general_division
FROM actor.usr u;
CREATE VIEW action. all_circulation AS n.id, aged_circulatio n.usr_post_ code, aged_circulatio n.usr_home_ ou, aged_circulatio n.usr_profile, aged_circulatio n.usr_birth_ year, aged_circulatio n.copy_ call_number, aged_circulatio n.copy_ location, aged_circulatio n.copy_ owning_ lib, aged_circulatio n.copy_ circ_lib, aged_circulatio n.copy_ bib_record, aged_circulatio n.xact_ start, aged_circulatio n.xact_ finish, aged_circulatio n.target_ copy, aged_circulatio n.circ_ lib, aged_circulatio n.circ_ staff, aged_circulatio n.checkin_ staff, aged_circulatio n.checkin_ lib, aged_circulatio n.renewal_ remaining, aged_circulatio n.grace_ period, aged_circulatio n.due_date, aged_circulatio n.stop_ fines_time, aged_circulatio n.checkin_ time, aged_circulatio n.create_ time, aged_circulatio n.duration, aged_circulatio n.fine_ interval, aged_circulatio n.recurring_ fine, aged_circulatio n.max_fine, aged_circulatio n.phone_ renewal, aged_circulatio n.desk_ renewal, aged_circulatio n.opac_ renewal, aged_circulatio n.duration_ rule, aged_circulatio n.recurring_ fine_rule, aged_circulatio n.max_fine_ rule, aged_circulatio n.stop_ fines, aged_circulatio n.workstation, aged_circulatio n.checkin_ workstation, aged_circulatio n.checkin_ scan_time, aged_circulatio n.parent_ circ aged_circulatio n a.post_ code, b.post_code) AS usr_post_code, p.home_ou AS usr_home_ou, p.profile AS usr_profile, date_part( 'year': :text, p.dob)::integer AS usr_birth_year, cp.call_number AS copy_call_number, cp.location AS copy_location, cn.owning_lib AS copy_owning_lib, cp.circ_lib AS copy_circ_lib, cn.record AS copy_bib_record, circ.xact_start, circ.xact_finish, circ.target_copy, circ.circ_lib, circ.circ_staff, circ.checkin_staff, circ.checkin_lib, circ.renewal_ remaining, circ.grace_period, circ.due_date, circ.stop_ fines_time, circ.checkin_time, circ.create_time, circ.duration, circ.fine_interval, circ.recurring_ fine, circ.max_fine, circ.phone_renewal, circ.desk_renewal, circ.opac_renewal, circ.duration_rule, circ.recurring_ fine_rule, circ.max_fine_rule, circ.stop_fines, circ.workstation, circ.checkin_ workstation, circ.checkin_ scan_time, circ.parent_circ
SELECT aged_circulatio
FROM action.
UNION ALL
SELECT DISTINCT circ.id, COALESCE(
FROM action.circulation circ
JOIN asset.copy cp ON circ.target_copy = cp.id
JOIN asset.call_number cn ON cp.call_number = cn.id
JOIN actor.usr p ON circ.usr = p.id
LEFT JOIN actor.usr_address a ON p.mailing_address = a.id
LEFT JOIN actor.usr_address b ON p.billing_address = b.id;
COMMIT;