.\" Automatically generated by Pod::Man 2.28 (Pod::Simple 3.28) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{ . if \nF \{ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Tangram::Type::Ref::FromMany 3pm" .TH Tangram::Type::Ref::FromMany 3pm "2015-10-09" "perl v5.20.2" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Tangram::Type::Ref::FromMany \- map references to persistent objects .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Tangram; \& \& # or \& use Tangram::Core; \& use Tangram::Type::Ref::FromMany; \& \& $schema = Tangram::Schema\->new( \& classes => { Company => { fields => { \& ref => [ qw( ceo vice_ceo ) ] \& \& # or \& \& $schema = Tangram::Schema\->new( \& classes => { Company => { fields => { \& ref => \& { \& ceo => \& { \& col => \*(Aqceo\*(Aq, \& null => 0 \& }, \& \& vice_ceo => \& { \& ... \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This class is responsible for mapping fields that contain a reference to a Perl object. The persistent fields are grouped in a hash under the \f(CW\*(C`ref\*(C'\fR key in the field hash. .PP The target object must belong to a persistent class. .PP Tangram uses a column on the source object to store the id of the target object. .PP The persistent fields may be specified either as a hash or as an array of field names. .PP In the hash form, each entry consists in a field name and an associated option hash. The option hash may contain the following fields: .IP "\(bu" 4 aggreg .IP "\(bu" 4 col .IP "\(bu" 4 type_col .IP "\(bu" 4 class .IP "\(bu" 4 null .IP "\(bu" 4 deep_update .PP Optional field \f(CW\*(C`aggreg\*(C'\fR specifies that the referenced element (if any) must be removed (erased) from persistent storage along with the source object. The default is not to aggregate. .PP \&\f(CW\*(C`col\*(C'\fR sets the name of the column that contains the target object's id. This field is optional, it default to the persistent field name. You need to specify a column name if the field name is not an allowed \s-1SQL\s0 column identifier. .PP \&\f(CW\*(C`type_col\*(C'\fR sets the name of the second column, that contains the target object's type id. This field is optional, it default to the value of \f(CW\*(C`col\*(C'\fR with "\f(CW\*(C`_type\*(C'\fR" appended. Set to the empty string (\f(CW""\fR) to disable this column, which requires that you also specify a class. .PP \&\f(CW\*(C`class\*(C'\fR specifies the base class of the reference, which automatically disables \f(CW\*(C`type_col\*(C'\fR (currently unimplemented). .PP \&\f(CW\*(C`null\*(C'\fR, if present and set to true, directs \fIdeploy()\fR to generate \s-1SQL\s0 code that allows \s-1NULL\s0 values for that column. .PP Optional field \f(CW\*(C`deep_update\*(C'\fR specificies that the target object has to be updated automatically when \f(CW\*(C`update\*(C'\fR is called on the source object. Automatic update ensures consisitency between the Perl representation and the \s-1DBMS\s0 state, but degrades update performance so use it with caution. The default is not to do automatic updates. .PP \&\fBwarning\fR: there is currently something of a bug with all deep_update collections. If you (for instance) insert an object, and a property of that object that is deep_update, then sometimes things end up getting inserted twice \- especially in mapping tables. This is currently under investigation. .PP You may also pass the names of the persistent fields in an array, in which case Tangram uses the field names as column names and allows \&\s-1NULL\s0 values. .SH "IMPLEMENTATION NOTES" .IX Header "IMPLEMENTATION NOTES" .SS "\s-1INHERITANCE\s0" .IX Subsection "INHERITANCE" Ref directly inherits from Tangram::Type::Scalar, and indirectly from Type. .SS "\s-1STORING REFERENCES\s0" .IX Subsection "STORING REFERENCES" When Tangram stores a reference to another object, it stores the target object's \s-1OID\s0 in the source object's table, just like what happens with other scalar types like String and Number. .PP At least that's what \fIbasically\fR happens, but there can be complications. .PP Complication #1: the target object is not persistent yet. Thus it doesn't have an \s-1OID\s0 yet. Tangram will attempt to store the target object; if this succeeds, the target object gets an \s-1OID\s0 too and Tangram can proceed. .PP Complication #2: Tangram may detect that the target object is already being saved; this happens in presence of cycles. Let's take an example: .PP .Vb 4 \& $homer = Person\->new(); \& $marge = Person\->new(); \& $homer\->{partner} = $marge; \& $marge\->{partner} = $homer; \& \& $storage\->insert( $homer ); .Ve .PP What happens here? Tangram detects that \f(CW$homer\fR refers to \f(CW$marge\fR, and that \f(CW$marge\fR is not yet persistent. So it ignores \f(CW$homer\fR for a while, and proceeds to storing \f(CW$marge\fR. .PP In the process, Tangram sees that \f(CW$marge\fR refers to \f(CW$homer\fR \- which is not persistent yet! its \fIinsert()\fR is suspended. Fortunately Tangram realizes that, and doesn't attempt to store \f(CW$homer\fR again. Instead it stores a \s-1NULL\s0 in the 'partner' column of Marge's row. .PP Tangram also schedules an \s-1UPDATE\s0 statement that will be executed just before returning from the call to \fIinsert()\fR. That statement will patch Marge's 'partner' column with the proper \s-1OID.\s0 .SS "\s-1LOADING REFERENCES\s0" .IX Subsection "LOADING REFERENCES" Tangram never loads the target object in the process of retrieving the source object. Doing so could have disastrous consequences. For example, consider a family tree, where each Person has a reference to Mom and Dad. Pulling any single Person would eventually retrieve everybody up to Adam and Eve! If Tangram did work that way, that is... .PP Instead, Tangram ties all the fields that are declared as outgoing references to a package (Tangram::Lazy::Ref). The underlying object keeps track of the source object's \s-1OID,\s0 the Storage object, and the name of the persistent field. .PP When \- if \- a reference field is accessed, the target object is pulled from the database (if it's not already present in memory), and the field is untied and its value is replaced with a reference to the target object. As a result, the target object is loaded on demand, but in an almost transparent fashion (why almost? because you can always use \fItied()\fR on the field and detect that strange things are taking place).