text:
|System for optimizing query processing in a relational database
|Tsuchida et al.
|Virtual software machine which preprocesses application program to isolate execution dependencies and uses target computer processes to implement the execution dependencies
|Talati et al.
|Method for providing a virtual execution environment on a target computer using a virtual software machine
|Talati et al.
|Natural language understanding system
|Loatman et al.
|Data base management system extending structure
|Kunii et al.
This application is a Continuation of application Ser. No. 08/639,808, filed Apr. 4, 29, 1996 now abandoned, and a Continuation of application Ser. No. 08/473,622 filed Jun. 7, 1995 now abandoned, which is a Continuation of application Ser. No. 07/516,369, filed Apr. 30, 1990 now pending.
constructing a preprocessor including a grammar coupling the object query language with the host language, wherein said grammar includes query statements to use expressions of the host language in accessing the objects and wherein said query statements access both transient and persistent objects by accessing a data dictionary having pointers to said transient and persistent objects to maintain information corresponding to both said transient and persistent objects;
using said preprocessor to preprocess said query statements by parsing, optimizing and translating at least one statement in said object query language into at least one statement of the host language; and
compiling said statement of the host language into executable code.
defining the object query language with set declarations;
formulating query statements by combining a type system of the host language as a database model with preselected aspects of a relational query language as a basic structure for said query statements;
preprocessing said query statements into host language statements, said host language statements to access transient and persistent objects by accessing a data dictionary having pointers to said transient and persistent objects to maintain information corresponding to both said transient and persistent objects;
compiling said host language statements; and
executing said compiled host language statements to return at least one result in response to said formulated query statement.
parsing said query statements;
optimizing said query statements; and
translating said query statements into statements compilable by a host language compiler.
a transient object memory;
a persistent object memory;
a programming language processor connected to said transient object memory and said persistent object memory and accepting statements in a programming language comprising a host programming language and a query extension to said host programming language, wherein said query extension uses a type system of said host programming language as a database model; and
a database processor connected to said transient object memory and to said persistent object memory, wherein query operations corresponding to said query extension of said database processor are directed by programs in said programming language, and wherein said query operations include access of objects in both said transient object memory and in said persistent object memory by accessing a data dictionary having pointers to said transient and persistent objects to maintain information corresponding to both said transient and persistent objects.
a preprocessor for accepting said statements in said programming language and operable to parse, optimize, and translate additional statements in said query extension into host language statements.
a compiler connected to said preprocessor to compile said host language statements into executable code.
accepting queries;
parsing said queries, including the sub-steps of:
validating said queries in an object query language having a grammar for combining a type system of a host language as a data model with preselected aspects of a relational query language as a basic structure for said queries, said queries accessing both persistent objects and transient objects by accessing a data dictionary having pointers to said transient and persistent objects to maintain information corresponding to both said transient and persistent objects;
indicating as a syntactic fault a query not conforming to said grammar and rejecting said query;
globally type checking said queries;
translating said queries from said object query language into said host language;
compiling said translated queries; and
executing said compiled queries.
.COPYRGT. Copyright 1990 Texas Instruments Incorporated. A portion of the disclosure of this patent document contains material which is subject to copyright protection. The copyright owner has no objection to the facsimile reproduction by anyone of the patent disclosure, as it appears in the Patent and Trademark Office patent file or record, but otherwise reserves all copyright rights whatsoever.
1. Field of the Invention
This invention relates to object-oriented programming languages and object-oriented database management systems, and more specifically to a language for querying collections of objects modeled using a host programming language which may in turn be stored in an object-oriented database system.
2. Description of Related Art
The relational model represents the data in a database as a collection of relations. Informally, each relation resembles a table. Each row in a table represents a collection of related data values that can be interpreted as a fact describing an entity in the real world. Each table and column in a relational database has a name. These names are used to help to interpret the meaning of the values contained in each row of a table. For example, table 20 in FIG. 1 is called Person because each of its rows represents facts about a particular person. The column names Name 22, SSN 24, Age 26, and Address 28, specify how to interpret the data values in each row based on the column to which each value belongs. All values in a column are of the same type.
In relational database terminology, a table is called a relation, a column name is an attribute, and a row is known as a tuple. Relations are described by means of a relation schema denoted by R(A1,A2, . . . ,An), where R is the relation name, and A1, A2, . . . , An are attributes. For example, the schema of the Person relation of FIG. 1 is Person(Name, SSN, Age, Address).
In a relational database, data is defined, queried, and updated using a database language. The data definition part of the language is referred to as the data definition language (DDL) and the query and update parts of the language are referred to as the data manipulation language (DML).
Every commercial relational database management system (DBMS) comes equipped with a database language. The best known is Structured Query Language (SQL) created as the database language for the International Business Machines (IBM) System R relational DBMS prototype, and now an ANSI database language standard for relational DBMSs. Although QUEL is another well-known database language (devised for the the INGRES relational DBMS prototype developed at the University of California at Berkeley), SQL is more widely used as a relational query language.
SQL commands for data definition in the database are CREATE TABLE (specifies a relation schema), ALTER TABLE (adds an attribute to a schema), and DROP TABLE (deletes a schema). Examples of these SQL data definition statements for the Person relation of FIG. 1 would be:
|CREATE TABLE Person ( Name VARCHAR(30) NOT NULL, SSN CHAR(9) NOT NULL, Age INTEGER, Address VARCHAR(40) ); DROP TABLE Person; ALTER TABLE Person ADD Salary INTEGER;
Once the database has been defined, the SELECT statement in SQL is used to retrieve information from the database. The basic form of the SELECT statement, is built from three clauses SELECT, FROM, and WHERE as follows:
SELECT <attributes>
FROM <tables>
WHERE <predicate>
where <attributes> is a list of attribute names whose values are to be retrieved by the query, <tables> is a list of relation names containing the data to be retrieved, and <predicate> is a Boolean predicate that specifies a constraint to be satisfied by the tuples to be retrieved.
For example, the SQL query required to retrieve the name and address of all persons less than 30 years old is:
SELECT Name, Address
FROM Person
WHERE Age <30
Unfortunately SQL, like other current query languages has several disadvantages, particularly when used to query object-oriented data. These disadvantages originate from the fact that it was designed as an interface to a relational model which handles only simple objects (tuples) and not composite objects. As a result, it does not handle inheritance or data abstraction, is not tightly coupled with a programming language and does not support strong typing.
|An example of SQL embedded in C.
2. VARCHAR name 30!;
3. VARCHAR address 40!;
7. main()
8. {
11. EXEC SQL WHENEVER NOT FOUND GOTO nomore;
12. while(1)
13. {
14. EXEC SQL FETCH C1 INTO :name,:address;
15. /* do something with this tuple */
16. }
17. nomore:
19. /* continue with program following the SQL quere */
20. }
SQL can be used in conjunction with a general-purpose programming language such as C, FORTRAN, or COBOL. Such programming language is called the host language. An SQL statement can be embedded in a host language. An embedded SQL statement is distinguished from host language statements by prefixing it with a special keyword so that a preprocessor can separate the embedded SQL statements from the host language statement. For example, the keywords EXEC SQL precede any embedded SQL statement in the C host language. The program fragment shown in Table 1 illustrates the way in which SQL is embedded in a C program to retrieve the name and address of all persons less than 30 years old.
The difference between the type systems of the host language and the embedded query language is normally highly visible to the application programmer resulting in several problems. First, strong typing is lost at the database interface. Strong typing in a programming language guarantees that the arguments of functions are type-correct; a programming language with strong typing is viewed as safer and more efficient than one that does not support enforcement of types. In current SQL embeddings, the representation of the host language and the database query language are different and the programmer must break strong typing to copy his data to the database. Experimental persistent programming languages correct this problem, but they lack query extensions. Second, query languages including embedded SQL can only formulate queries to retrieve persistent database objects (i.e., data stored in the relational database) to the program's memory space. It is not possible to query transient data, which stored only on the main memory of the computer existing only during a single execution of a program, or against persistent objects after they enter the program's memory space. Third, host language statements (e.g., user-defined functions written in the host language) cannot be used in queries and queries cannot be freely mixed with host language statements (e.g., as parameters to functions) and they must obey specific protocols. Fourth, programming languages typically do not provide SET type as one of their basic types. Consequently, the complete set of objects returned by a query cannot be made available to a program. It is only possible to make one tuple at a time available to the program. The concept of a cursor (Statement 9 of Table 1) used in all embeddings of SQL in host languages enforces this tuple-at-a-time processing (Statements 12-16 of Table 1). Finally, the syntax and semantics of the query and host languages are completely different, and the programmer has to learn and be aware of these differences.
As mentioned above, the relational model represents data in tabular form. A tuple in a relation can only be formed from atomic values. Therefore, information about a person and all his/her children, (as seen in table 30 of FIG. 2) cannot be represented in a single relation. Additionally, the relational model cannot handle inheritance or user-defined abstract data types defined by the host language. This is because the type systems of the host and query languages are different.
The object-oriented approach to modeling data provides a better match between real world entities and the way they are represented in a database. A central concept in this approach is the concept of an object which is an abstraction of a thing in the real world that is relevant to the application. An object is formed from two main components: its state and its behavior.
The state consists of a collection of attributes (also called instance variables, data members, or slots). The attributes can be viewed exactly as the attributes of a tuple representing a real world entity in the relational model. The behavior consists of a collection of functions (also called operations, methods, or member functions) that encapsulate the behavior of the object. The collection of functions that model the behavior of an object is also referred to as the object's interface and is the only way to interact with an object. An important property of an object is that its private state can be manipulated only by its own operations. This property ensures that the implementation of an object cannot depend on the internal details of other objects, only on their operations ensuring modularity and data independence of applications because they specify what operation is desired, but not how the operation should be accomplished.
|Some relationships between relational and object-oriented concepts. Relational Concept Object-oriented Concept
Relation schema
Class or Type
Attribute Attribute, data memeber, slot
Function, method, operation, member function
Tuple Object
Relation Set of objects
A class (or type) describes the implementation of a set of objects of the same kind. Every object, sometimes called instance, must belong to a class. Table 2 demonstrates the correlation between relational and object-oriented concepts.
|Components of a class definition.
class name Employee
superclass Person
attributes Hire-- date, Job-- grade,
Salary, Project
functions Hire-- employee, Increase-- salary,
Assign-- project, Promote-- employee
Table 3 illustrates the main components of an example class definition.
Unlike relations, classes are organized into an inheritance hierarchy. A class can be refined or specialized in a subclass that will inherit its behavior. The Employee class of Table 3 declares that the objects of the class inherit the behavior of the Person class which is the ancestor of Employee in the hierarchy. The relational model does not have these notions of behavior and inheritance.
In the object-oriented model, an object can be composed of other arbitrarily complex objects. For example, d car object is composed of a chassis and a body objects. A chassis in turn is composed of a frame, wheels, and engine objects.
Every object has an object identity that uniquely identifies the object and is independent of the object's state. This allows an object to be referenced by other objects so that it can be shared. In contrast, in the relational model tuples (the object of the model) cannot be shared. A tuple is fully identified by the values of its attributes and there cannot exist two tuples in a relation with the same values in all their attributes.
Consider now the C++ programming language as an example of an object-oriented data model. The C++ data model includes a set of predefined (built-in or primitive) data types which include: character, integer, long, short, float, and double. These primitive types can be used to define more complex types.
A class is the mechanism for defining such a complex type that determines the state and the behavior of a collection of objects. The definition of a class involves specifying a set of data members (attributes or instance variables) and a set of member functions (operations or methods). A class member (a member function or a data member) can be declared as public, private, or protected. A public member can be accessed from anywhere in a program. A private member can be accessed only by the member functions of its class. A protected member can be accessed by the member functions of its class as well as the member functions of the classes derived from it. An abstract data type is a class that has a public set of member functions and no public data members (all its data members are declared private or protected).
When defining a class, the type of each of its data members is specified. The type of a data member can be one of the predefined data types (integer, float, etc.) or it can be another user-defined type. This capability in C++ allows for building aggregation (sometimes referred to as composition) hierarchies or graphs to represent complex objects, which are recursively defined in terms of other objects. Recursive definitions in which a data member of a class points back to the same class are also possible.
A class can also be derived from one or more base classes, thereby supporting single and multiple inheritance. A derived class can itself serve as the base class for other derivations and this allows for building generalization hierarchies or lattices. A derived class inherits all of the public and protected members of its base class and is referred to as a subclass (subtype) of its base class. Private members of a base class are not accessible from any other classes including derived classes.
The C++ programming language is a good basis for a data model since it overcomes many of the relational data model limitations discussed previously, including the representation of arbitrarily complex objects, inheritance, and user-defined abstract data types. However, C++ still has some limitations as a database system because it cannot handle persistent data, concurrency control, or recovery; in addition, C++ lacks support for a SET type and lacks associative query mechanisms. Overcoming these latter limitations is desirable.
Previous object-oriented query languages can be classified into two groups. Those that are extensions to SQL and those that attempt to add a query capability to C++. Until the present invention, no previous approach provided a combination of the two.
Examples of such object-oriented query languages are OSQL, RELOOP, and O++. OSQL is the query language of the IRIS object-oriented database management system prototype developed at Hewlett-Packard. RELOOP is one of the query languages of the 02 object-oriented database management system prototype developed at Altair. Both OSQL and RELOOP are based on SQL, but they do not allow host language expressions in queries and are not therefore tightly integrated with a programming language.
O++, a database programming language derived from C++, is the language of the ODE database system prototype developed at AT&T. O++ includes in its syntax, iterator expressions (e.g., foreach) that allow sets of objects to be manipulated almost as declaratively as relational query languages. O++ is based on C++ but the basic structure of query statements does not use the SELECT-FROM-WHERE (SFW) form of SQL. O++ is a nonstandard language requiring a nonstandard and expensive compiler, and like OSQL and RELOOP, can only query persistent objects and not transient objects.
Also, in conventional databases, data is translated by application program code to and from the program data model to the database data model every time data is shifted between the two. The Carnegie-Mellon MACH project reports that 90% of applications that share data do so on the same machine type and the same programming language. By translating the language data model to some other data model (e.g., relational), the database programming language community pays for a mapping (translation cost from language data model to neutral data model) 100% of the time when it is required only 10% of the time. It is desirable to have this happen only if needed to share data among different programming languages that used different data models. Further, since the translation is left to programmers, this introduces a chance of errors and inefficiencies. As much as 30% of applications that access databases is spent in programmer code to perform such mappings, a major drain on programmers productivity. In addition, by leaving this translation up to application programmers, the type-safe, strong-typing is potentially broken (not guaranteed by the system) exactly at the program-database interface. this loss of strong typing at the database-program interface is a big problem because, within programs, type-safe behavior is viewed as a major feature and the data stored in the database is viewed as an enterprise's chief resource. Today's database systems do not maintain type-safety at this interface; tomorrow's must.
Lastly, no known OODBMS supports a seamless integration between the query and host languages. Generally, query languages are embedded in host languages in an ad hoc manner, not by seamlessly extending the host language with sets and queries.
In view of the above problems associated with the related art, it is an object of the present invention to provide an apparatus and method for achieving better integration (also known as seamlessness) between a query and an object-oriented host programming language.
Another object of the present invention is to provide an apparatus and method that makes database programming more accessible to programmers using a specific host language.
Another object of the present invention is to provide a method and apparatus that retains strong typing at the query interface, thereby making database programming much easier and more reliable than conventional SQL embeddings.
Other objects of the present invention are to provide an apparatus and method that enables the formulation of queries not only on persistent but also on transient collections of objects, enables user-defined functions written in the host language to be used in the formulation of queries, enables queries to be freely mixed with host language statements expecting a set object, enables support of a SET type so that complete collections of objects returned by queries are available in the host language, enables support of data abstraction, enables support of inheritance and composite objects in the formulation of queries, and provides a more uniform syntax and semantics of the query and host languages.
These objects are accomplished in a preferred embodiment by providing an apparatus and method to be known as Object Query Language (OQL). The term "OQL" refers to the specific method of extending any object-oriented host language with associative query statements, while "OQL C++!" refers to the particular coupling of OQL with C++ which allows certain C++ expressions to be used in the formulation of queries. Where the specific host language is not important, the term "OQL X!" will be used to designate a coupling of OQL with a host language X, where X is, for example, C++, CLOS, Smalltalk, Objective-C, etc.
Basically, OQL adopts the SELECT-FROM-WHERE (SFW) structure of the SQL SELECT statement and allows appropriate statements of the host language to be combined within queries. The SFW structure of SQL was adopted because it provides a standard model for the formulation of queries in object-oriented host languages that currently enjoys wide use in database applications.
The preferred embodiment, OQL C++!, extends the type system of C++ with the support of a parameterized set type, thereby enabling C++ to handle sets. Thus the invention is more than an embedding of a query language in C++ in that it provides a seamless integration between query and host languages by allowing the sets returned from an OQL C++! query to be used in any place within a C++ program expecting to handle a set (e.g., a parameter to a C++ function), allowing set-valued C++ functions to be used in the FROM clause of an OQL C++! statement, and allowing Boolean-valued C++ functions to be freely combined as part of a predicate in the WHERE clause of an OQL C++! statement. This seamlessness with respect to language occurs because C++ is being extended with sets of records and operations on sets.
Unlike many of the existing object-oriented query languages, the preferred embodiment of the present invention achieves a better integration with the object-oriented programming language, C++. The design objectives achieved by the preferred embodiment of the present invention are: minimal data model dependency by using the type system of the programming language as a bare-bones data model, data abstraction by restricting queries to use the object's public interface, orthogonal treatment of classes as types and classes as type extents by supporting user maintained class extents, persistence orthogonal to query processing by allowing queries on transient as well as on persistent sets, and a reduced impedance mismatch between the programming and query languages by using the same type system for both languages.
OQL C++! is minimally data model dependent. This is achieved by assigning only the knowledge of the type system of the host language (in this case C++) as a "barebones" data model rather than defining a new proprietary data model from scratch. C++'s concepts of object, class, data member, member function, inheritance and composition of class definitions provide the core of most object-oriented data models.
OQL C++! supports data abstraction by forcing all queries to be formulated through the object's public interface (member functions), thus hiding the object's internal representation. This is achieved by the parsing module 102 (see FIG. 7) of OQL C++! which consults the run-time data dictionary 112 containing all class information and disallows any query statement that is formulated on anything different than the class' public interface. A query that is incorrectly formulated in terms of the object's private data members or member functions results in a syntax error 122 illustrated in FIG. 7. This makes the principle of data independence (i.e., the immunity of applications to changes in the data structures used to organize data), which is one of the major advantages introduced by the relational model, to be preserved in object-oriented database queries.
OQL C++! supports explicit, user-maintained sets by requiring programmers to define variables of type OQL-- SET in their programs. This makes the concepts of class definition and class extent (the set of instances of a class) to be orthogonal. As a result of this, not all classes may have sets associated with them and some classes may have not one but many sets associated with them, as it is the case in all database systems which support implicit sets. This is achieved by allowing a programmer to explicitly define variables of type OQL-- SET and populating these sets using the membership functions of the OQL-- SET type (see Block 44 of FIG. 3) rather than assuming implicit sets of objects associated with the class definition.
OQL C++! allows queries on transient and persistent sets. In relational DBMSs and in all current OODBMSs, queries are performed exclusively on persistent data. In OQL, it is possible to define and query transient sets, that is, sets whose life span is a single program invocation. Returning now to FIG. 7, query of transient sets is achieved by maintaining a "run-time" data dictionary 112 that keeps track of all transient and persistent classes and set-valued variables defined by the application. Such data dictionary information is available to the OQL query processor 100 so that appropriate C++ or Persistent C++ code is generated. This makes the OQL approach to querying independent of whether data is maintained persistently in a DBMS or transiently in the memory of a computer. As a direct consequence of this independence, OQL can be used as a tool for supporting query statements in a host language.
OQL C++! provides a better integration with the host language by allowing certain host language concepts to be used in the formulation of queries. This is achieved by requiring typed range variables and user-defined set-valued functions in addition to OQL-- SETs in the FROM-clause, user-defined Boolean-valued functions and inherited member functions in the WHERE-clause, and typed objects and substitutability in the SELECT-clause of a query. Since all information about the inheritance class hierarchy is available in the data dictionary 112, which is accessed by the parser 102, query rewrite 104, and query translation 106 modules, it is possible for the parser and query rewrite modules to recognize valid references to inherited member functions, and for the query translator to generate the appropriate C++ or Persistent C++ code equivalent to the query being processed. This enables the invention to be much more programmable than SQL without requiring the special purpose, yet-another-language extensions to SQL to extend its DML functionality.
Additionally, OQL C++! provides elegant looping constructs for C++. The programmer can take advantage of SQL's relational calculus to specify what data needs to be retrieved and let the present invention map the higher level specification into loops that determine how to retrieve the data efficiently. The "what" is represented by the declarative OQL C++! 124 being input to the query processor 100, and the "how" is represented by the C++ or Persistent C++ code 126 being output by the query processor. This increases the programmer's productivity by relieving him/her from the burden of determining efficient access paths and by making his/her code easier to write and to read.
In the present invention, data is translated between the program and the database data models by the application program code only when one needs to share data among different programming languages based on different data models. This generates sizable savings since the database programming language community no longer has to pay for this cost 100% of the time when it is only required 10% of the time. This translation between the host language and the database is achieved in relational and other existing systems by application code. In persistent programming languages, this is achieved by a system-maintained mapping that translates data structures in the run-time host language memory to/from external memory representations. OQL is meant to work with these latter persistent programming languages. In this case, persistence or transience of sets is achieved in a manner exactly analogous to persistence or transience of any other host language data structure.
These and other features and advantages of the invention will be apparent to those skilled in the art from the following detailed description of a preferred embodiment, taken together with the accompanying drawings in which:
FIG. 1 is a block diagram demonstrating an example of a table in the relational model of data in the current art;
FIG. 2 is a block diagram showing an example of data that with current art cannot be represented in the relational model;
FIG. 3 is a block diagram showing the interface of the set class declaration according to the present invention;
FIG. 4 is a schematic of an example class hierarchy describing a hospital database schema;
FIGS. 5a-b are block diagrams showing examples of C++ classes;
FIG. 6 is an example of code showing an improved coupling of a query language with a host language according to a preferred embodiment of the present invention;
FIG. 7 is a block diagram of the query processor architecture according to a preferred embodiment of the present invention;
FIG. 8 is a diagram of the preprocessing stages required to compile a program written according to the present invention; and
FIG. 9 is a block diagram showing the placement of an application of the present invention, C++ statements, persistent C++ statements, transient, and persistent data in the main memory of a computer.
Although the preferred embodiment of the Object Query Language (OQL) of the present invention will be further described below in terms of its particular syntax and semantics with regard to its implementation with the C++ programming language, some additional background is required.
It should be realized that although the preferred embodiment to be described in detail below is OQL C++!, which provides a specific binding with C++ as a host language for data modeling an programming operations, OQL can be extended to other languages such as OQL Cobol!, OQL CLOS!, OQL Smalltalk!, etc. adding query capabilities to other programming languages as well. OQL can be generalized to OQL X!, where X is a data model, including a generic, language-neutral semantic data models; and domain-specific data models for Computer-Aided Design (e.g., Extended Data Interchange Format or EDIF), Computer-Aided Software Engineering (e.g., TI's Information Engineering Facility), Knowledge Representation (e.g., Carnegie Group Initiative's ROCK), Office Information Systems (e.g., Office Data Architecture, SGML), etc. OQL X! defines a family of bindings between a query language and either a host language or a data modeling environment. Therefore, the present invention should in no fashion be limited to only a C++ coupling.
The syntax of OQL C++! is based on the SFW paradigm of SQL, but extended with C++ expressions. The SFW paradigm of SQL is considered to be data model independent because it can be used to query not only relational data but data represented by other models, as evidenced by the large number of SQL extensions. The preferred embodiment of the present invention exactly combines the SFW paradigm of SQL with the data model of C++.
OQL C++! is not an embedding in C++ because sets resulting from OQL C++! queries can be used in any place in a C++ statement expecting a set (e.g., a parameter to a C++ function), sets returned by user-defined functions can be further queried, and user-defined functions can be combined as part of the predicates of queries.
OQL C++! is a declarative and non-procedural language which means the programmer can take advantage of OQL C++! to specify what and let OQL to be retrieved and let OQL map the higher level specification into loops that determine how to retrieve the data efficiently. This increases the programmer's productivity by relieving him/her from the burden of determining efficient access paths and by making his/her code easier to write and to read.
OQL C++! is minimally data model dependent. This is achieved by assuming only the knowledge of the type system of the given host language (in this case C++) as a data model instead of defining a new proprietary data model from scratch. OQL C++! adopts the object-oriented data modeling concepts and semantics of C++ including the concepts of object, class, data member, member function, inheritance, composition of class definitions, and message dispatch which together provides a core of concepts found in most object-oriented data models. OQL C++! extends C++ with queries and sets. The uniformity of the type systems of the host and query languages achieved in OQL C++! retains strong typing at the query interface, making database programming much easier and more reliable than conventional databases.
OQL C++! is specially useful to CA* (e.g., CAD, CAM, CASE) tool and application developers. A major requirement of these applications is to provide database amenities (i.e., persistence, recovery, concurrency control and queries) within the programming environments in a transparent (seamless) way. The present invention achieves this reduced impedance mismatch between the query and the host languages, by starting from the C++ programming language. Persistence, recovery, and concurrency control were added to C++ without requiring a new compiler. Then, a query capability which includes a language that blends features of SQL, and some of its proposed variations with the syntax of the host language (C++), was added.
The present invention achieves data abstraction. One of the most important concepts of the object-oriented approach to software development is data abstraction, wherein the data representation of an object is hidden from the application and all interactions with objects are made through the object's public interface. The present invention achieves data abstraction thereby, making applications data independent (i.e., invariant to changes in the representation of the objects). Thus, data independence, one of the major advantages of relational database systems, is preserved in OQL C++!. Data abstraction in the present invention is enforced by requiring that all query predicates be formulated in terms of the object's public interface. It should be noted that the principle of data abstraction is strictly enforced only from the user's or application's point of view, thereby leaving open the option for OQL C++!'s internal modules (e.g., the query optimizer) to have access to the object's representation.
The support of sets in an OODB system may be implicit or explicit. Implicit support means that sets of objects are collected implicitly as part of a programming language construct (e.g., class). For example, in a relational system, when tuples (the objects of the system) are created, they are implicitly added to a corresponding set (i.e., a relation). On the other hand, explicit sets are declared and maintained by a user. The present embodiment supports explicit, user-maintained sets, but is not limited to handling only explicit sets.
Consider an example class Patient defining information about patients in a hospital. In addition to the sets of all patients in the hospital, it may be convenient to allow the declaration of special sets of patients such as laboratory patients or pediatrics patients. In OQL C++!, sets of objects are declared and maintained explicitly by the user because it is undesirable that applications be forced to pay the overhead of maintaining implicit sets for classes that may not be queried.
In conventional database management systems (e.g., relational) and in all current object-oriented database management systems, queries are performed exclusively on persistent sets. In CA* environments and applications, a large amount of transient data is generated for which set-oriented query access is essential. OQL C++! provides the advantages of associative access to transient sets of objects as well. Because the present invention is an extension to C++, it is possible to define and query transient sets, that is, sets whose life span is a single program invocation.
Sets are declared and defined using the DECLARE and IMPLEMENT statements, respectively. OQL C++! sets, according to the preferred embodiment, are parameterized
|Set declaration statement grammar.
<set-declare> := DECLARE PERSISTENT! OQL-- SET <class-name>
(HASHED│B-TREE) INDEX ON <member-
list>! ;
<member-list> := <member-function-name> , <member-list>! ;
<class-name> := <identifier> ;
<member-function-name> := <identifier> ;
sets declared using the statement DECLARE OQL-- SET <class-name>, where DECLARE is a keyword that a preprocessor understands and class-name is the name of a previously declared class. The syntax of the set declaration is illustrated in Table 4. In the present embodiment, such a (transient or persistent) set can be declared only on classes, not on basic types (integer or character string).
The DECLARE statement causes the preprocessor to generate the necessary C++ code to declare an OQL C++! set class. The code generated as a result of the DECLARE statement is illustrated by the code fragment 40 of FIG. 3. The public interface of the set class includes member functions to populate the set (Block 44), to iterate through the members of the set (Block 46), to perform set operations (Block 48), and member functions to maintain indices on the set (Block 50). The iterator data member of the OQL C++! set is used to keep track of separate concurrent iteration requests on a set. Each iterator is uniquely identified by an iterator-id.
The statement IMPLEMENT OQL-- SET <class-name> expands the definition of the member functions of a set into appropriate C++ code that executes the intended functions.
During the OQL preprocessing stage 144 (FIG. 8), DECLARE and IMPLEMENT statements are recognized and transformed into C++ or Persistent C++ code that describes the declaration and implementation of the OQL sets. Also, during this preprocessing stage, OQL query statements are identified, parsed, optimized and translated (Block 100, FIG. 7) into efficient C++ or Persistent C++ code (depending on whether the set is a persistent set) that computes the query. The resulting program is then compiled by the C++ compiler 152 (FIG. 8).
The following examples are based on the schema illustrated by FIG. 4 which represents example clinical information about patients in a hospital. Names in the graph represent classes. Classes connected by a continuous line represent composition. Inheritance among classes is represented by dashed lines.
The structure of an OQL query is:
SELECT <objects>
FROM <range variable> IN <set>
WHERE <predicate>
The syntax of the present invention borrows the SFW paradigm of SQL in an upwards compatible way and enhances it in several ways. The SELECT clause identifies the objects that will populate the answer set (i.e., the result of the query). More about the type of objects that can be specified in the SELECT clause is discussed below. The FROM clause specifies the type of the objects in the target set, the set being queried, by means of a range variable. Finally, the WHERE clause specifies the predicate that defines the properties to be satisfied by the objects in the result.
Retrieve patients insured by Aetna
SELECT p
FROM Patient *p IN Patient-- Set
WHERE p->get-- insurance()->company=="Aetna"
In this example, p is a range variable of type pointer to a patient in class Patient 62, and is declared in the FROM clause. The use of p in the SELECT clause indicates that the answer set will consist of a set of pointers to patients 62. The use of typed range variables facilitates compile-time type-checking and the ability to formulate predicates in a syntax similar to C++.
Patient-- et 62 is a (target) OQL set containing objects of type Patient 90 as seen in the hospital scheme of FIG. 4. It is possible to specify any set-valued expression (e.g., a variable or user function) as a target set in the FROM clause. Other classes defined in FIG. 4 are Name 80 (FIG. 5a), Birthdate 82, Insurance 84, Person 86, Physician 88, and Patient 90.
The string p->get insurance()->company is called a path expression and it allows the formulation of predicates on values deeply nested in the structure of an object. If t is a range variable of type T (T *), then: (a) t and t.m() (t->mo) are path expressions where m is a member function of class T; and (b) if p is a path expression, then p.m() (p->m()) is a path expression. The function m is a member of the class T or its ancestors. There may be single-valued or set-valued path expressions. The importance of this distinction will be described below.
The use of path expressions and the declaration of typed range variables are two features of the present invention not available in SQL.
All predicates in the WHERE clause are expressed in terms of the object's public interface, that is, no predicates on private data members or functions are allowed. Currently, it is a user's responsibility to ensure that the member functions in predicates are side-effect free, that is, their invocation does not change the state of any object in the database.
Alternatively, the range variable could have been declared of type Patient 90, in this case the query would be written as:
SELECT p
FROM Patient p IN Patient-- Set
WHERE p.Insurance()->company=="Aetna";
In both forms of this query the expressions p. Insurance() and p->Insurance() return a pointer to an insurance structure 84. Therefore, in both cases the company name needs to be referenced using the arrow notation. Note that the arrow notation is directly from C++ and not part of OQL; OQL CLOS! would use Lisp syntax and CLOS semantics for referencing instance variables and methods.
The purpose of the SELECT clause is to declare the type of the individual objects that will form the answer set. Example 2 illustrates a different use of the SELECT clause.
Retrieve the patients insured by Aetna as a set of persons
SELECT Person *x=p
FROM Patient *p IN Patient-- Set
WHERE p->Insurance()->company=="Aetna";
This example shows how the principle of substitutability (i.e., a program variable of a type may be assigned any object from a derived type) can be applied within an OQL query according to the present invention. In an OQL query, it is possible for the answer set to contain members whose type is the same as the type of the members in the target set, as well as any of its ancestor types. In this example, Person 60 (FIG. 4)/86 (FIG. 5b) is an ancestor of Patient 62 (FIG. 4)/90 (FIG. 5b). The variable x of type pointer to Person 60/86 is assigned a pointer to Patient 62/90. Notice that the object identity of the members in the target set is preserved in the answer set. However, the answer set object will have a new identity every time the query is executed.
A query according to the present invention may also return objects of a type that is unrelated to the class hierarchy of the type of the objects in the target set. This is illustrated in Example 3.
Retrieve the names and ages of patients no more than 10 years old
|class New-- Patient { public: New-- Patient( Name *, int *); "New-- Patient(); void set-- name( Name& ); void set-- age( int& ); }; SELECT New-- Patient w(p->get-- name(), P->get-- age()) FROM Patient *p IN Patient-- Set WHERE p->get-- age() <= 10;
This query illustrates a use of the C++ constructor to create a set of objects of a new type provided that the new type is previously defined. The objects returned by this query have new identity. The query also illustrates the use of inheritance. The path expressions p->get-- name() and p->get-- age(), used in the constructor and in the predicate of the WHERE clause, refer to member functions inherited by the objects of class Patient from the ancestor class Person.
Notice that inheritance of member functions is offered in OQL C++! at no cost because it incorporates the C++ type system.
Other forms of inheritance (e.g., set inclusion) are possible in OQL even though they are not supported in C++. For example, in FIG. 4, given that Patient 62 and Employee 64 are classes derived from the class Person 60, one could expect that sets defined on these classes will carry set inclusion semantics. Set inclusion semantics means that any instance of type patient or employee which is a member of the set of patients 62 or the set of employees 64, respectively, becomes automatically an instance of the set of persons 60. This allows queries on the set of persons 60 to be executed not only on the instances initially created as persons, but also on instances of patients and of employees.
So far, all path expressions used in queries of Examples 1-3 have been single-valued. Example 4 demonstrates a case where a path expression is set-valued.
Retrieve patients of Dr. Smith who have been diagnosed with flu prior to Oct. 10, 1989
|SELECT p FROM Patient *p IN Patient-- Set WHERE p->get-- physician()->get-- name()->last == ``Smith`` && EXISTS ( SELECT r FROM Medical-- record *r IN p->get-- med-- record() WHERE r->get-- date() < ``10/10/89`` && r->get-- diagnosis() == ``flu`` );
Because the path expression p->get-- med-- record() is set-valued (i.e., the function get-- med-- rec() of patients returns a set of medical record 68 objects), it is necessary to define a variable r to range over the members of that set. This leads to the use of subqueries nested within an OQL statement. Requiring the use of an explicit range variable for queries involving set-valued path expressions rather than having OQL define them implicitly yields a cleaner semantics and a simpler implementation of the present invention.
The predicate EXISTS <set> evaluates to true whenever <set> is not empty. This is compatible with the corresponding predicate in SQL. Predicates in the WHERE clause can use comparison operators θε{==,<,<=,>,>=, =}, and logical operators && (AND), ∥ (OR), and NOT. C++ syntax is used for comparison and logical operators. Valid atomic terms are: t1 θ t2, t1 θ c, t1 IN s1, s1 CONTAINS s2, ν θ ALL s1, ν θ ANY s2 , and EXISTS s1 ; where t1 and t2 are single-valued path expressions, s1 and s2 are sets, ν is a single-valued path expression or a constant, c is a constant (integer or string), and θ is a comparison operator. The atomic terms involving ANY and ALL are used for existential and universal quantification, respectively. A predicate is a Boolean combination of atomic terms.
It should be apparent that from the point of view of the user, both inherited member functions and composite objects are referenced uniformly in the present invention through a single syntactic mechanism (i.e., the path expression).
Retrieve all pediatricians and their Aetna-insured patients
|class New-- Patient { public: New-- Patient( Name *, Set<Name> * ); "Name-- Patient(); Name * get-- dr-- name(); Set<Name> * get-- pat-- set(); }; SELECT New-- Patient w( p->get-- name(), SELECT Name n(pat->get-- name()) FROM Patient *pat IN p->Patient-- Set WHERE pat->Insurance()->com- pany==``Aetna`` ) FROM Physician *p IN Physician-- Set WHERE p->specialty() == ``Pediatrics``;
This query illustrates the principle of orthogonality within OQL itself. A SELECT statement can be used anywhere a set is expected, in this case, in the constructor of a New-- patient object.
The scope of a range variable is the whole Select statement associated with the FROM clause that defines it. This allows the variable p declared in the outer SELECT statement to be used in the inner SELECT statement. In contrast, the variable pat declared in the inner Select cannot be used in the outer one. This is exactly consistent with ANSI SQL scoping rules.
Retrieve patients having X-ray exams matching a tuberculosis of the lungs pattern
|X-- Ray-- List *f( Patient * p ) { X-- Ray-- List * x = p->med-- record()->exam-- list.extract(X-- RAY); return( x ); X-- Ray-- Set * Make-- set( X-- Ray-- List * 1 ) { X-- Ray-- Set * x; x = new X-- Ray-- Set; 1.reset(); for( X-- Ray * p = 1.value(); (1.end()); 1.next() ){ x.add( p ); }; return( x ); } SELECT p FROM Patient *p IN Patient-- Set WHERE EXISTS ( SELECT * FROM X-- Ray-- Set *r IN Make-- set( f( p ) ) WHERE x-- ray-- match( r->picture(), Bitmap *pattern ) )
The query of Example 6 illustrates the use of set-valued, user-defined functions in a OQL statement. Assume every medical record of a patient contains a heterogeneous list of laboratory exams (e.g., X-rays 74, ultrasounds 78, blood tests 76). To perform a query on a set of X-rays 74, it is necessary so first extract the X-ray objects from the list of laboratory exam reports 74 (performed by f above) and then make the list into a set (performed by function Make-- et above). This is necessary because OQL can only query sets of homogeneous objects. The user-defined (Boolean) function x-- ray-- match compares the bit pattern r->picture() of an X-ray with program variable of type Bitmap holding a typical tuberculosis pattern.
Data abstraction allows OQL C++! queries on composite objects to be formulated using a uniform mechanism (i.e., path expressions) without regard to the way composition is implemented. This is illustrated by Example 7.
Retrieve patients whose ages are less than 19 years old and who are treated by physicians who work for hospitals located in Dallas
|SELECT p FROM Patient p IN Patient-- Set WHERE p.age < 19 && p.get-- physician().get-- hospital().location()
== "Dallas``
Other query languages that do not support data abstraction require different formulations for queries on composite objects depending on the way the composite relationships are implemented. In these languages, an explicit join with objects returned by a nested query is necessary to express the above query as shown below.
|SELECT p FROM Patient p IN Patient-Set WHERE p.age < 19 && p.physician IN (SELECT s.Physician FROM Hospital s IN Hospital-- Set WHERE s.location == "Dallas``)
Statements 2 and 3 of FIG. 6 show how to declare and define a set of patients according to the present invention. Statement 6 declares two program variables mypatients, and result of type OQL set of patients. Statement 8 shows how sets are populated using the add member function. Statements 10-12 demonstrate how to iterate through all the individual members of a set. Statement 14 shows the query of Example 6 on the set mypatients. Note the use of user-defined functions as part of the program. Statements 16-19 represents code that defines the functions f and Make-- set.
To aid in the implementation of the preferred embodiment, of the present invention, the grammar of OQL C++! follows.
|oql : set-- expression : query-- expression │ QUIT set-- expression : declare-- spec │ implement-- spec ; declare-- spec : DECLARE set-- ref index-- spec │ DECLARE PERSISTENT set-- ref index-- spec ; set-- ref : OQL-- SET `<` IDENTIFIER `>` ; index-- spec : HASHED INDEX ON member-- ref-- commalist │ B-TREE INDEX ON member-- ref-- commalist ; member-- ref-- commalist : member-- ref │ member-- ref-- commalist `,` member-- ref ; member-- ref : member-- function ; member-- function : IDENTIFIER ; implement-- spec : IMPLEMENT set-- ref ; query-- expression : query-- term │ query-- expression UNION query-- term ; query-- term : query-- spec │ `(` query-- expression `)` ; query-- spec : SELECT selection container-- expression │ SELECT DISTINCT selection container-- expression ; selection : TIMES │ ALL │ value-- expression-- commalist │ value-- constructor ; container-- expression : from-- clause │ from-- clause where-- clause ; from-- clause : FROM table-- ref-- commalist │ FROM set-- ref-- commalist ; table-- ref-- commalist : tab1e-- ref │ table-- ref-- commalist `,` table-- ref ; table-- ref : table │ table range-- variable ; set-- ref-- commalist : set-- ref │ set-- ref-- commalist `,` set-- ref ; set-- ref : object-- ref IN set-- expression ; object-- ref : IDENTIFIER range-- variable │ IDENTIFIER pointer-- variable ; set-- expression : set │ function-- expression ; where-- clause : WHERE search-- condition ; search-- condition : boolean-- term │ search-- condition OR boolean-- term ; boolean-- term : boolean-- factor │ boolean-- term AND boolean-- factor ; boolean-- factor : boolean-- primary │ NOT boolean-- primary ; boolean-- primary : predicate │ `(` search-- condition `)` predicate : comparison-- predicate │ existence-- test │ function-- expression ; comparison-- predicate : value-- expression comparison value-- expression │ value-- expression comparison subquery │ path-- expression comparison path-- expression │ path-- expression comparison value-- expression ; comparison : COMP-- EQ │ NE │ LT │ LE │ GT │ GE ; existence-- test : EXISTS subquery ; subquery : `(` query-- spec `)` ; value-- expression-- commalist : value-- expression │ value-- expression-- commalist `,` value-- expression ; value-- expression : term │ value-- expression PLUS term │ value-- expression MINUS term ; value-- constructor : object-- ref │ object-- ref ` ` assignment-- expression-- commalist `!` ; assignment-- expression-- commalist : assignment-- expression │ assignment-- expression-- commalist `,` assignment-- expression ; assignment-- expression : IDENTIFIER `=` query-- expression │ IDENTIFIER `=` path-- expression ; term : factor │ term TIMES factor │ term DIVIDE factor ; factor : primary │ PLUS primary │ MINUS primary ; primary : value-- specification │ `(` value-- expression `)` ; value-- specification : literal ; literal : IDENTIFIER │ INTEGER │ STRING ; pointer-- variable : TIMES range-- variable ; range-- variable : IDENTIFIER ; set : path-- expression │ IDENTIFIER ; table : IDENTIFIER ; path-- expression : range-- variab1e connector function-- expression │ path-- expression connector function-- expression ; connector : ARROW │ DOT ; function-- expression : primary `(` `)` │primary `(` parameter-- commalist `)` ; parameter-- commalist :object-- ref │ path-- expression │ function-- expression │ parameter-- commalist `,` object-- ref ;
The approach used in OQL to provide a better integration with host languages can also be used by current SQL systems to provide a better integration with object-oriented programming languages.
The invention provides an elegant way to combine the computer industry's most used industrial strength object-oriented programming language, C++, with the industry's standard database query language SQL. The invention complements a C++ programmer's existing programming tools, by adding a query capability. This can result in better, more reliable C++ code and make database programming more accessible to the large number of C++ programmers.
The query processor architecture of OQL 100 is illustrated in FIG. 7. It consists of four main modules: parser 102, query rewriter 104, rule-based query translator and optimizer 106, and code optimizer 108. All these modules use the run-time data dictionary 112 that contains all type information of the application including class information (class names, data member names and types, and member function names types and parameters), class hierarchy information, and set-valued and Boolean-valued variables and functions used in the applications. The query processor takes as input OQL C++!'s SELECT statements 124, and produces as output optimized C++ or Persistent C++ code 126. In FIG. 7, lightly shadowed boxes represent run-time data structures, darker boxes represent rule-bases, arrows connecting modules represent transfer of control, and continuous lines represent access to data structures from the corresponding modules. Parser 102 takes as input OQL C++! SELECT statement and, with the help of the data dictionary, checks the syntax of the statement and whether references to class information and user-defined functions are valid. Syntactically incorrect statements are issued syntax errors 122 and syntactically correct statements are mapped into a query graph 116. After parsing, control passes to query rewrite module 104 which reads query graph 116 and transforms it in place after performing semantic and algebraic query optimization with the help of data dictionary 112 and algebraic rule-base 110, respectively. After query rewrite, control passes to rule-based query translator 106 which with the help of storage interface rule-base 118 and data dictionary 112 translates the query graph into a first version of an execution plan 114 written in C++ or Persistent C++. Finally, code optimizer 108 produces an improved sequence of C++ and Persistent C++ code 126 statements corresponding to original query 124.
The complete compilation process 140 of a program containing OQL C++! statements (i.e., DECLARE, IMPLEMENT, and SELECT statements) is illustrated in FIG. 8. The input to the compilation process is a program containing OQL C++! statements 142. This input is processed by the OQL preprocessor which, for SELECT statements, performs all the functions described in query processor 100 (FIG. 7). The OQL preprocessor produces a combination of C++ and Persistent C++ code 146 because of the possibility of a program querying transient and persistent data. A persistence C++ preprocessor 148 transforms Persistent C++ code into pure C++ code 150 and C++ code passes this process unchanged. C++ code 150 is then processed by a standard C++ compiler 152 which produces executable code 154.
FIG. 9 illustrates a possible placement of an application code 164 containing OQL C++! query statements 166, according to a preferred embodiment of the invention, in the main memory 162 of a computer 160. During the development of the application, a computer prograrmmer enters a program to the computer 160 via a computer terminal 180. The application is compiled according to the process described in FIG. 8 where OQL C++! statements 142 (FIG. 8)/166 (FIG. 9) are translated into pure C++ code 168 or Persistent C++ code 178 depending on whether queries access transient 170 or persistent data 172. Persistent data 172 is stored in a persistent database 176 on disk 174. Queries on transient data are performed using C++ code 168 in main memory 170. Queries on persistent data are performed using Persistent C++ code 178 which ensures the transfer of persistent data from the database 176 on disk 174 to a special area 172 of main memory 162 where the query is executed. It should be noted that although application code 164, OQL C++! code 166, C++ code 168, and Persistent C++ code 178 are distinguishable before compilation, they are a single, indistinguishable piece of execution code after compilation.
The description of OQL C++! as implemented by a a C++ preprocessor is specific to the implemented embodiment. If native C++ compilers (not implemented by preprocessors) were extended to use OQL, similar operations would be implemented by those compilers. In fact, if incremental C++ compilers become available, then OQL C++! will be able to be similarly incremental and still inherit the "ad hoc" interactive ability to state queries. This feature would be inherited immediately in OQL CLOS! when applied according to the present invention since CLOS allows incremental compilation.
While a specific embodiment of the invention has been shown and described above in this patent application, various modifications and alternate embodiments will occur to those skilled in the art. Accordingly, it is intended that the invention be limited only in terms of the appended claims.


text:
Big Red lighthouse is an icon of the Holland area. Locals and tourists from down the street and around the globe will be able to take a walk to the lighthouse starting Friday.
Big Red lighthouse is an icon of the Holland area. Locals and tourists from down the street and around the globe will be able to take a walk to the lighthouse starting Friday.
The lighthouse will be accessible Fridays through Sundays in May. Although people have always had to cross private property to reach the lighthouse, new rules enforced beginning last year restricted access over that land.
"We tried to find some palatable compromises," said Mark Harmsen, owner's representative for Point West I, which owns some of the land people have to cross to reach Big Red.
Dave Van Andel, Point West I and the Macatawa Park Cottagers Association met over the off-season to discuss how best to balance property rights and privacy with people's desire to see a local icon.
Out-of-state visitors also will be able to walk to Big Red, 11 a.m. to sunset Monday through Friday all summer. (Locals are still restricted to Tuesdays and Thursdays.) In addition to the annual Holland Historical Trust fundraiser July 24, which opens up the lighthouse for tours, a handful of other open house dates are planned.
"It's more nuanced than 'those selfish property owners don't want us there.' That's just a soundbite. That's not the whole story," said Nicki Arendshorst.
Arendshorst sees the issue from several angles. She is a Park Township Trustee, a member of the Holland Harbor Lighthouse Commission and sits on the security committee of the Macatawa Parc Cottagers Association.
The Macatawa Park Cottagers Association and Point West I share the cost of employing the seasonal gatehouse manager.
"Even if there was no gate, there is no parking — there's four spaces," Arendshorst said. "The parking is a huge issue. There is just no room."
In the case of inclement weather, the gatehouse won't be staffed, and people won't be able to get through to park in one of the four provided spots.
There is still the matter of property rights, Arendshorst said. To reach Big Red, visitors must cross property owned by Point West I, VA Properties, the Macatawa Park Cottagers Association and the U.S. Army Corps of Engineers.
"The fact remains that it's private property that you have to traverse," she said.
Still, they are trying to be good ambassadors, she said. That's why they opened up access for Tulip Time and why they started asking for public comment through the lighthouse commission's website.
What was billed as a "public comment period" in November is now "ongoing communication," Arendshorst said. She regularly brings comments and questions to the Holland Harbor Lighthouse Commission for consideration and sometimes responds personally to questions, she said.
For details about Big Red or to pose a comment or question, visit bigredlighthouse.com.
— Follow this reporter on Facebook and on Twitter, @SentinelAndrea.

subset: commoncrawl


text:
NEW DELHI (AP) — Officials from India and China were meeting in New Delhi on Tuesday to discuss ways to restore peace and tranquility on their shared Himalayan border, a source of longstanding tension between the Asian giants.
Top military and foreign ministry officials from the two sides were examining the workings of a group set up last year to deal with incidents on the border and defuse them before they escalate into major standoffs, said an Indian official speaking on condition of anonymity as he was not authorized to speak to the media.
During the two-day meeting, India is expected to raise its concerns about incursions by Chinese troops into Indian territory across the Line of Actual Control that serves as an informal border. Officials will also discuss ways to ensure better communication between the two sides should any incident take place near the border.
In April, the two countries were caught in a three-week stand-off when Chinese soldiers moved deep inside Indian boundary. Indian officials have reported several minor incursions since then, including three in the past week, when Chinese troops entered the Indian side in the Leh region of northern India adjacent to southwestern China.
India and China have separately held 16 rounds of talks since 2003 to resolve their border dispute, without making much progress.
China claims around 90,000 square kilometers (35,000 square miles) of land in India's northeastern state of Arunachal Pradesh, while India says China is occupying 38,000 square kilometers (15,000 square miles) of territory on the Aksai Chin plateau in the western Himalayas.
The two nations face tensions in other areas as well. China is a longtime ally and weapons supplier to Pakistan, India's bitter rival. The presence in India of the Tibetan spiritual leader the Dalai Lama and the self-declared Tibetan government-in-exile irks Beijing. China is also suspicious of New Delhi's growing ties with the United States.
Despite the tensions, trade between India and China has soared, with China becoming India's biggest trading partner. Two-way trade jumped from $5 billion in 2002 to nearly $75 billion in 2011, but declined slightly last year because of global economic conditions.
India is concerned, however, that trade remains heavily skewed in China's favor.


text:
Northeast Texas farmers and ranchers have an opportunity to learn the latest in weed control techniques Dec. 11 during the annual Ag Technology Conference at Texas A&M-Commerce.
The conference and expo will be held in the Sam Rayburn Student center on the Texas A&M-Commerce Campus.
Participants will qualify for five private applicator and five commercial applicator continuing education units.
Two experts from the University of Arkansas will discuss Mid-South emerging weed control problems that could soon affect growers in the Southwest. Jason Norsworthy, associate professor, University of Arkansas, will address glyphosate resistant weeds. John Boyd, University of Arkansas Extension weed scientist, will discuss managing difficult to control brushy weeds.
Don Renchie, Extension program leader for Agriculture and Environmental Safety, will provide a Laws and Regulations update.
Three industry representatives will discuss new product technology. Eric Castner, DuPont; Gary Fellows, BASF; and Jim Bloomberg, Bayer CropScience, will look at emerging technology expected within the next five years.
The annual conference is sponsored by Cereal Crops Research Inc., Texas A&M-Commerce, Texas AgriLife Extension and the agribusiness industry.
Registration fee before Nov. 30 is $20 ($30 after Nov. 30) per person. The fee includes lunch.
For more information, contact Jim Swart at [email protected].


text:
Dundee, Miss., cotton producer Justin Cariker is watching inputs very closely these days, but he's not cutting back on them at the expense of yield and quality. Cariker spoke of his move to increase efficiency during an innovative grower panel at the 2006 Beltwide Cotton Conferences in San Antonio.
Cariker farms 5,600 acres on Maud Farms in the north Mississippi Delta, including 4,300 acres devoted to cotton, 70 percent of which is irrigated. Two thousand acres are watered with center pivots, 1,000 acres with furrow irrigation.
The producer takes soil samples in the fall every two years which helps him plan out any variable-rate applications. Cariker and his consultant, Winston Earnheart, look at how each sample varies within the same field "before we decide whether or not to take grid samples. If there is not much variation, we go with a blanket shot of mixed fertilizer, lime or whatever the sample may call for.
"The following year, we look at the old samples and what we applied and apply a maintenance dose of mixed fertilizer and lime. Then we start our land preparation for the next year by Paratilling down the row. We've been very successful maintaining a controlled traffic pattern."
Cariker aims to Paratill each acre of cotton each year with three, six-row Paratills. "After Paratilling, we run a 12-row buster on our heavy ground followed by a roller. Hopefully, in the spring, all we'll have to do is burndown and plant.
"On sandier soils, we bed up in the spring. We'll look at each field to determine the burndown we need to use and when. In some cases, we burn down prior to bedding, wait two to three weeks and then plant."
Cariker plants with two, 12-row planters going with several varieties "to spread maturity. After we get a stand of cotton, we start scouting for insects and get ready for our first application of Sequence. On a normal year, we'll fly on one application. This will usually carry us long enough to where we are able to get under our cotton with Touchdown or Envoke.
"After we have been around every acre with two, 12-row hooded sprayers, we start to watch closely for the right time to begin our layby. Our layby application is a tank mix of Touchdown and Suprend (Caparol and Envoke pre-mix).
"After layby, we start to closely monitor our irrigation needs. We stay on top of it because if we ever get behind, it's hard to play catch-up."
Cariker uses a computer software program available though Syngenta "to help us watch our inputs. It allows us to get up-to-date costs per acre on every field."
Earnheart scouts Cariker's fields twice a week. Cariker noted that the only blanket insect applications are Cruiser for thrips and an application of Dynasty, a fungicide, "which I think is the best thing a farmer can do to insure a good, healthy stand. I have never been able to attain top yields and quality from skippy stands."
At defoliation, Cariker shoots for a one shot application of Def, Prep and Dropp in a tank mix, varying the rate depending on the amount of open bolls and juvenile growth in the field.
"We've been working with Syngenta for two years using satellite infrared images to determine when we are approaching cutout. With the use of this technology, we can determine which fields need to be defoliated before others — for example, fields that are not 100 percent irrigated or where we have corners that a pivot may not reach."
Defoliation usually starts at 60 percent to 65 percent open bolls. All Cariker's cotton is harvested with three John Deere harvesters. "Each picker has its own module builder and boll buggy. I know that seems like a lot of equipment. We try to harvest our crop in 28 to 32 days, before the days get too short. We have found that our picking efficiency at night falls off 10 percent to 15 percent."
Cariker markets his cotton using two co-op pools and "we do some marketing on our own. I like spreading our marketing strategy out this way because we don't always have our eggs in one basket. We don't plant our entire crop in one variety, therefore we don't market our crop in one way."
Cariker, a recent participant in the Cotton Foundation's Cotton Leadership program, said after his graduation from the class in August 2005, "I learned that all segments of the cotton industry have their own challenges they must overcome. Through the work of the National Cotton Council working together with each segment, we can all succeed.
"We have to find ways to improve our bottom lines," Cariker said. "We all have to watch our inputs very closely, but at the same time, not jeopardize our yield and quality."
e-mail: [email protected]


text:
SYCAMORE – The Sycamore Fire Department will work to upgrade a fourth ambulance thanks to an $8,000 donation from the Sycamore Lions Club.
The club presented the department with a check Tuesday that will upgrade the service vehicle to the basic life support level and eventually advanced life support level, said Sycamore Fire Chief Pete Polarek.
"We want to give this in memory of Lion Jack Shrout," said Barbara Schultz, president of the Sycamore Lions Club.
Shrout, who died in October and bequeathed the money to the club, was a dedicated member of the Lions Club and the Sycamore community, said Schultz.
"He was really into Sycamore," she said. "Anything that had to do with the town itself, he was really into that."
Polarek said the department was grateful for the donation, which he hopes will help make all four ambulances more available.
"I think it's going to really enhance our service delivery," he said.
This donation is just one of many ways the club works to benefit the community, Schultz said.
The Sycamore Lions Club, whose overall mission is to serve the aged, sick, poor and handicapped in the community, supports and operates various events and programs such as eyeglasses and hearing aid collections and the Sycamore Pumpkin Festival.
"Any money we make from the public goes back into the public," Schultz said.


text:
So here it is, the pros and cons I've gathered from my play experience with Square Enix's revamped and re-released MMORPG Final Fantasy XIV: A Realm Reborn. There will be plenty of Final Fantasy fanboys and fangirls alike who probably won't like the assessment laid out with the pros and cons of the game, but this is how the dice falls, folks.
Originally, I didn't have very many nice things to say about the game in my introductory first impressions piece, and things didn't get much better by the time I hit level 10. However, things did start to turn around heading into level 20 and I found a caveat of promise around the level 30 mark. Still, the game has its rough edges and I managed to carve out both the pros and cons of the game in this here article. So let's start with the pros.
Absolutely the best part about Final Fantasy XIV: A Realm Reborn. I wasn't really drawn into the game until I heard the iconic prelude piece from famed composer Nobuo Uematsu, and then I absolutely fell head over heels in love with the soundtrack by the time the night version of Ul'dah's theme started up. The original Chocobo theme making a remastered appearance; the bass guitar from Shadow's theme used during the Aleport music; that absolutely drop-dead gorgeous track for outer Lominsa, and the John Powell-sounding track from How to Train Your Dragon really had me cracking a smile in upper Limsa Lominsa. Uematsu and the rest of the sound design team really knocked it out of the park with the soundtrack and it was a much needed element to help keep players both engaged and audibly entertained.
The next best thing in the game was obviously the atmosphere. Each map felt as if it were designed to help bring to life Eorza in a fantastical and yet grounded way. Farming could only be done in forested areas – which nicely tied in with the job locations as well – mining could only be done in rocky, barren locales, and fishing areas were available every once in a while at strategically placed but topically correct spots. What's more is that there was a nice feeling of space and architectural breath to this game that's rarely captured in other MMOs. I felt like there was room to explore and breathe as an explorer, though not quite to the extent of games like Mortal Online or Repopulation. Still, I adored the very differently-depicted maps that didn't just come across like theme park locations with fetch-quest rides to pass through. I felt like it was an actual adventure having to travel back and forth between each region, and that there was an air of significance attached to the journey because each region had topographical and atmospheric relevance to the story, characters, jobs and quests, which is not an easy thing to achieve in an MMO.
Character Designs & Animations
The character designs are beautiful in the game. They aren't necessarily "realistic" looking so much as they are distinctive, especially with the varying armor designs for each of the class types. I thought the artists did a great job bringing out an idiosyncratic quality relative to the Final Fantasy series that felt right. The designs of the player characters and NPCs were creative enough that it didn't feel like the game was a typical MMO cloning facility when walking around, and that helps a lot with building a feeling of atmosphere for a game like this. This is also probably one of the few MMOs I've played where emotes aren't actually useless. It's just too bad that the game didn't force more social multiplayer interaction the way they forced the use of emotes in the game. One of the other big highlights of the game were the animations – Square's team of animators did a superb job, especially with little things like the running, sprinting and walking, which all looked and felt natural and authentic, which is rare for a lot of MMOs.
This borderlines on a con for a reason I'll mention later, but oh boy did the story feel classic Final Fantasy here. I just wish there was a real main character to helm the plot direction so that things felt more compelling, cohesive and personal, as opposed to having generic-created-player-character mute their way through the story events and bring sometimes poignant and interesting scenarios to a screeching halt due to other characters being required to fill in the context of the situation. Still, the subplots for each of the main disciplines of war were excellently told and I loved that some of them nearly rivaled the main plot in terms of character development and bringing a resolution to some matters with an apex showdown, sometimes with personal, tragic and interesting developments. But again – and this is where this "Pro" borderlines as a "Con" – the lack of focus due to making all these stories revolve around a mute, personality-vacant player-character really diminished the value of the stories the writers were trying to tell.
Job Diversity
This here was probably one of the better gameplay mechanics, or rather, the premise of the mechanic was very engaging and captivating but the gameplay itself revolving around the jobs was mostly mundane and grindy. Still, props are due where props are due, and I have to give huge props to Naoki Yoshida for rescuing the game and building a hugely diverse system of complex mechanics into an MMO that I haven't seen the likes of in any other game. In fact, the job diversity and skill branching is almost like an evolved throwback to the "Job System" from Final Fantasy V, where you could master different jobs and eventually cross-breed them to form a whole new class of character. That's not to mention that the crafting and supplying sub-jobs could almost become entirely new games in themselves. The diversity and openness of the class system is what helps keep the player-character feeling fresh and exposed to true role-playing possibilities, which I really liked. The crafting mini-games were okay and the grind to get up some of the supplier jobs could easily grate on some players, but the fact that players aren't ever pinned down to any singular class really helps the game maintain an air of freshness and replayability about it, and that's vital for a subscription-based game.


text:
The Leading eBooks Store Online
4,353,660 members ⚫ 1,442,818 ebooks
New to eBooks.com?Learn more
- Bestsellers - This Week
- Foreign Language Study
- Pets
- Bestsellers - Last 6 months
- Games
- Philosophy
- Archaeology
- Gardening
- Photography
- Architecture
- Graphic Books
- Poetry
- Art
- Health & Fitness
- Political Science
- Biography & Autobiography
- History
- Psychology & Psychiatry
- Body Mind & Spirit
- House & Home
- Reference
- Business & Economics
- Humor
- Religion
- Children's & Young Adult Fiction
- Juvenile Nonfiction
- Romance
- Computers
- Language Arts & Disciplines
- Science
- Crafts & Hobbies
- Law
- Science Fiction
- Current Events
- Literary Collections
- Self-Help
- Drama
- Literary Criticism
- Sex
- Education
- Literary Fiction
- Social Science
- The Environment
- Mathematics
- Sports & Recreation
- Family & Relationships
- Media
- Study Aids
- Fantasy
- Medical
- Technology
- Fiction
- Music
- Transportation
- Folklore & Mythology
- Nature
- Travel
- Food and Wine
- Performing Arts
- True Crime
- Foreign Language Books
Most popular at the top
Evidence-Based Medicine ToolkitWiley 2013; US$ 32.36
This bestselling pocket guide to the skills of evidence-based medicine succeeds in demystifying the terminology and processes in a handy and easy-to-follow format, all within the space of 100 pages. With an improved layout, this second edition of Evidence-based Medicine Toolkit offers more up-to-date guidance as well as new sections on important... more...
Statistics ToolkitWiley 2011; US$ 35.06
This concise book will help you to interpret the statistical evidence provided by quantitative studies and to plan how to work with data in your own clinical research. Following the successful format of the Toolkit series, Statistics Toolkit guides the reader through statistical concepts using flowcharts, diagrams and real life examples to reflect... more...
Patient and Public Involvement ToolkitWiley 2011; US$ 28.76
Providing information to implement a new core healthcare requirement – patient involvement Including real case scenarios to illustrate the principles of effective PPI Following the unique Toolkit series format of flowcharts and layouts that guide the reader through each section more...
Searching Skills ToolkitWiley 2011; US$ 38.66
The distinguishing feature of this pocket-sized searching skills book, like all the Toolkit series titles, is its user-friendliness. The guiding principle is that readers do not want to become librarians, but they are faced with practical difficulties when searching for evidence, such as lack of skills, lack of time and information overload. They need... more...
Diagnostic Tests ToolkitWiley 2011; US$ 31.46
This new volume in the Toolkit series is designed for clinicians and junior researchers who need to interpret the evidence for the effectiveness of the many diagnostic tests now available. Exceptionally user-friendly, this pocket-sized textbook realizes readers are not experts in diagnostic test interpretation. The authors cover a variety of issues,... more...
- 1
- Page


text:
Rating: 2.4/5 (Total votes: 32)
Basic Colors Theme for OI Notepad and OI Shopping List is a theme for OI Notepad and OI Shopping List. It features three basic colors red, green, and blue. It uses the standard Android font.
What's New in This Release:
· Fix crash in info screen
» show all
FreewareAndroid - Free Downloads Android Market Apps, Applications, Games, APK, WiFi, Sync, GPS for Google Android OS


text:
Bonjanvye Glitter Studded Flower Clutches Bag for Wedding and Party Rose Purses for LadiesRose Gold Rose Gold -
Because?it?is?factory?direct?sale,?the?price?is?cheap,?it?is?just?like?many?people?commented,?it?is?indeed?more?gorgeous?than?the?photo,?which?shines?beautiful?colors?from?every?angle,?it?is?a?evening?bag?which?is?with?impact?sensitivity,?revealing?dignity?and?charming.?Choosing Bonjanvye evening bag can remove your worries in the future.
All hardware of Bonjanvye is well selected to ensure there is no scratch, bubble, and no rust on surface. Besides, it uses K gold aluminum-free plating process.
Bonjanvye adopts emulation silk stain. The adoption of light silk makes cloth charming, thin, soft, smooth, colorful, lustrous, firm and durable.
Size: 20(L)x6(W)x11(H)cm, 110cm long chain, which are detachable.It seems small, but can hold an iphone 7, lipstick, cash and sunglasses effortlessly. It is an ideal choice for prom, party, dating or wedding occasions. Matching it with one dress can enhance your grace and style.
Clutches & Evening Bags


text:
On Sale $201.95
Regular Price
Sale ends
- Available in Silver or Black Trim
- Includes matching magnetic Q-Tray for storing markers
- 1/4" thick white board surface laminated to MDF
- Factory framed in anodized aluminum
- Includes L- Clips, rawl plugs and screws for installation
- Smooth low-gloss surface offers greater color contrast for markers
- Dust-free surface erases easily without ghosting
Shipping Details
Normal Ship Time:Approx. 2 days to 3 days
- Please add 2-5 business days for transit time
When will my order deliver?
We ship factory direct and can only estimate the length of time that it will take for your item to ship out. The normal ship-time before each item leaves the factory is indicated in the blue box.
Quick Ship options, such as select color choices, are available on some items and those options and their ship times will be listed in a red box above the normal ship time. If you do not see a red box, then there are no Quick Ship options for that item.
You may have multiple shipments to complete your order as each item has varying lead times and may be shipping from multiple factories.
Summer months (June through September) are especially busy due to the back-to-school season. Please expect that the listed ship times may be extended and plan ahead.
Contact us if you are concerned about your deadline and our team will confirm product availability with the factory and/or suggest a faster solution. We do our best to provide accurate ship times, but we cannot guarantee any delivery date.
See our Quick Ship section for items that we trust to have the fastest ship times, some even as fast as 24 Hours!


text:
Saiga tatarica
|Scope: Global
Language: English
|Scientific Name:
|Saiga tatarica (Linnaeus, 1766)
|Infra-specific Taxa Assessed:
|Regional Assessments:
Common Name(s):
Saiga imberbis
|Taxonomic Notes:
|Saiga tatarica is the only species in the genus Saiga. Although there is little geographical variation, two subspecies are recognized: Saiga tatarica tatarica (the nominate subspecies, to which the majority of the global population belong), and Saiga tatarica mongolica (endemic to western Mongolia). Grubb (2005) recognized the Pleistocene mammoth-steppe Saiga as a distinct species S. borealis, including the living subspecies mongolica.
|Red List Category & Criteria:
|Critically Endangered A2acd ver 3.1
|Year Published:
|Date Assessed:
|Mallon, D.P.
|Milner-Gulland, E.J. & Mallon, D.P. (Antelope Red List Authority)
The population has shown an observed decline of over 80% over the last 10 years and the decline is continuing. Severely skewed sex ratios are leading to reproductive collapse.
|Previously published Red List assessments:
|Range Description:
|Saiga tatarica inhabited the steppes and semi-desert regions of south-eastern Europe and Central Asia from the Precaspian steppes to Mongolia and western China. Currently, there is one population in Russia (Kalmykia) and three in Kazakhstan, although in winter some animals reach Uzbekistan and even northern Turkmenistan. A distinctive subspecies occurs in western Mongolia (the nominate subspecies formerly occurred in the Dzungarian Gobi of south-western Mongolia, but has not been seen in 40 years). Saiga became extinct in China by the 1960s, and in Ukraine in the 18th century.
|Countries occurrence:
Native:Kazakhstan; Mongolia; Russian Federation; Turkmenistan; Uzbekistan
Regionally extinct:China; Moldova; Poland; Ukraine
|Additional data:
|Range Map:
|Click here to open the map viewer and explore range.
|Historically, this was a common species in Eurasian steppes and semi-deserts. From information provided in recent references it appears that between 1991 and 1994, the global population of S. tatarica was relatively stable at just under one million animals, the majority of which were in Kazakhstan (approximately 810,00–825,000) (Bekenov et al. 1998, Lushchekina et al. 1999, Sokolov and Zhirnov 1998). However, the population in Kazakhstan had fallen to around 570,000 animals by 1998 (A.B. Bekenov and Iu. A. Grachev, in litt. to ASG).
In European Russia (Kalmykia), the Saiga population steeply declined after land reclamation of the Volga basin started, but the species remained numerous within the distribution area. In the 1970s the population recovered to ca.700,000–800,000 as a result of hunting regulation. However, since then the population has drastically declined. In 1980 there were an estimated 380,000 individuals, in 1996 there were 196,000, and by 2000 just 26,000 (see Milner-Gulland et al. 2001 for annual survey results for 1980–2000). At present there are no more than 18,000 animals in Kalmykia. Sex ratio is severely skewed; the proportion of males varies from 1 to 10% in different years.
The population of Mongolian Saiga increased from ca. 3,000 in 1998, to 5,200 in 2000 helped by favourable climatic conditions and active conservation measures by WWF–Mongolia. Numbers fell between 2000 and 2002 as a result of severe winters and summer drought. They continued to decline in 2002–2003, mainly because of poaching. Numbers were ca. 1,020 in 2003, and 750 in January 2004 (J. Chimeg, in litt.).
In total, the global population of Saiga is now estimated at ca.50,000, down from 1,250,000 in the mid-1970s, with most animals found in Kazakhstan.
|Current Population Trend:
|Additional data:
|Habitat and Ecology:
|The Saiga is a nomadic herding species that generally inhabits the open dry steppe grasslands and semi-arid deserts of Central Asia. Bekenov et al. (1998) described the typical habitat as flat open areas covered with low-growing vegetation, allowing animals to run quickly; areas of broken terrain or dense cover are generally avoided, but animals may stray into these out of necessity.
The Saiga is a migratory species with widely separated summer (northern) and winter (southern) ranges. The species lives in large herds, usually up to thousand individuals. It has a high rate of reproduction and recruitment. In years with a favourable climate the population can increase by up to 60% in a single year (Chan et al. 1995). Very few animals in a population are more than 3.5 years old, indicating that the population is almost completely renewed after four years (Bekenov et al. 1998).
|Movement patterns:
|Full Migrant
|Major Threat(s):
|Uncontrolled illegal hunting for horns (male horns are exported for the traditional Chinese medicine trade) and meat since the break-up of the former USSR has led to the catastrophic fall in numbers. Selective hunting of young males and subsequent distortion of the sex ratio has affected reproduction: recent research shows that heavily skewed sex ratios are resulting in reproductive collapse (Milner-Gulland et al. 2003). A second significant threat is the destruction of key habitats and traditional migration routes. Agricultural abandonment is a problem in some areas; cattle grazing formerly maintained the grassy species but land abandonment allows another species (Stippa sp.) to encroach, which the Saiga cannot eat. The recent increase in steppe fires is a further cause for concern. Severe winters can cause mass mortality.
|Conservation Actions:
Legislation protecting Saiga exists at national level, but increased enforcement, and especially external funding for anti-poaching measures and linked rural development are urgently needed. Some protected areas exist within Saiga range but distance between summer/winter ranges of the various populations hinders full protected area coverage. Extension of already existing and new protected areas is under discussion by the Russian Federation government. Some research is being carried out on numbers, range and behaviour. Total prohibition of saiga meat and horn trade as well as temporary removal of saiga from the hunting animals list have been proposed as key conservation measures.
The Mongolian Saiga has been legally protected since 1930. Two protected areas, Sharga NR (286,900 ha) and Mankhan NR (30,000 ha), were designated in 1993 to protect most of the remaining areas of occurrence.
Listed on CITES Appendix II.
|Mallon, D.P. 2008. Saiga tatarica. The IUCN Red List of Threatened Species 2008: e.T19832A9021682. . Downloaded on 24 September 2018.
|To make use of this information, please check the <Terms of Use>.
|If you see any errors or have any questions or suggestions on what is shown on this page, please provide us with feedback so that we can correct or extend the information provided


text:
In this video I interview Joe Pulizzi, author of Managing Content Marketing, co-author of Get Content Get Customers and founder of the Content Marketing Institute.
Joe shares the story behind the Content Marketing Institute and explains why content marketing is not a fad and is here to stay.
You'll also learn how a multi-author blog can help your business and what you need to know to develop one.
Be sure to check out the takeaways below after you watch the video.


text:
People are wrong.
The dimensions are uncountable, each completely separate and for the most part, ignorant of one another. Yet every once in a while, a portion of a dimension "Folds" over, depositing a resident here, onto our world, onto Earth. These residents have gathered together to construct the Community of Folder's Point, a place where a multitude of possibilities are realized.
We are a plot driven board with Science Fiction/Fantasy influences. Here at the Point you can construct a character from your wildest imaginations, and have them interact with the multitude of people who have found themselves here. Site-wide plots occur regularly, and will see that everyone has a chance to participate.
Are you ready to enter the Fold?
Starter's Guide
The Storm is HERE
The Conglomerate
The Rock of Folding
Elections are coming
Hatred in the Field
Head AdminMaggie
Global ModSteveBall
Listed at:
Sister sites:
Idea, plot and concepts by Fate.