PmDev: Technical notes and documentation


Table of contents

  1. Data model
  2. Code base

PerlMonks Data Model

Note 1:Subtypes noted only when subtypes change behavior without adding database tables.
Note 2:Supertypes chosen based on data inheritance.
Note 3:Highlighted items are things I'm not sure about.

Table groupings

General questions

Design philosophy

From a design point of view the database tables in the PerlMonks database can be divided into two groups: database tables storing nodes and database tables storing "other information".

Node tables

A node is anything that can be directly created, edited, or deleted by a human being and is not merely the history of a site process (e.g. node approvals or consideration). There is a wide range of information that fits that description and all of it is stored in the database: metadata and integrity rules, root nodes and replies on SOPW, the images displayed in the header, the code that runs each box in the sidebar of a PerlMonks page, the standard layout of each page (header, footer, sidebar on the right), and much more.

Each node has an entry in the node table. This entry assigns the node a node id and node type. It also tracks essential audit information about the node: the owner and the last update date, for example. For many nodes this is not enough information so each node may also link in a 1-to-1 fashion to several additional tables. These tables store extra attributes: document text, an ad-hoc list of settings, additional users who may edit the node, the position of the node within a hierarchy of nodes, and much more.

The set of tables to which a node links is determined by its node type. The node type determines all of the data, integrity constraints, processing and display requirements of the node. It also controls who may add, update, or delete the node and its attributes.

Though normal PerlMonks users will never see a page "list nodetypes", the definition of a node type is also considered a node since a human being must define its rules. In fact it is the very first node created in the database (id=1) and its assigned node type itself. (If that sounds confusing, you might want to first twist your mind into a mobius strip and then reread the sentence). The available node types and their relationships one to another can be seen in Type Tree. You can use that page to click through to a detailed description of the node type and/or to list of nodes belonging to that node type.

Non-node tables

The second group of database tables, non-node tables, tend to store one of two types of data: (a) data about a node that have a 1-to-Many relationship to that node. (b) data about the history of a process. For example, when the text field of certain nodes contain links to other nodes, the PerlMonks parsing engine extracts those links and saves them in the links table.which nodes does this apply to? which text fields?. The entries in the links table don't count as nodes because they are never edited independently of the containing node's text field. Similarly edithistory records aren't nodes in their own right because they are the by-product of the node editing process and have no existence apart from the node and its editing process.

The records in non-node database tables don't have display pages. In some cases, you can view the database table contents using one of the queries in sqlquery.TODO: list sqlqueries for each non-node table.

Basic site structure

Site look and feel (themes)

The PerlMonks site's look and feel is defined using a combination of htmlpages,containers and a variety of components that can be embedded within them. Htmlpages define how to render content for a particular display type. Containers define the HTML that surrounds that content.

These components may be either free standing or bundled together into a theme. Free standing components define site wide defaults. Themes define a set of htmlpages, containers and HTML/CSS default attributes that can override the site-wide defaults to give the website a particular look and feel.

Theme components

Themes

Site help system

Group editing with revision history

Nodes are normally edited only by the user or user group that created them. However, PerlMonks supports three modes of group editing: group owned nodes, moderated nodes and wiki nodes.

The following types of nodes are all group edited. Unless noted otherwise, they all track edit history.

Group edited nodes need special tables to track who can edit and the history of edits performed so far:

Site management

Database management

Codebase management

Aside from patch, the tools for managing site enhancements seem little used. How do we manage bug reports in PM? enhancements? It seems like the process is very ad-hoc and informal. Would we benefit from something more formal? (i.e. would it enable us to bring on/manage more volunteers?) If so, would we want to build on what is already in PM? Integrate PM with bugzilla? other?

Node approval process

There are a number of different tables here, but the tables seem to overlap in function. Which of these tables are actually in use at this point?

Request management

Is cachedinfo currently in use? How? Or are we using another mechanism for caching site code?

Site statistics

Which of these stat tables are in use? dbstats+dbstattype+dbstatduration would be able to track all statistics but there are several other tables that capture specific stats with or without start time and duration. Which of these are in use if any? is dbstat in use?

Site content

