%3 ::xo::db::Attribute ::xo::db::Attribute attribute_reference column_spec create_attribute db_attribute_defined init ::xo::Attribute ::xo::Attribute init ::xo::db::Attribute->::xo::Attribute ::xotcl::Attribute ::xotcl::Attribute ::xo::Attribute->::xotcl::Attribute ::xo::db::CrAttribute ::xo::db::CrAttribute create_attribute ::xo::db::CrAttribute->::xo::db::Attribute

Class ::xo::db::Attribute

::xo::db::Attribute[i] create ... \
           [ -column_name column_name ] \
           [ -constraint_values constraint_values ] \
           [ -create_acs_attribute:substdefault (default "true") ] \
           [ -create_table_attribute:substdefault (default "true") ] \
           [ -datatype:substdefault (default "text") ] \
           [ -help_text help_text ] \
           [ -index index ] \
           [ -max_n_values:substdefault (default "1") ] \
           [ -min_n_values:substdefault (default "1") ] \
           [ -multivalued multivalued ] \
           [ -not_null not_null ] \
           [ -pretty_name pretty_name ] \
           [ -pretty_plural:substdefault (default "") ] \
           [ -references:substdefault (default "") ] \
           [ -required:substdefault (default "false") ] \
           [ -spec spec ] \
           [ -sqltype sqltype ] \
           [ -substdefault substdefault ] \
           [ -unique unique ] \
           [ -validator validator ]

ORM class representing an acs_attribute from and acs_object.
Defined in packages/xotcl-core/tcl/05-db-procs.tcl

Class Relations

  • class: ::xotcl::MetaSlot[i]
  • superclass: ::xo::Attribute[i]
  • subclass: ::xo::db::CrAttribute[i]
::xotcl::MetaSlot create ::xo::db::Attribute \
     -superclass ::xo::Attribute

Methods (to be applied on instances)

  • attribute_reference (scripted, public)

     <instance of xo::db::Attribute[i]> attribute_reference tn
    Parameters:
    tn (required)
    Returns:
    the name of a DB attribute, potentially with an alias name.

    Testcases:
    No testcase defined.
    if {${:column_name} ne ${:name}} {
      return "$tn.${:column_name} AS ${:name}"
    } else {
      return "$tn.${:name}"
    }
  • column_spec (scripted, public)

     <instance of xo::db::Attribute[i]> column_spec \
        [ -id_column id_column ]
    Switches:
    -id_column (optional, defaults to "false")
    Returns:
    the full SQL spec for a DB attribute, potentially containing defaults, primary key, constraints, etc.

    Testcases:
    No testcase defined.
    set table_name [${:domain} table_name]
    set column_spec ""
    append column_spec " " [::xo::dc map_datatype ${:sqltype}]
    #
    # Default
    #
    if {[info exists :default]} {
      append column_spec " DEFAULT '${:default}' "
    }
    #
    # References
    #
    if {[info exists :references] && ${:references} ne ""} {
      append column_spec " REFERENCES ${:references}"
    } elseif {$id_column} {
      set sc [${:domain} info superclass]
      if {![$sc istype ::xo::db::Class]} {set sc ::xo::db::Object}
      append column_spec " REFERENCES [$sc table_name]([$sc id_column]) ON DELETE CASCADE "
    }
    #
    # Unique and Not NULL
    #
    if {[info exists :unique]}   {append column_spec " UNIQUE "  }
    if {[info exists :not_null]} {append column_spec " NOT NULL "}
    #
    # Primary key
    #
    if {$id_column} {
      # add automatically a constraint for the id_column
      append column_spec " PRIMARY KEY "
    }
    append column_spec [::xo::dc datatype_constraint ${:sqltype} $table_name ${:name}]
    return $column_spec
  • create_attribute (scripted, public)

     <instance of xo::db::Attribute[i]> create_attribute

    Create an OpenACS attribute, if not already defined (or attribute creation is turned off for this xo::db::Attribute)

    Testcases:
    No testcase defined.
    if {!${:create_acs_attribute}} return
    
    set object_type [${:domain} object_type]
    #ns_log notice "::xo::db::Attribute create_attribute $object_type ${:column_name} epoch [ns_ictl epoch] [array get ::db_state_default]"
    
    if {![:db_attribute_defined -object_type $object_type -attribute_name ${:column_name} ]} {
    
      #ns_log notice "GN: Attribute create_attribute flushes acs_attributes cache"
      nsv_unset -nocomplain acs_attributes acs_attributes
    
      if {![::xo::db::Class object_type_exists_in_db -object_type $object_type]} {
        ${:domain} create_object_type
      }
    
      ::acs::dc call acs_attribute create_attribute  -object_type    $object_type  -attribute_name ${:column_name}  -datatype       ${:datatype}  -pretty_name    ${:pretty_name}  -min_n_values   ${:min_n_values}  -max_n_values   ${:max_n_values}
    
      if {[::acs::icanuse "nsv_dict"]} {
        nsv_dict set acs_attributes $object_type ${:column_name} 1
      }
    }
  • db_attribute_defined (scripted, public)

     <instance of xo::db::Attribute[i]> db_attribute_defined \
        [ -object_type object_type ] [ -attribute_name attribute_name ]

    One could try caching this, but be aware that this also requires proper flushing, this value cannot be considered immutable, not even per request. ns_log notice "GN: db_attribute_defined name $attribute_name type $object_type" ::xo::dc 0or1row -prepare text,text check_att { select 1 from acs_attributes where attribute_name = :attribute_name and object_type = :object_type }

    Switches:
    -object_type (optional)
    -attribute_name (optional)

    Testcases:
    No testcase defined.
    if {![nsv_get acs_attributes acs_attributes list]} {
      #ns_log notice "GN: fetch all db_attributes"
      set list [xo::dc list get_all_attributes {
        select object_type || '-' || attribute_name from acs_attributes
      }]
      nsv_set acs_attributes acs_attributes $list
    }
    set key $object_type-$attribute_name
    #ns_log notice "GN: check is $object_type $attribute_name in list? [expr {$key in $list}]"
    expr {$key in $list}
  • init (scripted, public)

     <instance of xo::db::Attribute[i]> init

    Constructor of ::xo::db::Attribute. It provides defaults and creates the ACS attribute if necessary.

    Testcases:
    No testcase defined.
    next    ;# do first ordinary slot initialization
    if {![info exists :sqltype]}     {set :sqltype     ${:datatype}}
    if {![info exists :column_name]} {set :column_name ${:name}}
    
    :create_attribute