FESI language extensions - File I/O
Author: Jean-MarcLugrin
Description: Describe the FESI EcmaScript interpreter extensions to access File I/O capabilities
Keywords: EcmaScript, JavaScript, JScript, Java, extension

| Free EcmaScript Interpreter. A JavaScript interpreter written in Java.

Language extensions - Database

The `Database` extension is always loaded by the interactive interpreter, and provide access to database functions via `JDBC`. The database mechanism is patterned after the Infobus 1.1 database access interface, but it has been adapted to be well integrated in EcmaScript. The more general `JDBC` access is still available using the JavaAcess extension, but the Database extension provides a simple to use access, more suitable to a scripting language.

SQL errors can be detected - in general a false is returned in case of error, and the function getLastError can be used to the error object (which is a Java exception). Programming errors (as reading after the last record was signaled, or reading on a released connection) directly throws an exception.

The error handling capability allows to use it as interactive script without having to worry about errors - a message will be generated at the first command following an error. But it is possible to check for error status as well, and therefore trap all SQL errors (EcmaScript programming errors are not trappable).

### Global database object

A global `Database` object is used to implement access to the databases via `JDBC`. The `Database` object is a prototype, which can be instanciated for various specific databases. The instanciated objects implement the `DbAccess` protocol of the InfoBus, allowing to connect to and disconnect from the database. For example a new database access iobject may be created by:

> `db = new Database("com.sybase.jdbc.SybDriver");`

The JDBC driver does not have to be in the path, the two argument version of the Database creation routine allows to specify the path of the driver, as in:

> `db = new Database("myorg.com.ourDriver","d:\\java\\drivers\\ourDriver")`

This is very useful during development, but all referenced routines must then be reachable from that path or from the default path. Note that the naming system of java creates a driver which is different from a driver which would be loaded from the default path.

It is recommended to test in an error occured by calling `getLastError` on the just created database object. It should returned `undefined`. Otherwise the database object will generate an error on its first usage if it was not initialized correctly.

The string representation of a Database object includes its state (connected or disconnected).

### DbAccess protocol

As implemented in `FESI`, the `DbAccess` protocol includes the following routines:

`connect(url)`
  Open a new connection for the specified `URL` on the `DbAccess` object. Generates an error if the driver was not correctly initialized, returns `true` if connection is successful, `false` otherwise. Use `getLastError` to get details on the error.
`connect(url, userName, password)`
  Open a new connection for the specified `URL`, with specified user name and password, on the `DbAccess` object. Generates an error if the driver was not correctly initialized, returns `true` if connection is successful, `false` otherwise. Use `getLastError` to get details on the error.
`disconnect()`
  Close a connection (do nothing if not connected). Generates an error if the driver was not correctly initialized, returns `true` if successful or already disconnected, `false` in case of error. Use `getLastError` to get details in case of error.
`getLastError()`
  Return the last error which occured when connecting or executing a statement, undefined if none.
`getMetaData()`
  Return the meta data attached to the connection.
`release()`
  Equivalent to `disconnect`, but does not return a status and alway succeed. Usually this will release any associated `RowSet`.
`executeRetrieval(sqlString)`
  Used to implement `SELECT` and other value returning statements. Return a `RowSet` object implementing the `RowsetAccess` protocol if the request is successful. Returns `false` otherwise. Additional arguments are ignored, and data is always returned as a `RowsetAccess`. The cursor is positioned before the fist row. If `false` was returned, `getLastError` may be called on the database object to get the error information. Note that an error is generated (rather than returning a status) if the connection was not successful.
`executeCommand(sqlString)`
  Used to implement `INSERT`, `UPDATE`, ddl statements and other non value returning statements. Returns the number of rows impacted if the request is successful. Returns `false` otherwise. If `false` was returned, `getLastError` may be called on the database object to get the error information. Note that an error is generated (rather than returning a status) if the connection was not successful.

### RowAccess protocol (RowSet object)

As implemented in `FESI`, the `RowSetAccess` protocol includes the following routines:

`next()`
  Get the next row of results, return true if there is a next row, false otherwise. Note that `next` must be called before the first row can be accesses.
`hasMoreRows()`
  Optimistic view of the possibility that more rows are present. Currently only returns `false` if `next` returned false.It is possible to call this routine at any time.
`getLastError()`
  Return the last error which occured when connecting or executing a statement, `null` (which test as `false`) if none.
`getMetaData()`
  Return the meta data attached to the row set.
`release()`

  Release the resources attached to this RwoSet object. The object should not be accessed after it has been released.The use of release is not mandatory, but is recommended as otherwise the resources (which may include large cache and a database connection) is not reclaimed before the next garbage collection, in this only if it is not reachable anymore.
`getColumnCount()`
  Get the number of columns of this result, identical to the `length` attribute. It is possible to call this routine before the first record is fetched.

`getColumnName()`
  Get the name of a column, in a way which is always working. The names can be accessed as properties, but they are shadowed by the functions and properties of the `RowSetAccess` prototype object. It is possible to call this routine before the first record is fetched.

`getColumnDatatypeNumber()`
  Get the number of the datatype associated with the column. See the jdbc documentation for details. It is possible to call this routine before the first record is fetched.
`getColumnDatatypeName()`
  Get the name of the datatype associated with the column. See the jdbc documentation for details. Some database do not return a valid name, in that case undefined is returned. It is possible to call this routine before the first record is fetched.
`getColumnItem(name)`
  Get the value of a column by its name (the value can be accessed by number simply indexing them - this is not faster than by name for `FESI`). The proper value is returned even if the name is used for a property of the `RowSetAccess` protocol, as `next` or `length`. A record must be available (that is `next` must have been called at least once).

In addition, the RowSet will return any column name property as its value, any index as the value of the corresponding column, and enumerate column names. The enumeration will only contain the column names, not any property added to the prototype or the object itself. However the internal names (`valueOf`, `toString`, `length`), the properties of the prototype (including the routines of the `RowSetAccess` protocol) takes precedence over the name of columns when accessed as a property. The usage of indexed access or of the routine `getColumnItem` is therefore prefered.

The `RowSet` string representation includes the SQL statement and its logical position if at start or at end.

### Examples

`db= new Database("com.sybase.jdbc.SybDriver");`
`db.connect("jdbc:sybase:Tds:charlie:7078","dba","sql")`

`result = db.executeRetrieval("select * from employee")`
`while (result.next()) {`
`writeln("record has " + result.length + " columns");`
`for (c in result) {`
`writeln("Column: " + c + ": " + result.getColumnItem(c));`
`}`
`}`
`db.disconnect();`

Return to the main page

Last update: 22 January 1999