Simple content nodes

Simple content nodes inherit their data from document and store any extra attributes in a single database table named after the nodetype.

Polls

<TODO>

Node stats

<TODO>

Search

<TODO>

User data

User activity

<TODO>

PerlMonks Code Architecture

Defining a webpage

The web pages served up by the PerlMonks website are defined by nodes that store text with a combination of HTML and special perl monks markup. The PerlMonks markup supports both embedded perl code and inclusion of perl code defined in htmlcode nodes. There are several categories of nodes that define themselves using PerlMonks markup. You can click on the links in the list below to see all the nodes in each category.

PerlMonks markup

Perl code is embedded into the above nodes using special perl markup:

["perl string"]
evaluates "perl string" as a Perl interpolated string and inserts the result in place of the markup.
[% any perl code %]
evaluates the perl code between [% and %] ???and inserts the return value in place of the markup.???
[{ code_call }] and [{code_call:param1,param2,...}]
evaluates a script stored in an htmlcode nodes and inserts the return value in place of the markup.

Perl version and configuration

The PerlMonks website is currently using perl-5.8.3. Full details of the configuration of the PerlMonks version of Perl may be found in Config.pm. Have there been any changes to it that will be lost when/if Perl is regenerated? Are we running our own custom compiled version of Perl?

Permitted modules

Any module included in the 5.8.3 core may be used in embedded Perl code. In addition, any class or function defined in a PM module object may be used in code embedded in the PerlMonks website. A full list of the available modules may be found here.

The modules that are displayed in the above link are in fact the files that are being used by the PerlMonks website engine. pmmodule nodes are displayed using the pmmodule display page htmlpage node. That node calls handle_pmmodule_display which calls readPmModule which searches for the module path in %INC and loads the module's text via do. Since we are reading in the module via do, we must be able to safely reload all of the pmmodule files. Has this constraint ever caused problems? Is this a bug waiting to happen if we should wish to move some of the code in htmlcode fragments into pmmodule file subroutines? Might it be better to read the file in line by line like a normal text file?

These modules come from a variety of sources: CPAN, the original everything engine, and the PerlMonks website development effort. (jdporter: Everything/HTML.pm is particularly important).

Data and Perl code stored in the database

The htmlcode node type has many subclasses. Nodes from any of the following categories may be used with this markup - to see a full list of nodes in each category, click on each link:

In addition to htmlcode nodes, the following node types can also embed code or data into a web page definition:

what are these used for: file (0 nodes), includefile (1 node, viewable only by gods), rawpage (6 nodes, mostly empty or with what looks like garbage)

Database engine

The PerlMonks website stores data in a variety of ways, not all of it accessible to a relational database engine. For example, significant amounts of metadata are stored as rows in database tables rather than in system catalogs. Also, some fields contain denormalized data and repeating groups that are difficult for SQL engines to work with. Additionally, at the time that the engine was originally designed, open source relational databases lacked built-in support for many features needed by the PerlMonks data model: row level locking and transaction management, to name two.

As a result of these factors PerlMonks data management is split between the built-in features of the database and wrapper modules that supplement or provide an alternative implementation of the built-in database management support. This custom database management can be compiled separately from the PerlMonks webserver by placing the following files in the @INC path:

The following modules are sometimes used by the database engine but are required at runtime by certain branches of the code. They are only needed if those code branches are traversed and do not affect compilation:

Database engine questions and food for thought

SQL and persistance engines

The Perl Monks website currently uses mysql 5.0.45-log. Table types are MyISAM by default. For details about the configuration, you can run the query show sql variables.

There is also an unofficial port of the PM website to SQLite written by Corion.

Database connection management

