read online nwjs nodejs node instal consola javascript sqlite

online - sqlite local javascript



¿Es posible crear una función javascript definida por el usuario en sqlite? (2)

Sí. Es posible llamar a las funciones de JavaScript

//(thanks to Mirnal Kant, SQLManager) //Version 2 -- Prevent Firefox crashing // -- Suspect a problem with continual creation of Regex objects var g_RegExpString = null; var g_RegExp = null; //functions to be created for the db var smDbFunctions = { // (0) = Regex Expression // (1) = Column value to test regexp: { onFunctionCall: function(val) { if (g_RegExp == null || val.getString(0) != g_RegExpString) { g_RegExpString = val.getString(0); g_RegExp = new RegExp(g_RegExpString); } if (val.getString(1).match(g_RegExp)) return 1; else return 0; } } };

después de instanciar una instancia de SQLite:

Database.createFunction("REGEXP", 2, smDbFunctions.regexp);

FONDO:

  • Firefox 3 incluye SQLite versión 3.5.9. Firefox también permite extensiones, que están escritas en javascript y pueden llamar al motor SQLite incorporado.

  • Como era de esperar, ejecutando la siguiente instrucción SQL ''SELECT'' TEXT "REGEXP" T * "; '' da un error, ya que no hay una función REGEXP incluida de forma nativa en SQLite.

  • JavaScript incluye una función integrada de expresiones regulares.

  • SQLite permite extensiones cargables a través de SELECT load_extension (''filename'');

PREGUNTA: ¿Es posible cargar una extensión en SQLite que está escrita en javascript que puede hacer REGEXP?


De lo que Noah está hablando se ha incluido en el add-on de SQLite Manager para Firefox.

Cuando inicie este complemento, puede hacer clic en el icono etiquetado como f (x) para abrir la pestaña de funciones definidas por el usuario. A partir de ahí, seleccione un directorio en el que tenga una base de datos SQLite llamada smFunctions.sqlite, con el siguiente esquema:

CREATE TABLE "functions" ( "name" TEXT PRIMARY KEY NOT NULL , "body" TEXT NOT NULL , "argLength" INTEGER , "aggregate" INTEGER NOT NULL DEFAULT 0 , "enabled" INTEGER NOT NULL DEFAULT 1 , "extraInfo" TEXT ); CREATE TABLE "aggregateFunctions" ( "name" TEXT PRIMARY KEY NOT NULL , "argLength" INTEGER , "onStepBody" TEXT , "onFinalBody" TEXT , "enabled" INTEGER NOT NULL DEFAULT 1 , "extraInfo" TEXT );

Dentro de esa tabla puedes definir funciones personalizadas. Los parámetros se pasarán como una matriz llamada aValues . Por ejemplo:

INSERT INTO "functions" ("name", "body", "argLength", "aggregate", "enabled", "extraInfo") VALUES(''regexp_replace'' ,''// exemple : SELECT regexp_replace(''''FOOBAR'''',''''o+'''',''''a'''',''''gi'''') var input = new String(aValues.getString(0)); var regex = new String(aValues.getString(1)); var substitute = new String(aValues.getString(2)); var flags = new String(aValues.getString(3)); return input.replace(new RegExp(regex,flags), substitute); '' ,4 ,0 ,1 ,'''' );

  • si argLength == -1, entonces no hay límite en la cantidad de argumentos. Puede obtener el conteo con aValues.numEntries .
  • Puede usar aValues.getTypeOfIndex(i) para conocer el tipo de argumento: 0 => NULL, 1 => Integer ( aValues.getInt64(i) ), 2 => Real ( aValues.getDouble(i) ), 3 = > Cadena, ver ejemplo.

Para las funciones agregadas puede usar this._store como una matriz inicialmente vacía para empujar los elementos durante la fase onStepBody, y leer desde allí onStepFinal para calcular el resultado final.

A continuación se muestra un script bash que creará smFunctions.sqlite con algunas funciones personalizadas (este es un .dump de mi propio smFunctions.sqlite):

sqlite smFunctions.sqlite << EOF PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE "functions" ("name" TEXT PRIMARY KEY NOT NULL, "body" TEXT NOT NULL, "argLength" INTEGER, "aggregate" INTEGER NOT NULL DEFAULT 0, "enabled" INTEGER NOT NULL DEFAULT 1, "extraInfo" TEXT); INSERT INTO "functions" VALUES(''accumulate'',''var sum = 0; for (var j = 0; j < aValues.numEntries; j++) { sum += aValues.getInt32(j); } return sum; '',-1,0,1,NULL); INSERT INTO "functions" VALUES(''concatenate'',''var valArr = []; var delim = new String(aValues.getString(0)); for (var j = 1; j < aValues.numEntries; j++) { switch (aValues.getTypeOfIndex(j)) { case 0: //NULL valArr.push(null); break; case 1: //INTEGER valArr.push(aValues.getInt64(j)); break; case 2: //REAL valArr.push(aValues.getDouble(j)); break; case 3: //TEXT default: valArr.push(aValues.getString(j)); } } return valArr.join(delim);'',-1,0,1,NULL); INSERT INTO "functions" VALUES(''regexp_match'',''var regExp = new RegExp(aValues.getString(0)); var strVal = new String(aValues.getString(1)); if (strVal.match(regExp)) { return 1; } else { return 0; } '',2,0,1,NULL); INSERT INTO "functions" VALUES(''regexp_replace'',''// exemple : regexp_replace(''''toto'''',''''o+'''',''''a'''',''''g'''') var input = new String(aValues.getString(0)); var regex = new String(aValues.getString(1)); var substitute = new String(aValues.getString(2)); var flags = new String(aValues.getString(3)); return input.replace(new RegExp(regex,flags), substitute); '',4,0,1,NULL); INSERT INTO "functions" VALUES(''instr'',''var char = new String(aValues.getString(0)); var str = new String(aValues.getString(1)); return str.indexOf(char, 0) + 1;'',2,0,1,NULL); INSERT INTO "functions" VALUES(''rinstr'',''var char = new String(aValues.getString(0)); var str = new String(aValues.getString(1)); return str.lastIndexOf(char) + 1; '',2,0,1,NULL); CREATE TABLE "aggregateFunctions" ("name" TEXT PRIMARY KEY NOT NULL, "argLength" INTEGER, "onStepBody" TEXT, "onFinalBody" TEXT, "enabled" INTEGER NOT NULL DEFAULT 1, "extraInfo" TEXT); INSERT INTO "aggregateFunctions" VALUES(''stdDev'',1,''this._store.push(aValues.getInt32(0));'',''var iLength = this._store.length; let total = 0; this._store.forEach(function(elt) { total += elt }); let mean = total / iLength; let data = this._store.map(function(elt) { let value = elt - mean; return value * value; }); total = 0; data.forEach(function(elt) { total += elt }); this._store = []; return Math.sqrt(total / iLength);'',1,NULL); INSERT INTO "aggregateFunctions" VALUES(''longest_prefix'',1,''this._store.push(aValues.getString(0));'',''if (this._store.length == 0) { return ""; } var prefix = this._store[0]; var prefixLen = prefix.length; for (var i = 1; i < this._store.length && prefixLen > 0; i++) { var word = this._store[i]; // The next line assumes 1st char of word and prefix always match. // Initialize matchLen to -1 to test entire word. var matchLen = 0; var maxMatchLen = Math.min(word.length, prefixLen); while (++matchLen < maxMatchLen) { if (word.charAt(matchLen) != prefix.charAt(matchLen)) { break; } } prefixLen = matchLen; } return prefix.substring(0, prefixLen);'',1,NULL); COMMIT; EOF