Database
When started, web server creates schema pgorm in database with procedures, tables, and other service objects
pgorm.orm_relation_enable(schema name, table_name name)
Procedure enable object-relational mapping (ORM) for specified table or view, create JavaScript modules
Parameters:
schema | - | schema | |
name | - | table or view name |
Call example:
call pgorm.orm_relation_enable('example', 'invoice');
pgorm.orm_relation_disable(schema name, table_name name)
Procedure disable object-relational mapping (ORM) for specified table or view, remove JavaScript modules
Parameters:
schema | - | schema | |
name | - | table or view name |
Call example:
call pgorm.orm_relation_disable('example', 'invoice');
pgorm.orm_relation
Table pgorm.orm_relation contains list of tables and views for enabled ORM. Edit of module_source field is allowed, and JavaScript module will be automatically updated
Table columns:
schema | - | schema | |
name | - | table or view name | |
type | - | type: 'table' or 'view' | |
class_name | - | JavaScript class name | |
module_source | - | source code of module orm/[schema]/[table_name].js |
Usage example:
select * from pgorm.orm_relation; update pgorm.orm_relation set module_source = 'import { BaseInvoice,BaseInvoiceArray } from "/orm/example/base/BaseInvoice.js" export class Invoice extends BaseInvoice { } export class InvoiceArray extends BaseInvoiceArray { }' where schema='example' and name='invoice';
pgorm.orm_relation_column
Table pgorm.orm_relation_column contains list columns of tables or views for enabled ORM. Edit of class_field_name field is allowed, and JavaScript module will be automatically updated
Table columns:
schema | - | schema | |
relation_name | - | table or view name | |
column_name | - | column name | |
class_field_name | - | class field name |
Usage example:
select * from pgorm.orm_relation_column; update pgorm.orm_relation_column set class_field_name='ExtInfo' where schema='example' and relation_name='invoice' and column_name='extended_information';
pgorm.orm_table_fkey
Table pgorm.orm_table_fkey contains foreign keys (relations) of tables for which ORM is enabled. Edit of child_column_sort_pos name,class_field_parent_name,class_field_child_name fields is allowed, and JavaScript module will be automatically updated
Поля таблицы:
parent_table_schema | - | parent table schema | |
parent_table_name | - | parent table name | |
child_table_schema | - | child table schema | |
child_table_name | - | child table name | |
child_columns | - | child table foreign key columns | |
child_column_sort_pos | - | child table sort column | |
class_field_parent_name | - | field name of parent class/object | |
class_field_child_name | - | field name of child class/object |
Usage example:
select * from pgorm.orm_table_fkey; update pgorm.orm_table_fkey set class_field_parent_name='Invoice' where parent_table_schema='example' and parent_table_name='invoice' and child_table_name='invoice_product';
Module /orm/pgorm.js
Module is designed to interact with the database and contains the following classes:
Module classes:
Relation | - | table and class description |
Column | - | description of table column and corresponding class field |
Record | - | record (table row), main class is inherited from it |
RecordArray | - | array of records, class is inherited from it |
Relationship | - | description of relationship by foreign key |
ORMConnection | - | methods for working with database |
ORMUtil | - | methods for validating and casting values |
ORMError | - | error description |
Source code:
export class Relation { #schema; #name; #type; #comment; #columns; #columnsPrimaryKey; #columnNames; #columnNamesPrimaryKey; #recordClassFunc; #recordArrayClassFunc; #relationshipsParent; #relationshipsChildFunc; constructor(schema, name, type, comment, columns, columnsPrimaryKey, recordClassFunc, recordArrayClassFunc, relationshipsParent, relationshipsChildFunc) { this.#schema = schema; this.#name = name; this.#type = type; this.#comment = comment; this.#columns = columns; this.#columnsPrimaryKey = columnsPrimaryKey; this.#columnNames = columns.map( property => property.getName() ); this.#columnNamesPrimaryKey = columnsPrimaryKey.map( property => property.getName() ); this.#recordClassFunc = recordClassFunc; this.#recordArrayClassFunc = recordArrayClassFunc; this.#relationshipsParent = relationshipsParent; this.#relationshipsChildFunc = relationshipsChildFunc; } getSchema() { return this.#schema; } getName() { return this.#name; } getType() { return this.#type; } getComment() { return this.#comment; } getColumns() { return this.#columns; } getColumnsPrimaryKey() { return this.#columnsPrimaryKey; } getColumnNames() { return this.#columnNames; } getColumnNamesPrimaryKey() { return this.#columnNamesPrimaryKey; } getRecordClass() { return this.#recordClassFunc(); } getRecordArrayClass() { return this.#recordArrayClassFunc(); } getRelationshipsParent() { return this.#relationshipsParent; } getRelationshipsChild() { return this.#relationshipsChildFunc(); } } export class Column { #name; #type; #typeArray; #fieldName; #typePrimitive; #typeObject; #notNull; #recordClassFunc; #validateValueFunc; #jsValueFunc; #pgValueFunc; #comment; constructor(name, type, typeArray, fieldName, typePrimitive, typeObject, notNull, recordClassFunc, validateValueFunc, jsValueFunc, pgValueFunc, comment) { this.#name = name; this.#type = type; this.#typeArray = typeArray; this.#fieldName = fieldName; this.#typePrimitive = typePrimitive; this.#typeObject = typeObject; this.#notNull = notNull; this.#recordClassFunc = recordClassFunc; this.#validateValueFunc = validateValueFunc; this.#jsValueFunc = jsValueFunc; this.#pgValueFunc = pgValueFunc; this.#comment = comment; } getName() { return this.#name; } getType() { return this.#type; } isTypeArray() { return this.#typeArray; } getFieldName() { return this.#fieldName; } getTypePrimitive() { return this.#typePrimitive; } getTypeObject() { return this.#typeObject; } isNotNull() { return this.#notNull; } getRecordClass() { return this.#recordClassFunc(); } getComment() { return this.#comment; } validateValue(value) { this.#validateValueFunc(value); } jsValue(pgValue) { return this.#jsValueFunc(pgValue); } pgValue(jsValue) { return this.#pgValueFunc(jsValue); } } export class Record { constructor() { if (this.constructor===Record) throw new Error("Record is abstract class"); } #recordExists = false; isRecordExists() { return this.#recordExists; } setFieldValue(column, value) { return this["set"+column.getFieldName()](value); } getFieldValue(column, value) { return this["get"+column.getFieldName()](); } isFieldValueChanged(column) { return this["isChanged"+column.getFieldName()](); } save(connection) { validateConnection(connection); let relation = this.constructor.getRelation(); let columnsChanged = []; let values = []; relation.getColumns().filter( column => this.isFieldValueChanged(column) ).forEach( column => { columnsChanged.push(column.getName()); let value = this.getFieldValue(column); column.validateValue(value); values.push(column.pgValue(value)); }); let valuesPrimaryKey = relation.getColumnsPrimaryKey().map( column => column.pgValue(this.getFieldValue(column)) ); let fieldValues = sendRequest("/pgorm/record-save", { "connectionID": connection.getID(), "relationSchema": relation.getSchema(), "relationName": relation.getName(), "columns": relation.getColumnNames(), "recordExists": this.#recordExists, "columnsChanged": columnsChanged, "values": values, "columnsPrimaryKey": relation.getColumnNamesPrimaryKey(), "valuesPrimaryKey": valuesPrimaryKey }).record; this._initialize(fieldValues, null, true); return this; } delete(connection) { validateConnection(connection); let relation = this.constructor.getRelation(); let valuesPrimaryKey = relation.getColumnsPrimaryKey().map( column => column.pgValue(this.getFieldValue(column)) ); let fieldValues = sendRequest("/pgorm/record-delete", { "connectionID": connection.getID(), "relationSchema": relation.getSchema(), "relationName": relation.getName(), "columns": relation.getColumnNames(), "columnsPrimaryKey": relation.getColumnNamesPrimaryKey(), "valuesPrimaryKey": valuesPrimaryKey }).record; this._initialize(fieldValues, null, false); return this; } static loadWhere(recordClass, connection, condition, params) { validateConnection(connection); let relation = recordClass.getRelation(); let fieldValues = sendRequest("/pgorm/record-load-where", { "connectionID": connection.getID(), "relationSchema": relation.getSchema(), "relationName": relation.getName(), "columns": relation.getColumnNames(), "condition": condition, "params": ORMUtil.pgArrayParam(params) }).record; if (fieldValues===null) return null; return new recordClass()._initialize(fieldValues, null, true); } toJSON() { let relation = this.constructor.getRelation(); let json = {}; let columnsChanged = []; relation.getColumns().forEach( column => { json[column.getName()] = column.pgValue(this.getFieldValue(column)); if (this.isFieldValueChanged(column)) columnsChanged.push(column.getName()); }); json["#orm"] = { "relation" : relation.getSchema()+"."+relation.getName(), "record_exists": this.#recordExists, "columns_primary_key": relation.getColumnNamesPrimaryKey(), "columns_changed": columnsChanged }; return json; } static fromJSON(recordClass, json) { let relation = recordClass.getRelation(); let pgValues = []; relation.getColumns().forEach(column => pgValues.push(json[column.getName()]) ); let valuesChanged; let recordExists; if ("#orm" in json) { let orm = json["#orm"]; if (orm["relation"]!=(relation.getSchema()+"."+relation.getName())) throw new ORMError(311, `Relation ${orm["relation"]} does not match class ${recordClass.name}`); recordExists = orm["record_exists"]; let columnNames = relation.getColumnNames(); valuesChanged = Array(columnNames.length).fill(false); orm["columns_changed"].forEach(columnChanged => { valuesChanged[columnNames.indexOf(columnChanged)] = true; }); } else { recordExists = true; relation.getColumnsPrimaryKey.forEach(column => { if ( !(column.getName() in json) || json[column.getName()]===null) recordExists = false; } ); valuesChanged = null; } return new recordClass()._initialize(pgValues, valuesChanged, rowExists); } _initialize(recordExists) { this.#recordExists = recordExists; return this; } } export class RecordArray extends Array { constructor() { super(); if (this.constructor===RecordArray) throw new Error("RecordArray is abstract class"); } static load(recordArrayClass, connection, condition, params) { validateConnection(connection); let relation = recordArrayClass.getRelation(); let records = sendRequest("/pgorm/record-array-load", { "connectionID": connection.getID(), "relationSchema": relation.getSchema(), "relationName": relation.getName(), "columns": relation.getColumnNames(), "condition": condition!==null && condition!==undefined ? condition : "", "params": ORMUtil.pgArrayParam(params) }).records; let recordArray = new recordArrayClass(); records.forEach( fieldValues => { recordArray.push(new (relation.getRecordClass())()._initialize(fieldValues, true)); }); return recordArray; } static delete(recordArrayClass, connection, condition, params) { validateConnection(connection); let relation = recordArrayClass.getRelation(); return sendRequest("/pgorm/record-array-delete", { "connectionID": connection.getID(), "relationSchema": relation.getSchema(), "relationName": relation.getName(), "condition": condition!==null && condition!==undefined ? condition : "", "params": ORMUtil.pgArrayParam(params) }).records_deleted; } toJSON() { let json = JSON.parse('[]'); this.forEach( record=>json.push(record.toJSON()) ); return json; } toArrayJSON() { let arrayJSON = []; this.forEach( record=>arrayJSON.push(record.toJSON()) ); return arrayJSON; } } export class Relationship { #parentTableSchema; #parentTableName; #parentClassFunc; #childTableSchema; #childTableName; #childClassFunc; #childColumns; #childColumnOrderPos; constructor(parentTableSchema, parentTableName, parentClassFunc, childTableSchema, childTableName, childClassFunc, childColumns, childColumnOrderPos) { this.#parentTableSchema = parentTableSchema; this.#parentTableName = parentTableName; this.#parentClassFunc = parentClassFunc; this.#childTableSchema = childTableSchema; this.#childTableName = childTableName; this.#childClassFunc = childClassFunc; this.#childColumns = childColumns; this.#childColumnOrderPos = childColumnOrderPos; } getParentTableSchema() { return this.#parentTableSchema; } getParentTableName() { return this.#parentTableName; } getParentClass() { return this.#parentClassFunc(); } getChildTableSchema() { return this.#childTableSchema; } getChildTableName() { return this.#childTableName; } getChildClass() { return this.#childClassFunc(); } getChildColumns() { return this.#childColumns; } getChildColumnOrderPos() { return this.#childColumnOrderPos; } } export class ORMConnection { static #LOCAL_STORAGE_KEY = "ORMConnection.ID"; #id; getID() { return this.#id; } connect(user, password, idleSessionTimeout = '1h') { this.#id = sendRequest("/pgorm/connect", { "user": user, "password": password, "idleSessionTimeout": idleSessionTimeout }).connectionID; return this; } disconnect() { sendRequest("/pgorm/disconnect", { "connectionID": this.#id }); if (this.#id==localStorage.getItem(ORMConnection.#LOCAL_STORAGE_KEY)) localStorage.clear(ORMConnection.#LOCAL_STORAGE_KEY); this.#id = undefined; } execute(query, params) { return sendRequest("/pgorm/execute", { "connectionID": this.#id, "query": query, "params": ORMUtil.pgArrayParam(params) }); } setDefault() { localStorage.setItem(ORMConnection.#LOCAL_STORAGE_KEY, this.#id); return this; } static getDefault() { let id = localStorage.getItem(ORMConnection.#LOCAL_STORAGE_KEY); if (id===null) return null; let connection = new ORMConnection(); connection.#id = id; return connection; } } export class ORMError extends Error { constructor(code, message) { super( (message.startsWith("PGORM-") ? "" : "PGORM-"+code.toString().padStart(3, "0")+" ")+message ); this.code = code; this.name = "ORMError"; } } export class ORMUtil { constructor() { throw new Error("Final abstract class"); } static validateNumber (value) { if (value!==null && value!==undefined && (typeof value)!=="number" && !(value instanceof Number)) throw new ORMError(303, `Value ${ORMUtil._valueToStringShort(value)} is not number`); } static validateBoolean (value) { if (value!==null && value!==undefined && (typeof value)!=="boolean" && !(value instanceof Boolean)) throw new ORMError(303, `Value ${ORMUtil._valueToStringShort(value)} is not boolean`); } static validateString (value) { if (value!==null && value!==undefined && (typeof value)!=="string" && !(value instanceof String)) throw new ORMError(303, `Value ${ORMUtil._valueToStringShort(value)} is not string`); } static validateObject (value) { if (value!==null && value!==undefined && (typeof value)!=="object") throw new ORMError(303, `Value ${ORMUtil._valueToStringShort(value)} is not object`); } static validateDate (value) { if (value!==null && value!==undefined && !(value instanceof Date)) throw new ORMError(303, `Value ${ORMUtil._valueToStringShort(value)} is not Date`); } static validateUint8Array (value) { if (value!==null && value!==undefined && !(value instanceof Uint8Array)) throw new ORMError(303, `Value ${ORMUtil._valueToStringShort(value)} is not Uint8Array`); } static validateXMLDocument(value) { if (value!==null && value!==undefined && !(value instanceof XMLDocument)) throw new ORMError(303, `Value ${ORMUtil._valueToStringShort(value)} is not XMLDocument`); } static validateArray(array, validateElementFunc) { if (array===null || array===undefined) return; if (!(array instanceof Array)) throw new ORMError(303, `Value ${ORMUtil._valueToStringShort(array)} is not Array`); array.forEach( element => element instanceof Array ? validateArray(element, validateElementFunc) : validateElementFunc(element) ); } static validateArrayNumber (array) { ORMUtil.validateArray(array, ORMUtil.validateNumber); } static validateArrayBoolean (array) { ORMUtil.validateArray(array, ORMUtil.validateBoolean); } static validateArrayString (array) { ORMUtil.validateArray(array, ORMUtil.validateString); } static validateArrayObject (array) { ORMUtil.validateArray(array, ORMUtil.validateObject); } static validateArrayDate (array) { ORMUtil.validateArray(array, ORMUtil.validateDate); } static validateArrayUint8Array (array) { ORMUtil.validateArray(array, ORMUtil.validateUint8Array); } static validateArrayXMLDocument(array) { ORMUtil.validateArray(array, ORMUtil.validateXMLDocument); } static _valueToStringShort(value) { return JSON.stringify(value.toString().length<=15 ? value.toString() : value.toString().substr(1,12)+"..."); } static jsPrimitive (pgValue) { return pgValue; } static jsDate (pgValue) { return pgValue!==null ? new Date(pgValue) : null; } static jsUint8Array (pgValue) { return pgValue!==null ? new Uint8Array([...pgValue].map((c,i) => i && !(i%2) ? parseInt(pgValue.substr(i,2),16) : null).filter(b => b!==null)) : null; } static jsXMLDocument(pgValue) { return pgValue!==null ? new DOMParser().parseFromString(pgValue, "text/xml") : null; } static pgPrimitive (jsValue) { return jsValue!==undefined ? jsValue : null; } static pgDate (jsValue) { return jsValue!==null && jsValue!==undefined ? jsValue.getFullYear()+"-"+(jsValue.getMonth()+1).toString().padStart(2,"0")+"-"+jsValue.getDate().toString().padStart(2,"0") : null; } static pgTime (jsValue) { return jsValue!==null && jsValue!==undefined ? jsValue.getHours().toString().padStart(2,"0")+":"+jsValue.getMinutes().toString().padStart(2,"0")+":"+jsValue.getSeconds().toString().padStart(2,"0")+"."+jsValue.getMilliseconds().toString().padStart(3,"0") : null; } static pgTimezoneOffset(jsValue) { return jsValue!==null && jsValue!==undefined ? (jsValue.getTimezoneOffset()>0 ? "-" : "+")+(Math.abs(jsValue.getTimezoneOffset())/60|0).toString().padStart(2,"0")+(Math.abs(jsValue.getTimezoneOffset())%60).toString().padStart(2,"0") : null; } static pgTimetz (jsValue) { return jsValue!==null && jsValue!==undefined ? ORMUtil.pgTime(jsValue)+ORMUtil.pgTimezoneOffset(jsValue) : null; } static pgTimestamp (jsValue) { return jsValue!==null && jsValue!==undefined ? ORMUtil.pgDate(jsValue)+"T"+ORMUtil.pgTime(jsValue) : null; } static pgTimestamptz (jsValue) { return jsValue!==null && jsValue!==undefined ? ORMUtil.pgDate(jsValue)+"T"+ORMUtil.pgTime(jsValue)+ORMUtil.pgTimezoneOffset(jsValue) : null; } static pgInterval (jsValue) { return jsValue!==null && jsValue!==undefined ? (jsValue/(24*60*60*1000)|0)+" day "+(jsValue%(24*60*60*1000)/(60*60*1000)|0).toString().padStart(2,"0")+":"+(jsValue%(60*60*1000)/(60*1000)|0).toString().padStart(2,"0")+":"+(jsValue%(60*1000)/(1000)|0).toString().padStart(2,"0")+"."+(jsValue%1000).toString().padEnd(3,"0") : null; } static pgBytea (jsValue) { return jsValue!==null && jsValue!==undefined ? "\x"+jsValue.map(byte=>byte.toString(16).padStart(2,'0')).join("") : null; } static pgJSON (jsValue) { return jsValue!==null && jsValue!==undefined ? JSON.stringify(jsValue) : null; } static pgXML (jsValue) { return jsValue!==null && jsValue!==undefined ? new XMLSerializer().serializeToString(jsValue) : null; } static pgRecord (jsValue) { return jsValue!==null && jsValue!==undefined ? "("+jsValue.constructor.getRelation().getColumns().map(column=> { let v = jsValue.getFieldValue(column); return v!==null ? JSON.stringify(column.pgValue(v)) : ""; }).join(",")+")" : null; } static jsArray(pgArray, jsElementFunc) { return pgArray!==null && pgArray!==undefined ? pgArray.map( element => jsElementFunc(element) ) : null; } static jsArrayPrimitive (pgArray) { return ORMUtil.jsArray(pgArray, ORMUtil.jsPrimitive); } static jsArrayDate (pgArray) { return ORMUtil.jsArray(pgArray, ORMUtil.jsDate); } static jsArrayUint8Array (pgArray) { return ORMUtil.jsArray(pgArray, ORMUtil.jsUint8Array); } static jsArrayXMLDocument(pgArray) { return ORMUtil.jsArray(pgArray, ORMUtil.jsXMLDocument); } static pgArray(jsArray, pgElementFunc) { return jsArray!==null && jsArray!==undefined ? "{" + jsArray.map( (element,index) => element===null || element===undefined ? "null" : element instanceof Array ? ORMUtil.pgArray(element, pgElementFunc) : JSON.stringify(pgElementFunc(element)) ).join() + "}" : null; } static pgArrayPrimitive (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgPrimitive); } static pgArrayDate (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgDate); } static pgArrayTime (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgTime); } static pgArrayTimezoneOffset(jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgTimezoneOffset); } static pgArrayTimetz (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgTimetz); } static pgArrayTimestamp (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgTimestamp); } static pgArrayTimestamptz (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgTimestamptz); } static pgArrayInterval (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgInterval); } static pgArrayBytea (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgBytea); } static pgArrayJSON (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgJSON); } static pgArrayXML (jsArray) { return ORMUtil.pgArray(jsArray, ORMUtil.pgXML); } static #pgParam(jsValue) { console.log("pgValue: "+ jsValue); if (jsValue===null || jsValue===undefined) return null; if ((typeof jsValue)==="number" || (typeof jsValue)==="boolean") return jsValue; if (jsValue instanceof Date) return ORMUtil.pgTimestamptz(jsValue); if (jsValue instanceof Uint8Array) return ORMUtil.pgBytea(jsValue); if (jsValue instanceof XMLDocument) return ORMUtil.pgXML(jsValue); if (jsValue instanceof Record) return ORMUtil.pgRecord(jsValue); if (jsValue instanceof Array) return ORMUtil.pgArray(jsValue, ORMUtil.#pgParam); return JSON.stringify(jsValue); } static pgArrayParam(jsArray) { return jsArray!==null && jsArray!==undefined ? jsArray instanceof Array ? jsArray.map( element => ORMUtil.#pgParam(element) ) : [ORMUtil.#pgParam(jsArray)] : []; } static #compareNull (value1, value2, nullsFirst) { return value1===null ? value2!==null ? (nullsFirst ? -1 : +1) : 0 : (nullsFirst ? +1 : -1); } static compareNumber (number1, number2, desc, nullsFirst) { return number1!==null && number2!==null ? !desc ? number1-number2 : number2-number1 : ORMUtil.#compareNull(number1, number2, nullsFirst); } static compareString (string1, string2, desc, nullsFirst) { return string1!==null && string2!==null ? !desc ? string1.localeCompare(string2) : string2.localeCompare(string1) : ORMUtil.#compareNull(string1, string2, nullsFirst); } static compareBoolean(boolean1, boolean2, desc, nullsFirst) { return ORMUtil.compareNumber(boolean1!==null ? boolean1|0 : null, boolean2!==null ? boolean2|0 : null, desc, nullsFirst); } static compareDate (date1, date2, desc, nullsFirst) { return ORMUtil.compareNumber(date1!==null ? date1.getTime() : null, date2!==null ? date2.getTime() : null, desc, nullsFirst); } } function sendRequest(path, body) { let xhr = new XMLHttpRequest(); try { xhr.open("POST", path, false); xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); xhr.send(JSON.stringify(body)); } catch (error) { throw new ORMError(305, `Error on send HTTP request (path: ${path}): ${error.name} ${error.message}`); } if (xhr.readyState!=4) throw new ORMError(306, `Incorrect HTTP request state (${xhr.readyState})`); if (xhr.status!=200) throw new ORMError(307, `Incorrect HTTP request status (${xhr.status})`); let response = JSON.parse(xhr.responseText); if (!response.sucess) throw new ORMError(response.errorCode, response.errorText); return response; } function validateConnection(connection) { if (connection===null) throw new ORMError(308, "Connection is null"); }
Модуль /orm/[schema]/[Class].js
Module is editable, created on first call to pgorm.orm_relation_enable and is intended for overrides of existing methods (e.g. save)
Example:
// Module can be edited by changing field "module_source" of table "pgorm.orm_table" import { BaseInvoice,BaseInvoiceArray } from "/orm/public/base/BaseInvoice.js" export class Invoice extends BaseInvoice { } export class InvoiceArray extends BaseInvoiceArray { }
Модуль /orm/[schema]/base/Base[Class].js
Module contains methods for working with table and its description. Module is automatically updated when performing DDL operations on table. Edit of module is not provided.
Example:
// Module made automatically based on relation (table definition) and cannot be edited import { Relation,Column,Row,RowArray,Relationship,ORMConnection,ORMUtil,ORMError } from "/orm/pgorm-db.js" import { Invoice,InvoiceArray } from "/orm/public/Invoice.js" export class BaseInvoice extends Row { // Columns static #columnID = new Column("id", "int4", false, "ID", "number", Number, true, BaseInvoice.getRowClass, ORMUtil.validateNumber, ORMUtil.jsPrimitive, ORMUtil.pgPrimitive, null); static #columnDate = new Column("date", "date", false, "Date", null, Date, true, BaseInvoice.getRowClass, ORMUtil.validateDate, ORMUtil.jsDate, ORMUtil.pgDate, null); static #columnNumber = new Column("number", "varchar", false, "Number", "string", String, true, BaseInvoice.getRowClass, ORMUtil.validateString, ORMUtil.jsPrimitive, ORMUtil.pgPrimitive, null); static #columnAmount = new Column("amount", "numeric", false, "Amount", "number", Number, true, BaseInvoice.getRowClass, ORMUtil.validateNumber, ORMUtil.jsPrimitive, ORMUtil.pgPrimitive, null); static getColumnID() { return BaseInvoice.#columnID; } static getColumnDate() { return BaseInvoice.#columnDate; } static getColumnNumber() { return BaseInvoice.#columnNumber; } static getColumnAmount() { return BaseInvoice.#columnAmount; } // Relation (table definition) static #relation = new Relation("public", "invoice", null, [BaseInvoice.#columnID,BaseInvoice.#columnDate,BaseInvoice.#columnNumber,BaseInvoice.#columnAmount], [BaseInvoice.#columnID], function() { return Invoice; }, function() { return InvoiceArray; }, [], function() { return []; }); static getRelation() { return BaseInvoice.#relation; } // Row fields #ID = null; #ID$changed = false; #Date = null; #Date$changed = false; #Number = null; #Number$changed = false; #Amount = null; #Amount$changed = false; // Set values setID (value) { ORMUtil.validateNumber(value); this.#ID = value; this.#ID$changed = true; return this; } setDate (value) { ORMUtil.validateDate (value); this.#Date = value; this.#Date$changed = true; return this; } setNumber(value) { ORMUtil.validateString(value); this.#Number = value; this.#Number$changed = true; return this; } setAmount(value) { ORMUtil.validateNumber(value); this.#Amount = value; this.#Amount$changed = true; return this; } // Get values getID() { return this.#ID; } getDate() { return this.#Date; } getNumber() { return this.#Number; } getAmount() { return this.#Amount; } // Get change marks isChangedID() { return this.#ID$changed; } isChangedDate() { return this.#Date$changed; } isChangedNumber() { return this.#Number$changed; } isChangedAmount() { return this.#Amount$changed; } // Save row and get values (SQL statement: insert or update with returning) save(connection = ORMConnection.getDefault()) { return super.save(connection); } // Delete row and get values (SQL statement: delete with returning) delete(connection = ORMConnection.getDefault()) { super.delete(connection); } // Load one row by condition (SQL statement: select) static loadByCondition(condition, params = null, connection = ORMConnection.getDefault()) { return Row.loadByCondition(Invoice, connection, condition, params); } // Load row by primary key static load(ID, connection = ORMConnection.getDefault()) { return Invoice.loadByCondition("id=$1", [ID], connection); } // Load row by unique index "invoice_pkey" static loadByUnique$ID(ID, connection = ORMConnection.getDefault()) { return Invoice.loadByCondition("id=$1", [ID], connection); } // Initialize field values fetched from database _initialize(pgValues, rowExists) { this.#ID = ORMUtil.jsPrimitive(pgValues[0]); this.#ID$changed = false; this.#Date = ORMUtil.jsDate (pgValues[1]); this.#Date$changed = false; this.#Number = ORMUtil.jsPrimitive(pgValues[2]); this.#Number$changed = false; this.#Amount = ORMUtil.jsPrimitive(pgValues[3]); this.#Amount$changed = false; return super._initialize(rowExists); } } export class BaseInvoiceArray extends RowArray { // Get relation static getRelation() { return BaseInvoice.getRelation(); } // Load any row by condition (SQL statement: select) // If there is no condition, all row load static load(condition = null, params = null, connection = ORMConnection.getDefault()) { return RowArray.load(InvoiceArray, connection, condition, params); } // Sort by fields sortByID (desc = false, nullsFirst = false) { this.sort( (row1,row2) => ORMUtil.compareNumber(row1.getID(), row2.getID(), desc, nullsFirst) ); return this; } sortByDate (desc = false, nullsFirst = false) { this.sort( (row1,row2) => ORMUtil.compareDate (row1.getDate(), row2.getDate(), desc, nullsFirst) ); return this; } sortByNumber(desc = false, nullsFirst = false) { this.sort( (row1,row2) => ORMUtil.compareString(row1.getNumber(), row2.getNumber(), desc, nullsFirst) ); return this; } sortByAmount(desc = false, nullsFirst = false) { this.sort( (row1,row2) => ORMUtil.compareNumber(row1.getAmount(), row2.getAmount(), desc, nullsFirst) ); return this; } }
Command line
Command line options (after installation, can view them by executing pgorm --help):
[root@vds2157681 ~]# pgorm --help PGORM is web server for database PostgreSQL version 23.1.6, linux 64 bits Usage: pgorm start|execute|status|stop [OPTIONS] Parameter: start execute pgorm in new process execute execute pgorm in current process status print info about running pgorm stop stop pgorm Database options: -h HOSTNAME database server host (default: 5432) -p PORT database server port (default: 127.0.0.1) -d DBNAME database name (default: site) -U USERNAME superuser name (default: postgres) -W PASSWORD superuser password in PostgreSQL (if nessesary) HTTP options: -hd DIRECTORY site directory (default: /site) -hp PORT HTTP port (default: 80) Administration options: -ap PORT administration port (default: 1080) Logging options: -l FILE log file Info: -h, --help print this help Examples: pgorm start pgorm start -d sitedb -hd /mysite1 -l /tmp/pgorm.log