$DB
Declared in Everything.pm. Global variable providing database access. The variable stores a reference to a Everything::NodeBase object created by initEverything.
initEverything($sDb, $bUseStaticNodetypes)
Declared in Everything.pm. The parameters to this function are passed without modification directly to Everything::Nodebase->new(...). What calls this function?
$sClass->new($sDb, $bUseStaticNodetypes)
Declared in Everything/Nodebase.pm. Creates a database connection to a database named $sDb. $sClass must be Everything::Nodetype or one of its subclasses. $bUseStaticNodetypes is a flag that determines caching behavior. If true, nodetypes will be cached the first time they are retrieved and changes to nodetypes will not take effect until the server is restarted. If false, changes to nodetypes take effect immediately.
$DB->getDatabaseHandle()
Defined in Everything/NodeBase.pm. Provides access to raw uncached database connection.
$dbh (deprecated)
Defined in Everything.pm. Global variable equivalent to $DB->getDatabaseHandle()

Nodetype management

Nodetypes supplement the metadata stored in the DBMS's data catalog with metadata for specific rows of nodes. The DBMS for which the PerlMonks database engine was originally designed did not provide all of the support needed. One needs to be aware of this history because some of the information stored in nodetype records would normally be stored directly in a modern database system.

Nodetypes are just regular nodes so most (but not all) the node management routines are used with nodetypes. The methods included in this section are particular to nodetypes and do not apply to general purpose node management.

$DB->getType($idOrName)
Defined in Everything/NodeBase.pm. Returns a hash containing all the attributes of a node type.
$DB->getAllTypes()
Defined in Everything/NodeBase.pm. Returns an array of hashes, one for each nodetype defined in the system. The individual hashes are returned by getType()
$DB->deriveType($hType)
Defined in Everything/NodeBase.pm. Calculate default values for nodetype attributes using inheritance. Called automatically by getType
$DB->getNodetypeTables($hType)
Defined in Everything/NodeBase.pm. Cleans up list of a nodetype's tables. Called automatically by deriveType
$DB->isGroup($hType)
Defined in Everything/NodeBase.pm. Returns true if $hType has a group table. Is it always true that a nodetype that is a subclass of NodeGroup (name?) also has a group table? How is this enforced? By virtue of inheritance? And if something has a group table how do we make sure that it also a subtype of NodeGroup (and do we even care)?

Permissions management

$DB->isApproved($hUser,$hGroupOrAccessRule,$hNode, $bIgnoreGod)
Defined in Everything/NodeBase.pm. Returns true if user $hUser can access node $hNode for the purposes defined in access rule $hGroupOrAccessRule. Normally, gods are authorized automatically, but if $bIgnoreGod is true, then user $hUser's access will be assessed based on their non-godly group memberships.
$DB->getLevel($xUserHashOrId)
Defined in Everything/Experience.pm
$DB->isGod($hUser, $hType)
Defined in Everything/NodeBase.pm. Returns true if user is in the gods group.
$DB->canCreateNode($hUser, $hType)
Defined in Everything/NodeBase.pm. Returns true if user $hUser can create a node of type $hType
$DB->canDeleteNode($hUser, $hType)
Defined in Everything/NodeBase.pm. Returns true if user$hUser can delete a node of type $hType
$DB->canUpdateNode($hUser, $hType)
Defined in Everything/NodeBase.pm. Returns true if user $hUser can update a node of type $hType
$DB->canReadNode($hUser, $hType)
Defined in Everything/NodeBase.pm. Returns true if user $hUser can read a node of type $hType

Node management

This section contains methods used to retrieve and generate data for node records. Special methods are needed because of the complex way node data is stored. Node attributes may be split among several different tables with 1-to-1 relationships to the node table. Additionally, some nodes are collections of nodes, or even deeply nested node hierarchy.

what about nodetype additions, updates and deletes? It seems that the general purpose node insert,update,and nuke routines are being used for nodetypes (needs to be verified by looking at the htmlpage/maintenance/htmlcode nodes for nodetype). If so, how are the differences between non node-type and node-type nodes being accounted for?

Retrieve and generate node data (public methods)

Although you can use these node retrieval routines with nodetype nodes, it isn't recommended because non- nodetype and nodetype nodes need to derive different data for each node. If you use one of the node retrieval routines to retrieve a node type you will get only part of the node information needed. To get the remainder, one would also need to pass the node id or hash to getType()

