UNPKG

@ngageoint/geopackage

Version:
417 lines 17.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __values = (this && this.__values) || function(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.SqljsAdapter = void 0; var rtree_sql_js_1 = __importDefault(require("rtree-sql.js")); /** * This adapter uses sql.js to execute queries against the GeoPackage database * @module db/sqljsAdapter * @see {@link http://kripken.github.io/sql.js/documentation/|sqljs} */ var SqljsAdapter = /** @class */ (function () { /** * @param {string|Buffer|Uint8Array} [filePath] string path to an existing file or a path to where a new file will be created or a url from which to download a GeoPackage or a Uint8Array containing the contents of the file, if undefined, an in memory database is created */ function SqljsAdapter(filePath) { this.filePath = filePath; } SqljsAdapter.setSqljsWasmLocateFile = function (locateFile) { SqljsAdapter.sqljsWasmLocateFile = locateFile; }; /** * Returns a Promise which, when resolved, returns a DBAdapter which has connected to the GeoPackage database file */ SqljsAdapter.prototype.initialize = function () { var _this = this; return new Promise(function (resolve, reject) { new Promise(function (resolve) { if (SqljsAdapter.SQL == null) { (0, rtree_sql_js_1.default)({ locateFile: SqljsAdapter.sqljsWasmLocateFile, }).then(function (SQL) { SqljsAdapter.SQL = SQL; resolve(SQL); }).catch(function (e) { reject(e); }); } else { resolve(SqljsAdapter.SQL); } }).then(function (SQL) { if (_this.filePath && typeof _this.filePath === 'string') { if (typeof process !== 'undefined' && process.version) { // eslint-disable-next-line @typescript-eslint/no-var-requires var fs = require('fs'); if (_this.filePath.indexOf('http') === 0) { // eslint-disable-next-line @typescript-eslint/no-var-requires var http = require('http'); http .get(_this.filePath, function (response) { if (response.statusCode !== 200) { return reject(new Error('Unable to reach url: ' + _this.filePath)); } var body = []; response.on('data', function (chunk) { return body.push(chunk); }); response.on('end', function () { var t = new Uint8Array(Buffer.concat(body)); _this.db = new SQL.Database(t); resolve(_this); }); }) .on('error', function (e) { return reject(e); }); } else { try { fs.statSync(_this.filePath); } catch (e) { _this.db = new SQL.Database(); // var adapter = new SqljsAdapter(db); return resolve(_this); } var filebuffer = fs.readFileSync(_this.filePath); var t = new Uint8Array(filebuffer); _this.db = new SQL.Database(t); return resolve(_this); } } else { // eslint-disable-next-line no-undef var xhr_1 = new XMLHttpRequest(); xhr_1.open('GET', _this.filePath, true); xhr_1.responseType = 'arraybuffer'; xhr_1.onload = function () { if (xhr_1.status !== 200) { return reject(new Error('Unable to reach url: ' + _this.filePath)); } var uInt8Array = new Uint8Array(xhr_1.response); _this.db = new SQL.Database(uInt8Array); return resolve(_this); }; xhr_1.onerror = function () { return reject(new Error('Error reaching url: ' + _this.filePath)); }; xhr_1.send(); } } else if (_this.filePath) { var byteArray = _this.filePath; _this.db = new SQL.Database(byteArray); return resolve(_this); } else { _this.db = new SQL.Database(); return resolve(_this); } }).catch(function (e) { reject(e); }); }); }; /** * Closes the connection to the GeoPackage */ SqljsAdapter.prototype.close = function () { this.db.close(); }; /** * Get the connection to the database file * @return {any} */ SqljsAdapter.prototype.getDBConnection = function () { return this.db; }; /** * Returns a Uint8Array containing the contents of the database as a file */ SqljsAdapter.prototype.export = function () { return __awaiter(this, void 0, void 0, function () { return __generator(this, function (_a) { return [2 /*return*/, this.db.export()]; }); }); }; /** * Registers the given function so that it can be used by SQL statements * @see {@link http://kripken.github.io/sql.js/documentation/#http://kripken.github.io/sql.js/documentation/class/Database.html#create_function-dynamic|sqljs create_function} * @param {string} name name of function to register * @param {Function} functionDefinition function to register * @return {module:db/sqljsAdapter~Adapter} this */ SqljsAdapter.prototype.registerFunction = function (name, functionDefinition) { this.db.create_function(name, functionDefinition); return this; }; /** * Gets one row of results from the statement * @see {@link http://kripken.github.io/sql.js/documentation/#http://kripken.github.io/sql.js/documentation/class/Statement.html#get-dynamic|sqljs get} * @see {@link http://kripken.github.io/sql.js/documentation/#http://kripken.github.io/sql.js/documentation/class/Statement.html#getAsObject-dynamic|sqljs getAsObject} * @param {String} sql statement to run * @param {Array|Object} [params] substitution parameters * @return {Object} */ SqljsAdapter.prototype.get = function (sql, params) { params = params || []; var statement = this.db.prepare(sql); statement.bind(params); var hasResult = statement.step(); var row; if (hasResult) { row = statement.getAsObject(); } statement.free(); return row; }; /** * Determines if a tableName exists in the database * @param {String} tableName * @returns {Boolean} */ SqljsAdapter.prototype.isTableExists = function (tableName) { var statement = this.db.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name=:name"); statement.bind([tableName]); var hasResult = statement.step(); var row; if (hasResult) { row = statement.getAsObject(); } statement.free(); return !!row; }; /** * Gets all results from the statement in an array * @param {String} sql statement to run * @param {Array|Object} [params] bind parameters * @return {Object[]} */ SqljsAdapter.prototype.all = function (sql, params) { var e_1, _a; var rows = []; var iterator = this.each(sql, params); try { for (var iterator_1 = __values(iterator), iterator_1_1 = iterator_1.next(); !iterator_1_1.done; iterator_1_1 = iterator_1.next()) { var row = iterator_1_1.value; rows.push(row); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (iterator_1_1 && !iterator_1_1.done && (_a = iterator_1.return)) _a.call(iterator_1); } finally { if (e_1) throw e_1.error; } } return rows; }; /** * Returns an Iterable with results from the query * @param {string} sql statement to run * @param {Object|Array} params bind parameters * @return {IterableIterator<Object>} */ SqljsAdapter.prototype.each = function (sql, params) { var _a; var statement = this.db.prepare(sql); statement.bind(params); return _a = {}, _a[Symbol.iterator] = function () { return this; }, _a.next = function () { if (statement.step()) { return { value: statement.getAsObject(), done: false, }; } else { statement.free(); return { value: undefined, done: true, }; } }, _a; }; /** * Runs the statement specified, returning information about what changed * @see {@link http://kripken.github.io/sql.js/documentation/#http://kripken.github.io/sql.js/documentation/class/Statement.html#run-dynamic|sqljs run} * @param {string} sql statement to run * @param {Object|Array} [params] bind parameters * @return {Object} object containing a changes property indicating the number of rows changed and a lastInsertROWID indicating the last inserted row */ SqljsAdapter.prototype.run = function (sql, params) { if (params && !(params instanceof Array)) { for (var key in params) { params['$' + key] = params[key]; } } this.db.run(sql, params); var lastId = this.db.exec('select last_insert_rowid();'); var lastInsertedId; if (lastId) { lastInsertedId = lastId[0].values[0][0]; } return { lastInsertRowid: lastInsertedId, changes: this.db.getRowsModified(), }; }; /** * Runs the specified insert statement and returns the last inserted id or undefined if no insert happened * @param {String} sql statement to run * @param {Object|Array} [params] bind parameters * @return {Number} last inserted row id */ SqljsAdapter.prototype.insert = function (sql, params) { if (params && !(params instanceof Array)) { for (var key in params) { params['$' + key] = params[key]; } } var statement = this.db.prepare(sql, params); statement.step(); statement.free(); var lastId = this.db.exec('select last_insert_rowid();'); if (lastId) { return lastId[0].values[0][0]; } else { return; } }; /** * Prepares a SQL statement * @param sql */ SqljsAdapter.prototype.prepareStatement = function (sql) { return this.db.prepare(sql); }; /** * Runs an insert statement with the parameters provided * @param {any} statement statement to run * @param {Object|Array} [params] bind parameters * @return {Number} last inserted row id */ SqljsAdapter.prototype.bindAndInsert = function (statement, params) { if (params && !(params instanceof Array)) { for (var key in params) { params['$' + key] = typeof params[key] === 'undefined' ? null : params[key]; } } return statement.run(params).lastInsertRowid; }; /** * Closes a prepared statement * @param statement */ SqljsAdapter.prototype.closeStatement = function (statement) { statement.free(); }; /** * Runs the specified delete statement and returns the number of deleted rows * @param {String} sql statement to run * @param {Object|Array} [params] bind parameters * @return {Number} deleted rows */ SqljsAdapter.prototype.delete = function (sql, params) { var rowsModified; var statement = this.db.prepare(sql, params); statement.step(); rowsModified = this.db.getRowsModified(); statement.free(); return rowsModified; }; /** * Drops the table * @param {String} table table name * @return {Boolean} indicates if the table was dropped */ SqljsAdapter.prototype.dropTable = function (table) { var response = this.db.exec('DROP TABLE IF EXISTS "' + table + '"'); this.db.exec('VACUUM'); return !!response; }; /** * Counts rows that match the query * @param {String} tableName table name from which to count * @param {String} [where] where clause * @param {Object|Array} [whereArgs] where args * @return {Number} count */ SqljsAdapter.prototype.count = function (tableName, where, whereArgs) { var sql = 'SELECT COUNT(*) as count FROM "' + tableName + '"'; if (where) { sql += ' where ' + where; } return this.get(sql, whereArgs).count; }; SqljsAdapter.prototype.transaction = function (func) { this.db.exec('BEGIN TRANSACTION'); try { func(); this.db.exec('COMMIT TRANSACTION'); } catch (e) { this.db.exec('ROLLBACK TRANSACTION'); throw e; } }; SqljsAdapter.sqljsWasmLocateFile = function (filename) { return filename; }; return SqljsAdapter; }()); exports.SqljsAdapter = SqljsAdapter; //# sourceMappingURL=sqljsAdapter.js.map