Error in Include(/www/htdocs/nge/dispatcher.html):
Required data was not found. primary_key => undef criteria => lower(regexp_replace(description, '[^a-zA-Z]', '', 'g')) = ? at /www/lib/perl/OmniTI/Class/TableBacked.pm line 1399
[ 1] 1: =head1 NAME
[ 2] 2:
[ 3] 3: OmniTI::Exception - OO Exceptions
[ 4] 4:
[ 5] 5: =head1 SYNOPSIS
[ 6] 6:
[ 7] 7: use OmniTI::Exception;
[ 8] 8:
[ 9] 9: # In API code:
[ 10] 10:
[ 11] 11: # dies locally
[ 12] 12: OmniTI::Exception::Params::Missing->throw(param => 'id');
[ 13] 13:
[ 14] 14: # dies from caller's perspective
[ 15] 15: OmniTI::Exception::Params::Missing->croak(param => 'id');
[ 16] 16:
[ 17] 17: # dies from caller's caller's perspective
[ 18] 18: OmniTI::Exception::Params::Missing->croak(param => 'id', frames => 2);
[ 19] 19:
[ 20] 20: # To catch:
[ 21] 21: eval { something_dangerous(); }
[ 22] 22: if (my $e = OmniTI::Exception::Params::Missing->caught()) {
[ 23] 23: my $p = $e->param(); # Find out what was missing
[ 24] 24: print $e; # Stringifies nicely
[ 25] 25: } else {
[ 26] 26: die $@; # Pass on unrecognized exceptions
[ 27] 27: }
[ 28] 28:
[ 29] 29: # Special handler included for working with OmniTI::DB connections....
[ 30] 30: my $dbh = NatGeo::DB::Magazine->new();
[ 31] 31: $dbh->set_handle_error(OmniTI::Exception->make_db_error_handler());
[ 32] 32:
[ 33] 33:
[ 34] 34: =head1 DESCRIPTION
[ 35] 35:
[ 36] 36: Uses Exception::Class to define a wide variety of exceptions.
[ 37] 37:
[ 38] 38: =head1 STRINGIFICATION
[ 39] 39:
[ 40] 40: Any extra fields defined for a particular exception
[ 41] 41: class will be included in the stringification of
[ 42] 42: the exception, like this:
[ 43] 43:
[ 44] 44: Error message
[ 45] 45: field1 => value1
[ 46] 46: field2 => value2
[ 47] 47:
[ 48] 48: =head1 EXCEPTIONS
[ 49] 49:
[ 50] 50: =over
[ 51] 51:
[ 52] 52: =item OmniTI::Exception::Param
[ 53] 53:
[ 54] 54: Exceptions related to parameter passing. Expect fields 'param'.
[ 55] 55:
[ 56] 56: =over
[ 57] 57:
[ 58] 58: =item OmniTI::Exception::Param::Missing
[ 59] 59:
[ 60] 60: =item OmniTI::Exception::Param::Empty
[ 61] 61:
[ 62] 62: An array or hash ref turned out to be present but empty.
[ 63] 63:
[ 64] 64: =item OmniTI::Exception::Param::ExpectedHash
[ 65] 65:
[ 66] 66: Thrown when the method uses named parameters, but an odd number of parameters were provided. param field is not used.
[ 67] 67:
[ 68] 68: =item OmniTI::Exception::Param::ExpectedHashRef
[ 69] 69:
[ 70] 70: =item OmniTI::Exception::Param::ExpectedArrayRef
[ 71] 71:
[ 72] 72: =item OmniTI::Exception::Param::ExpectedHashref
[ 73] 73:
[ 74] 74: =item OmniTI::Exception::Param::MutuallyExclusive
[ 75] 75:
[ 76] 76: Used when two parameters cannot both be present. Use fields 'param' and 'other_param'.
[ 77] 77:
[ 78] 78: =item OmniTI::Exception::Param::Duplicate
[ 79] 79:
[ 80] 80: Thrown when the same named parameter is used more than once.
[ 81] 81:
[ 82] 82: =back
[ 83] 83:
[ 84] 84: =back
[ 85] 85:
[ 86] 86:
[ 87] 87: =head1 AUTHOR
[ 88] 88:
[ 89] 89: Clinton Wolfe
[ 90] 90:
[ 91] 91: =cut
[ 92] 92:
[ 93] 93: package OmniTI::Exception;
[ 94] 94: use strict;
[ 95] 95: our $DEBUG = 0;
[ 96] 96: use Data::Dumper;
[ 97] 97:
[ 98] 98:
[ 99] 99: our @ISA = ('Exception::Class::Base');
[ 100] 100:
[ 101] 101: sub full_message {
[ 102] 102: my $self = shift;
[ 103] 103: my @field_names = $self->Fields();
[ 104] 104: my $msg = $self->message . "\n"; # Automatic newline?
[ 105] 105: $msg .= ($self->description . "\n") || '';
[ 106] 106: foreach my $field (@field_names) {
[ 107] 107: my $val = $self->$field;
[ 108] 108: $msg .= "\t$field => " . (defined($val) ? $val : 'undef') . "\n";
[ 109] 109: }
[ 110] 110:
[ 111] 111: # Include filename and file
[ 112] 112: #print STDERR "In full_message, have frame count " . $self->trace->frame_count . "\n";
[ 113] 113: my $frame = $self->trace->frame(0);
[ 114] 114: $msg .= " at " . $frame->filename . " line " . $frame->line . "\n";
[ 115] 115:
[ 116] 116: return $msg;
[ 117] 117: }
[ 118] 118:
[ 119] 119: sub croak {
[ 120] 120: my $class = shift;
[ 121] 121: my %args;
[ 122] 122:
[ 123] 123: # Behave like throw: if one arg, it's the message.
[ 124] 124: if (@_ == 1) {
[ 125] 125: %args = (message => shift());
[ 126] 126: } else {
[ 127] 127: %args = @_;
[ 128] 128: }
[ 129] 129:
[ 130] 130: my $frame_count = defined($args{frames}) ? $args{frames} : 1;
[ 131] 131: delete $args{frames};
[ 132] 132:
[ 133] 133: my $self = $class->new(%args);
[ 134] 134:
[ 135] 135: my @frames = @{$self->{trace}->{frames}};
[ 136] 136: #print STDERR "In croak, have orginal frame count " . (scalar @frames) . "\n";
[ 137] 137: my @dropped_frames = splice @frames, 0, $frame_count; # Delete $frame_count frames from the top (nearest) end of the stack.
[ 138] 138: $self->{trace}->{frames} = \@frames;
[ 139] 139: #print STDERR "In croak, have final frame count " . (scalar @frames) . "\n";
[ 140] 140:
[ 141] 141: if ($DEBUG > 1) {
[ 142] 142: print STDERR __PACKAGE__ . ':' . __FILE__ . " - Have dropped frames:\n";
[ 143] 143: for (@dropped_frames) {
[ 144] 144: print "\t" . $_->filename . ':' . $_->line . "\n";
[ 145] 145: }
[ 146] 146: }
[ 147] 147:
[* 148] 148: die $self;
[ 149] 149: }
[ 150] 150:
[ 151] 151: # Returns a coderef suitable for setting the DBI HandleError attribute.
[ 152] 152: sub make_db_error_handler {
[ 153] 153: my $class = shift;
[ 154] 154: my $code = sub {
[ 155] 155: my $errstr = shift;
[ 156] 156: my $dbh = shift;
[ 157] 157: my $bind_msg = '(in PREPARE stage)';
[ 158] 158: if ($dbh->{ParamValues}) {
[ 159] 159: my %binds = %{$dbh->{ParamValues}};
[ 160] 160: if ($DEBUG) { print STDERR __PACKAGE__ . ':' . __LINE__ . "In DB error handler, have binds:\n" . Dumper(\%binds); }
[ 161] 161: $bind_msg = join ', ', map { $_ . ':' . (defined($binds{$_}) ? $binds{$_} : 'undef') } keys %binds;
[ 162] 162: }
[ 163] 163: OmniTI::Exception::Data::SqlError->croak(
[ 164] 164: frames => 1,
[ 165] 165: error => $errstr,
[ 166] 166: statement => $dbh->{Statement},
[ 167] 167: bind_values => $bind_msg,
[ 168] 168: );
[ 169] 169: }
[ 170] 170: }
[ 171] 171:
[ 172] 172:
[ 173] 173: package main;
[ 174] 174:
[ 175] 175: # Note: this should follow the definition of OmniTI::Exception
[ 176] 176: use Exception::Class
[ 177] 177: (
[ 178] 178:
[ 179] 179: # Coding
[ 180] 180: 'OmniTI::Exception::NotImplemented' =>
[ 181] 181: {
[ 182] 182: isa => 'OmniTI::Exception',
[ 183] 183: description => 'The code that is being attempted to execute has not yet been written.',
[ 184] 184: },
[ 185] 185: 'OmniTI::Exception::CannotLoadClass' =>
[ 186] 186: {
[ 187] 187: isa => 'OmniTI::Exception',
[ 188] 188: description => 'The requested class cannot be loaded.',
[ 189] 189: fields => [qw(class)],
[ 190] 190: },
[ 191] 191:
[ 192] 192:
[ 193] 193:
[ 194] 194: # Param handling
[ 195] 195: 'OmniTI::Exception::Param' =>
[ 196] 196: {
[ 197] 197: isa => 'OmniTI::Exception',
[ 198] 198: description => 'A general parameter error',
[ 199] 199: fields => [ qw(param value) ],
[ 200] 200: },
[ 201] 201:
[ 202] 202: 'OmniTI::Exception::Param::Missing' =>
[ 203] 203: {
[ 204] 204: isa => 'OmniTI::Exception::Param',
[ 205] 205: description => 'A required parameter is missing. The required parameter is listed in the param field.',
[ 206] 206: },
[ 207] 207:
[ 208] 208: 'OmniTI::Exception::Param::BadValue' =>
[ 209] 209: {
[ 210] 210: isa => 'OmniTI::Exception::Param',
[ 211] 211: description => 'A parameter has an invalid value.',
[ 212] 212: },
[ 213] 213:
[ 214] 214: 'OmniTI::Exception::Param::ExpectedHash' =>
[ 215] 215: {
[ 216] 216: isa => 'OmniTI::Exception::Param',
[ 217] 217: description => 'The method or subroutine expected to be called with named paramters, but an odd number of parameters were passed.',
[ 218] 218: },
[ 219] 219:
[ 220] 220: 'OmniTI::Exception::Param::ExpectedArrayRef' =>
[ 221] 221: {
[ 222] 222: isa => 'OmniTI::Exception::Param',
[ 223] 223: description => 'A parameter was expected to be an array ref, but was not. The parameter is listed in the param field.',
[ 224] 224: },
[ 225] 225:
[ 226] 226: 'OmniTI::Exception::Param::ExpectedHashRef' =>
[ 227] 227: {
[ 228] 228: isa => 'OmniTI::Exception::Param',
[ 229] 229: description => 'A parameter was expected to be an hash ref, but was not. The parameter is listed in the param field.',
[ 230] 230: },
[ 231] 231:
[ 232] 232: 'OmniTI::Exception::Param::WrongType' =>
[ 233] 233: {
[ 234] 234: isa => 'OmniTI::Exception::Param',
[ 235] 235: description => 'A parameter is of the wrong type. ',
[ 236] 236: fields => [ qw(param expected) ],
[ 237] 237: },
[ 238] 238:
[ 239] 239: 'OmniTI::Exception::Param::MutuallyExclusive' =>
[ 240] 240: {
[ 241] 241: isa => 'OmniTI::Exception::Param',
[ 242] 242: description => 'You may only provide or or the other of a pair of parameters, but you provided both. The parameters are listed in the param and other_param field.',
[ 243] 243: fields => [ qw(param other_param) ],
[ 244] 244: },
[ 245] 245:
[ 246] 246: 'OmniTI::Exception::Param::Duplicate' =>
[ 247] 247: {
[ 248] 248: isa => 'OmniTI::Exception::Param',
[ 249] 249: description => 'You specified the same parameter more than once in a list, when unique values are required.',
[ 250] 250: },
[ 251] 251: 'OmniTI::Exception::Param::Spurious' =>
[ 252] 252: {
[ 253] 253: isa => 'OmniTI::Exception::Param',
[ 254] 254: description => 'You provided extra, unrecognized parameters.',
[ 255] 255: },
[ 256] 256:
[ 257] 257:
[ 258] 258:
[ 259] 259: # Other function calling problems
[ 260] 260: 'OmniTI::Exception::Call' =>
[ 261] 261: {
[ 262] 262: isa => 'OmniTI::Exception',
[ 263] 263: description => 'A general error in function/method calling style',
[ 264] 264: },
[ 265] 265:
[ 266] 266: 'OmniTI::Exception::Call::NotMutator' =>
[ 267] 267: {
[ 268] 268: isa => 'OmniTI::Exception::Call',
[ 269] 269: description => 'You may not use this function to set a value.',
[ 270] 270: fields => [ qw(attribute) ],
[ 271] 271: },
[ 272] 272:
[ 273] 273: 'OmniTI::Exception::Call::NotPermitted' =>
[ 274] 274: {
[ 275] 275: isa => 'OmniTI::Exception::Call',
[ 276] 276: description => 'You may not call this method.',
[ 277] 277: },
[ 278] 278:
[ 279] 279: 'OmniTI::Exception::Call::Deprecated' =>
[ 280] 280: {
[ 281] 281: isa => 'OmniTI::Exception::Call',
[ 282] 282: description => 'You may not call this method, because it is no longer supported.',
[ 283] 283: },
[ 284] 284:
[ 285] 285: 'OmniTI::Exception::Call::PureVirtual' =>
[ 286] 286: {
[ 287] 287: isa => 'OmniTI::Exception::Call',
[ 288] 288: description => 'This method may not be called directly, because a subclass is supposed to provide its own implementation.',
[ 289] 289: },
[ 290] 290:
[ 291] 291: 'OmniTI::Exception::Call::NoSuchMethod' =>
[ 292] 292: {
[ 293] 293: isa => 'OmniTI::Exception::Call',
[ 294] 294: description => 'You tried to use a method that does not exist. This usually means the module does not know how to AUTOLOAD the requested method.',
[ 295] 295: },
[ 296] 296:
[ 297] 297:
[ 298] 298: # Database problems
[ 299] 299: 'OmniTI::Exception::Data' =>
[ 300] 300: {
[ 301] 301: isa => 'OmniTI::Exception',
[ 302] 302: description => 'A general data-related error.',
[ 303] 303: fields => [ qw(primary_key) ],
[ 304] 304: },
[ 305] 305:
[ 306] 306: 'OmniTI::Exception::Data::NotFound' =>
[ 307] 307: {
[ 308] 308: isa => 'OmniTI::Exception::Data',
[ 309] 309: description => 'Required data was not found.',
[ 310] 310: fields => [ qw(criteria) ],
[ 311] 311: },
[ 312] 312:
[ 313] 313: 'OmniTI::Exception::Data::AlreadyInserted' =>
[ 314] 314: {
[ 315] 315: isa => 'OmniTI::Exception::Data',
[ 316] 316: description => 'A data object is marked as already existing in the database, but you just tried to insert it again.',
[ 317] 317: },
[ 318] 318: 'OmniTI::Exception::Data::DependsOnInsert' =>
[ 319] 319: {
[ 320] 320: isa => 'OmniTI::Exception::Data',
[ 321] 321: description => 'This object depends on another data object, which must be inserted before you can perform this operation.',
[ 322] 322: },
[ 323] 323:
[ 324] 324: 'OmniTI::Exception::Data::UpdateWithoutInsert' =>
[ 325] 325: {
[ 326] 326: isa => 'OmniTI::Exception::Data',
[ 327] 327: description => 'A data object is marked as not yet existing in the database, but you just tried to do an UPDATE on it.',
[ 328] 328: },
[ 329] 329:
[ 330] 330: 'OmniTI::Exception::Data::DeleteWithoutInsert' =>
[ 331] 331: {
[ 332] 332: isa => 'OmniTI::Exception::Data',
[ 333] 333: description => 'A data object is marked as not yet existing in the database, but you just tried to do a DELETE on it.',
[ 334] 334: },
[ 335] 335:
[ 336] 336: 'OmniTI::Exception::Data::NeedMoreKeys' =>
[ 337] 337: {
[ 338] 338: isa => 'OmniTI::Exception::Data',
[ 339] 339: description => 'An operation depends on having multiple primary or foreign keys, but you did not provide enough keys.',
[ 340] 340: },
[ 341] 341:
[ 342] 342: 'OmniTI::Exception::Data::SqlError' =>
[ 343] 343: {
[ 344] 344: isa => 'OmniTI::Exception::Data',
[ 345] 345: description => 'An error occured within the database.',
[ 346] 346: fields => [ qw(statement bind_values) ],
[ 347] 347: },
[ 348] 348:
[ 349] 349: 'OmniTI::Exception::Data::AmbiguousReference' =>
[ 350] 350: {
[ 351] 351: isa => 'OmniTI::Exception::Data',
[ 352] 352: description => 'A table or column reference could not be disambiguated.',
[ 353] 353: fields => [ qw(statement referent) ],
[ 354] 354: },
[ 355] 355:
[ 356] 356: 'OmniTI::Exception::Data::UnsupportedCascade' =>
[ 357] 357: {
[ 358] 358: isa => 'OmniTI::Exception::Data',
[ 359] 359: description => 'An insert or update would require performing a cascading insert or update, which is not supported.',
[ 360] 360: },
[ 361] 361:
[ 362] 362: 'OmniTI::Exception::Data::FetchRequired' =>
[ 363] 363: {
[ 364] 364: isa => 'OmniTI::Exception::Data',
[ 365] 365: description => 'You tried to access a child object using an ORM, but the child object has not been fetched yet. Rather than make hidden DB calls, you should call fetch_METHOD.',
[ 366] 366: fields => [ qw(call_instead called) ],
[ 367] 367: },
[ 368] 368:
[ 369] 369: # TODO - add more exception classes as needed
[ 370] 370:
[ 371] 371: );
[ 372] 372:
[ 373] 373:
[ 374] 374: 1;