$DB->selectNodeWhere($hWhere, $hType, $orderby,$bNodeTableOnly)
Defined in Everything/NodeBase.pm Returns a reference to an array containing all node ids that match the criteria stored in $hWhere. For an explanation of the parameters see getNodeCursor
$DB->getNodeWhere($hWhere,$hType,$orderby)
Defined in Everything/NodeBase.pm Returns a reference to an array containing fully populated node hashes for all the nodes that match the criteria stored in $hWhere. For an explanation of the parameters see getNodeCursor
$DB->getNode($sTitle,$xNodetypeTitleOrHash)
Defined in Everything/NodeBase.pm. Retrieves a node hash by title+nodetype or by node_id. All data for the node will be retrieved.
$DB->getNodeById($id,$mode)
Defined in Everything/NodeBase.pm Returns the node hash for the node identified by $id. $mode may have one of the following values:
$DB->isNodetype($hNode)
Defined in Everything/NodeBase.pm. Returns true if $hNode belongs to the nodetype class.
Retrieve and generate node data (internal methods)
$DB->constructNode($hNode)
Defined in Everything/NodeBase.pm. Adds 1-to-1 table data and group members to a node hash that only has data from the Node table.
$DB->getRef($aIdOrHash)
Defined in Everything/NodeBase.pm Converts each member of $aIdOrHash from an id to a hash reference, if it is not already a hash reference.
$DB->getNodeCursor($hWhere,$hType,$orderby,$bNodeTableOnly)
Generates a query that joins all of the tables storing node attributes into a single view. $bNodeTableOnly is true if only the fields in the node table should be retrieved. If false or missing, then all fields in all tables with a 1-to-1, the relationship to the node will be returned. For an explanation of the remaining parameters, see genWhereString.
$DB->genWhereString($hWhere, [$hType], [$orderby])
Defined in Everything/Nodebase.pm Generates a where clause from a set of conditions defined in $hWhere. $hWhere is a hash reference whose keys are field names and whose values store a constraint on the value of that field. The generated where clause will "and" together each of the field constraints. This is not intended to be a general purpose where clause generator, so only a limited number of commonly needed conditions are supported.

If the key begins with '-', then the value is expected to be prefixed with some sort of comparison operator. The condition will be constructed by stripping the '-' from the key and the comparison operator from the beginning of the value:

If the key begins with anything else then the reference type of the value determines how the condition will be built:

The $hType parameters stores a hash containing the field values of a node type. If defined, a condition to limit the query to a particular nodetype will be added to the query. The $orderby parameter is the clause that follows an ORDERBY keyword. If this is defined, an ORDERBY clause will be appended to the end of the where clause.

$DB->loadGroupNodeIDs($hNode)
$DB->selectNodeGroupFlat($hNode)
Defined in Everything/NodeBase.pm. Calls <a href="flattenNodeGroup> flattenNodegroup($hNode,{},[])
$DB->flattenNodeGroup($hNode, $seen,$array)
Defined in Everything/NodeBase.pm. Returns an array reference storing all leaf nodes of the group member tree (or subtree) of which $hNode is the root Any reason not to use a visitor pattern here? Actions that require traversal of a group tree would be less memory and processor intensive if they used a visitor pattern because they can stop traversal as soon as the answer is found. Also if a subroutine reference is used as the visitor we can easily support situations where the whole list all at once really is needed.</scan>
getId($aIdOrNodeHash)
Defined in Everything/Nodebase.pm Scans $aIdOrNodeHash for any elements that are hashes and replaces them with the node id. The hashes are presumed to be node hashes.
$DB->getCache()
returns the node cache. The node cache stores nodes that have been retrieved from the database and remain unchanged. The cache's contents are managed by the other node retrieval functions. Access to the cache is provided primarily for monitoring purposes.
Node reputation management (public methods)

The actions a user can take depend on the user's number of experience points. Experience points are made or lost by three kinds of actions: voting on nodes, writing nodes (which other users vote on), and simply showing up and reading nodes. See Voting/Experience System. Thus reputation management system and its database support is a core function of the database engine and its permissions management.

$DB->hasVoted($xNodeHashOrId,$xUserHashOrId)
Defined in Everything/Experience.pm. Returns a hash containing the vote a particular user has made on a particular node. For more information about data stored for each vote, see the database table for vote
$DB->getVotes($xNodeHashOrId,$xUserHashOrId)
Defined in Everything/Experience.pm. Returns an array reference containing information on each up or down vote made on a node. Each array element stores a hash reference describing the user, ip address, and direction and weight of the vote. If $xUserHashOrId is defined, the query will only return the votes for that user.
$DB->allocateVote($xUserHashOrId,$iVoteCount)
Defined in Everything/Experience.pm. Updates the unused vote code of user $xUserHashOrId so that it equals $iVoteCount. Votes are allocated by daily rounds of the votebot.
$DB->castVote($xNodeHashOrId,$xUserHashOrId,$weight,$ip)
Defined in Everything/Experience.pm. Decrements the unused vote count of user $xUserHashOrId and adds (or subtracts) one from the vote count of the node $xNodeHashOrId.
Node reputation management (internal methods)
$DB->insertVote($xNodeHashOrId,$xUserHashOrId,$weight,$ip)
Defined in Everything/Experience.pm. Called by castVote to do the actual creation of a vote record.
$DB->adjustRep($xNodeHashOrId,$iRepChange)
Defined in Everything/Experience.pm. Called by castVote to adjust the vote count for the node. Each node keeps an accumulated total of votes so that the individual votes don't have to be counted each time we want to display the total vote count.
$DB->adjustExp($xUserHashOrId,$iRepChange)
Defined in Everything/Experience.pm. Called by castVote to adjust the experience level of the node's author and of the voter $xUserHashOrId.
Create, modify, or delete nodes (public methods)
$DB->replaceNode($hNode,$hUser,$hData)
Defined in Everything/NodeBase.pm. Inserts $hNode into the database if it is a new node and updates it if it is an existing node. Why do we need the "-key" form in data? do we use it? can't we always put the raw value in $hData and use the SQL schema to determine whether or not to pass the value through quote?
replaceNodegroup($xNode,$xMember,$xUser)
Defined in Everything/NodeBase.pm. Generates and executes an SQL query to replace all the nodes in $xMembers into the group table of node $xNode. The replace is done by first deleting and then reinserting the nodes. The parameters are the same as insertIntoNodegroup
$DB->nukeNode($hNode,$hUser,$bNoTomb)
Defined in Everything/NodeBase.pm. Performs a cascading delete on a node object. It deletes records for a node from the node,links,nodegroup, and considernodes as well as any tables associated with the nodes nodetype (attribute tables, group member table)
Create, modify, or delete nodes (internal methods)
insertNode($hNode,$hUser,$hData)
Defined in Everything/NodeBase.pm. Generates and executes an SQL query to insert a node. This method will fail if the node exists.
updateNode($hNode,$hUser)
Defined in Everything/NodeBase.pm. Generates and executes an SQL query to update a node. This method will fail if the node does not exist.
insertIntoNodegroup($xNode,$xUser,$xMembers,$orderby)
Defined in Everything/NodeBase.pm. Generates and executes an SQL query to insert all the nodes in $xMembers into the group table of node $xNode. $xNode is the id or hash for group. $xMembers may be a single node id, a node hash or an array of node hashes and ids. $xUser is the id or hash for the user trying to do the insert. $orderby is used to position the new nodes within a group of existing nodes.How does this method work when multiple nodes change the value of their orderby field? There seems to be a bug in the current implementation when more than one node changes its orderby field value, but I don't remember the details of what happened (though I think a node disappeared!)
removeFromNodegroup($xNode,$xMember,$xUser)
Defined in Everything/NodeBase.pm. Generates and executes an SQL query to remove $xMembers from the group table of node $xNode. $xNode and $xUser are defined as for insertIntoNodegroup. $xMember is id or hash of the group member to be removed.
$DB->nodeMaintenance($nodeIdOrHash, $op)
Defined in Everything/NodeBase.pm. Retrieves and executes content of a "maintenence" type node. The code is retrieved by calling <a href="#getMaintenanceCode> getMaintenanceCode. It is executed by calling Everything::HTML::embedCode. For an explanation of parameters, see getMaintenanceCode. What do we gain by passing this to embed code rather than executing it directly? Do maintenance nodes embed calls to htmlcode nodes? Or use any feature that would require using embedCode? Could we make things more efficient by moving all of the maintenance code to modules? If we want to segregate custom nodetypes from core engine nodetypes, do we really need a database to do it? Why not just load and write files from a special reserve place in the file system, ideally connected to a VCS?
$DB->getMaintenanceCode($nodeIdOrHash, $op)
Defined in Everything/NodeBase.pm. Retrieves the content of a "maintenance" type node storing the Perl code that must be run before executing database operation $op for nodes belonging to the same type as $nodeIdOrHash. $op can be "create", "update", or "delete" though in practice only the "create" and "delete" actions are currently used. (The code that triggers a call for the "update" operation has been commented out.)
$DB->tombstoneNode($hNode,$hUser)
Defined in Everything/NodeBase.pm. Takes a Data::Dumper snapshot of the node and saves it to a table (tomb). This method is called by nuke only when its $bNoTomb method to true. Any other uses? How often is nuke called with $bNoTomb set to true?

Catalog (metadata) queries

In the database engine, catalog queries are called directly only by the nodetype management routines. Node management routines interact with the data dictionary via their node type. None the less, these methods are split out into a separate group of functions because they are written in a very general way that could be used with any mySQL database. Their definition is not specific to nodetypes.

$DB->tableExists($table)
Defined in Everything/Nodebase.pm. Returns true if $table exists in $DB and false otherwise.
.
$DB->createNodeTable($table)
Defined in Everything/Nodebase.pm. Creates a skeletal node table with a primary key named "${table}_id".
$DB->dropNodeTable($table)
Defined in Everything/Nodebase.pm. Removes a node table and all of its data from the database. Certain tables are hard coded so that they cannot be dropped. Is this list complete? Does it need to be updated or has it been continuously maintained?
.
$DB->addFieldToTable($table,$field,$type,$bPrimary,$default)
Defined in Everything/Nodebase.pm. Adds a field to a database table
$DB->dropFieldFromTable($table,$field)
Defined in Everything/Nodebase.pm. Drops a field from a table. <scan class="highlight">Any field can be dropped. No integrity checks here. Oversight? Reason?
$DB->getFields($table,$mode)
Defined in Everything/Nodebase.pm. Returns an array with one element per field in table $table. $mode determines what information will be retrieved for each field. If 0, only the field name will be retrieved. If 1, a hash reference containing all of the SQL catalog data for that field will be returned. Defaults to 1.

$DB->getFields($table)
Defined in Everything/Nodebase.pm. Returns an array whose elements are the names of the fields in $table. This is equivalent to calling $DB->getFieldHash($table,0).

SQL command generation

These methos are used by both node and nodetype management routines. sqlquery nodes also contain code that call these methods.

$DB->sqlSelectMany($select,$from,$where,$other)
Defined in Everything/Nodebase.pm. Builds, prepares and executes the query. $select is the clause after the SELECT keyword, $from is the clause after the FROM keyword. $where is the clause after the WHERE keyword and $other contains any other clauses such as GROUPBY and LIMIT clauses. If this method is successful it returns the populated query cursor. If it fails to execute it returns undef.
$DB->sqlSelect($select,$from,$where,$other)
Defined in Everything/Nodebase.pm. Returns a single query result as either a scalar or an array. $select is the clause after the SELECT keyword, $from is the clause after the FROM keyword. $where is the clause after the WHERE keyword and $other contains any other clauses such as GROUPBY and LIMIT clauses. mysql now supports limit clauses. Wouldn't it be more efficient to rewrite this to use a "limit 1" clause rather than fetch all matching rows? Or would this be a problem because callers are already setting $other to a limit clause?

If one field is selected by the query, then the field value from the first record found will be returned. If multiple fields are selected, an array containing the field values in the order they appear in $select. If the query failes to execute or finds no matching rows, this method returns undef. Just out of curiosity, why did this method use number of fields in the select statement rather than wantarray?

$DB->sqlSelect($select,$from,$where,$other)
Defined in Everything/Nodebase.pm. Returns a single query result as a hashref whose keys are field names and whose values are the values assigned to those fields. If the query fails to execute or executes but finds no rows, this method returns undef.
$DB->sqlDelete($from,$where)
Defined in Everything/Nodebase.pm. Generates, prepares, and executes an SQL DELETE command. $from is the clause after the FROM keyword. $whereis the clause after the WHERE keyword. Returns 1 if successful, even if no rows were deleted. Returns 0 if query failed to execute.
$DB->sqlUpdate($table,$hData,$where)
Defined in Everything/Nodebase.pm. Generates, prepares, and executes an SQL UPDATE command. $table is the clause after the UPDATE keyword $hData is a hash reference whose keys are field names and whose values are the value that should be assigned to each field. If the field name begins with a '-', the '-' will be stripped and the value will be used as is, e.g. -K=>V will be added to the SET clause as "K = V". Otherwise the key will be used as is and the value will be quoted using the quote()</c> method. $where is the clause after the WHERE keyword.

Returns 1 if successful, even if no rows were deleted. Returns 0 if query failed to execute. On failure a message will be printed out via Everything::printErr().

$DB->sqlInsert($table,$hData,$where)
Defined in Everything/Nodebase.pm. Generates, prepares, and executes an SQL INSERT command. $table is the clause after the INSERT keyword. Otherwise it behaves exactly like sqlUpdate.
$DB->quote($s)
Defined in Everything/Nodebase.pm. quotes a string value in accordance with ISO SQL2. Single quotes (') will be doubled and the entire string will be surrounded with single quotes.

XML generation

XML::Fling is the preferred way to generate XML feeds. XML::Fling define both an OO and functional interface for generating and storing unvalidated unvalidated XML. an object that generates and stores unvalidated XML. It was developed as a faster alternative to XML::Generator and XML::Writer. The OOP implementation studiously avoids inheritance via @ISA. What was the reasoning behind that? Or does it merely reflect the time when the code was originally written, i.e. a time when there was still no consensus on how OOP should be implemented in Perl?</scan>

The functional interface is defined in XML/Fling.pm (via a list of exported subroutines), but the actual subroutine definitions are stored in XML/Fling/Export.pm. There are seven functions in the interface, each of which return a string containing the requested snippet of XML:

xml_header([ $encoding [, $version ]])
generates an XML instruction identify the XML version and encoding: <?xml version="$version" encoding="$encoding"?>
xml_start($tag,[$attr=>$val]...)
generates an opening $tag tag with the attribute value pairs $attr => $val. The values should be unencoded. They will be encoded using the same logic as xml_quote below.
xml_quote($attrval)
encodes $attrval so that it may be used as an attribute value. This function does not add the quotes. It merely replaces the characters <&"> with their equivalent HTML entity. One will rarely call this function directly as xml_start,xml_element and xml_empty all handle attribute value encoding on the caller's behalf.
xml_escape($dataval)
encodes $dataval so that it may be used as a data between open and close tags. It replaces the characters <&> with their equivalent HTML entity.
xml_end($tag)
generates a closing $tag tag
xml_element($tag,[$attr=>$val]...,[$data])
generates an entire $tag element: open tag, data, and closing tag.
xml_empty($tag, [$attr=>$val]...)
generates an empty $tag element, e.g. <$tag $attr => $val />

New objects created by XML::Fling->new($buffer) and will be blessed into one of three classes depending on the type of reference stored in $buffer:

All three types of fling objects have the following seven methods. These methods take the same parameters as the xml_XXX equivalent method above. However, rather than return an XML snippet, they append the generated XML to the buffer passed into the constructor. Each method returns $xml so that methods may be called like this: $xml->start('p')->escape('Hello World')->end('p')

XML::Fling is used in the following nodes (links display code):

For additional nodes using XML::Fling click here

Mail system

Performance considerations

Are race conditions, performance - still an issue? how does it come about? If resolved, how? See

Miscellaneous topics

URLs

HTML generation

  • Everything/CGI.pm - overrides and extends methods defined in CGI.pm.
  • Everything/FormMenu.pm: Everything::FormMenu class
  • Other

    THE END