mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-11-15 22:34:51 +00:00
Use the empty string as special plugin name for ordinary tiddlers
Using NULL was working against the grain of SQL
This commit is contained in:
parent
863066d41f
commit
d4dec0ca65
@ -45,14 +45,14 @@ $tw.SqlFunctions = function(options) {
|
|||||||
sql: `
|
sql: `
|
||||||
DROP TABLE IF EXISTS plugins;
|
DROP TABLE IF EXISTS plugins;
|
||||||
CREATE TABLE plugins (
|
CREATE TABLE plugins (
|
||||||
plugintitle TEXT NOT NULL,
|
plugintitle TEXT NOT NULL, -- Empty string shoud be the highest priority
|
||||||
priority INTEGER NOT NULL,
|
priority INTEGER NOT NULL,
|
||||||
PRIMARY KEY(plugintitle)
|
PRIMARY KEY(plugintitle)
|
||||||
);
|
);
|
||||||
DROP TABLE IF EXISTS tiddlers;
|
DROP TABLE IF EXISTS tiddlers;
|
||||||
CREATE TABLE tiddlers (
|
CREATE TABLE tiddlers (
|
||||||
title TEXT NOT NULL ${COLLATION_CLAUSE},
|
title TEXT NOT NULL ${COLLATION_CLAUSE},
|
||||||
plugintitle TEXT, -- or NULL for non-shadow tiddlers
|
plugintitle TEXT NOT NULL, -- Empty string for tiddlers that are not part of a plugin
|
||||||
meta TEXT NOT NULL,
|
meta TEXT NOT NULL,
|
||||||
text TEXT NOT NULL,
|
text TEXT NOT NULL,
|
||||||
PRIMARY KEY(title,plugintitle)
|
PRIMARY KEY(title,plugintitle)
|
||||||
@ -61,7 +61,7 @@ $tw.SqlFunctions = function(options) {
|
|||||||
DROP TABLE IF EXISTS titles;
|
DROP TABLE IF EXISTS titles;
|
||||||
CREATE TABLE titles (
|
CREATE TABLE titles (
|
||||||
title TEXT NOT NULL ${COLLATION_CLAUSE},
|
title TEXT NOT NULL ${COLLATION_CLAUSE},
|
||||||
plugintitle TEXT, -- or NULL for non-shadow tiddlers
|
plugintitle TEXT NOT NULL, -- Empty string for tiddlers that are not part of a plugin
|
||||||
PRIMARY KEY(title)
|
PRIMARY KEY(title)
|
||||||
);
|
);
|
||||||
`
|
`
|
||||||
@ -70,7 +70,7 @@ $tw.SqlFunctions = function(options) {
|
|||||||
Debugging
|
Debugging
|
||||||
*/
|
*/
|
||||||
var statementLogTiddlersTable = self.db.prepare("select title, plugintitle, meta, text from tiddlers order by title, plugintitle;"),
|
var statementLogTiddlersTable = self.db.prepare("select title, plugintitle, meta, text from tiddlers order by title, plugintitle;"),
|
||||||
statementLogPluginsTable = self.db.prepare("select plugintitle, priority from plugins order by plugintitle;"),
|
statementLogPluginsTable = self.db.prepare("select plugintitle, priority from plugins order by priority;"),
|
||||||
statementLogTitlesTable = self.db.prepare("select title, plugintitle from titles order by title;");
|
statementLogTitlesTable = self.db.prepare("select title, plugintitle from titles order by title;");
|
||||||
function sqlLogTable(statement) {
|
function sqlLogTable(statement) {
|
||||||
let resultRows = [];
|
let resultRows = [];
|
||||||
@ -90,11 +90,12 @@ $tw.SqlFunctions = function(options) {
|
|||||||
Set the plugin priorities
|
Set the plugin priorities
|
||||||
*/
|
*/
|
||||||
this.sqlSetPluginPriorities = function(prioritisedPluginTitles) {
|
this.sqlSetPluginPriorities = function(prioritisedPluginTitles) {
|
||||||
|
const plugintitles = prioritisedPluginTitles.concat([""]);
|
||||||
self.db.exec({
|
self.db.exec({
|
||||||
sql: "DELETE FROM plugins"
|
sql: "DELETE FROM plugins"
|
||||||
});
|
});
|
||||||
let priority = 1;
|
let priority = 1;
|
||||||
for(const plugintitle of prioritisedPluginTitles) {
|
for(const plugintitle of plugintitles) {
|
||||||
self.db.exec({
|
self.db.exec({
|
||||||
sql: "insert or replace into plugins (plugintitle, priority) values ($plugintitle, $priority)",
|
sql: "insert or replace into plugins (plugintitle, priority) values ($plugintitle, $priority)",
|
||||||
bind: {
|
bind: {
|
||||||
@ -117,26 +118,21 @@ $tw.SqlFunctions = function(options) {
|
|||||||
INSERT OR REPLACE INTO titles (title, plugintitle)
|
INSERT OR REPLACE INTO titles (title, plugintitle)
|
||||||
SELECT
|
SELECT
|
||||||
t.title,
|
t.title,
|
||||||
CASE
|
(SELECT t2.plugintitle
|
||||||
WHEN t.null_count > 0 THEN NULL
|
FROM tiddlers AS t2
|
||||||
ELSE t.max_priority_plugintitle
|
JOIN plugins AS p ON t2.plugintitle = p.plugintitle
|
||||||
END AS plugintitle
|
WHERE t2.title = t.title
|
||||||
FROM (
|
ORDER BY p.priority DESC
|
||||||
SELECT
|
LIMIT 1
|
||||||
t.title,
|
) AS plugintitle
|
||||||
SUM(CASE WHEN t.plugintitle IS NULL THEN 1 ELSE 0 END) AS null_count,
|
FROM tiddlers AS t
|
||||||
MAX(p.priority) AS max_priority,
|
WHERE t.title = $title;
|
||||||
FIRST_VALUE(t.plugintitle) OVER (PARTITION BY t.title ORDER BY p.priority DESC) AS max_priority_plugintitle
|
|
||||||
FROM tiddlers t
|
|
||||||
LEFT JOIN plugins p ON t.plugintitle = p.plugintitle
|
|
||||||
WHERE t.title = $title
|
|
||||||
GROUP BY t.title
|
|
||||||
) AS t;
|
|
||||||
`);
|
`);
|
||||||
this.sqlSaveTiddler = function(tiddlerFields,plugintitle) {
|
this.sqlSaveTiddler = function(tiddlerFields,plugintitle) {
|
||||||
|
plugintitle = plugintitle || "";
|
||||||
querySaveTiddlerTableTiddlers.bind({
|
querySaveTiddlerTableTiddlers.bind({
|
||||||
$title: tiddlerFields.title,
|
$title: tiddlerFields.title,
|
||||||
$plugintitle: plugintitle || null,
|
$plugintitle: plugintitle,
|
||||||
$meta: JSON.stringify(Object.assign({},tiddlerFields,{title: undefined, text: undefined})),
|
$meta: JSON.stringify(Object.assign({},tiddlerFields,{title: undefined, text: undefined})),
|
||||||
$text: tiddlerFields.text || ""
|
$text: tiddlerFields.text || ""
|
||||||
});
|
});
|
||||||
@ -153,36 +149,22 @@ $tw.SqlFunctions = function(options) {
|
|||||||
*/
|
*/
|
||||||
var statementDeleteTiddlerDeleteFromTiddlers = self.db.prepare(`
|
var statementDeleteTiddlerDeleteFromTiddlers = self.db.prepare(`
|
||||||
DELETE FROM tiddlers
|
DELETE FROM tiddlers
|
||||||
WHERE title = $title AND plugintitle IS NULL;
|
WHERE title = $title AND plugintitle = $plugintitle;
|
||||||
`);
|
`);
|
||||||
var statementDeleteTiddlerFindShadow = self.db.prepare(`
|
var statementDeleteTiddlerFindShadow = self.db.prepare(`
|
||||||
WITH HighestPriority AS (
|
SELECT t.title, t.plugintitle
|
||||||
SELECT
|
FROM tiddlers AS t
|
||||||
plugintitle,
|
JOIN plugins AS p ON t.plugintitle = p.plugintitle
|
||||||
MAX(priority) AS max_priority
|
WHERE t.title = $title
|
||||||
FROM
|
ORDER BY p.priority DESC
|
||||||
plugins
|
LIMIT 1;
|
||||||
WHERE
|
|
||||||
plugintitle IS NOT NULL
|
|
||||||
GROUP BY
|
|
||||||
plugintitle
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
t.title,
|
|
||||||
t.plugintitle,
|
|
||||||
t.meta,
|
|
||||||
t.text
|
|
||||||
FROM
|
|
||||||
tiddlers AS t
|
|
||||||
JOIN
|
|
||||||
HighestPriority AS ho ON t.plugintitle = ho.plugintitle
|
|
||||||
WHERE
|
|
||||||
t.title = $title;
|
|
||||||
`);
|
`);
|
||||||
this.sqlDeleteTiddler = function(title) {
|
this.sqlDeleteTiddler = function(title,plugintitle) {
|
||||||
|
plugintitle = plugintitle || "";
|
||||||
// Delete the tiddler from the tiddlers table
|
// Delete the tiddler from the tiddlers table
|
||||||
statementDeleteTiddlerDeleteFromTiddlers.bind({
|
statementDeleteTiddlerDeleteFromTiddlers.bind({
|
||||||
$title: title
|
$title: title,
|
||||||
|
$plugintitle: plugintitle
|
||||||
});
|
});
|
||||||
statementDeleteTiddlerDeleteFromTiddlers.step();
|
statementDeleteTiddlerDeleteFromTiddlers.step();
|
||||||
statementDeleteTiddlerDeleteFromTiddlers.reset();
|
statementDeleteTiddlerDeleteFromTiddlers.reset();
|
||||||
@ -191,8 +173,8 @@ $tw.SqlFunctions = function(options) {
|
|||||||
$title: title
|
$title: title
|
||||||
});
|
});
|
||||||
if(statementDeleteTiddlerFindShadow.step()) {
|
if(statementDeleteTiddlerFindShadow.step()) {
|
||||||
// There is a corresponding shadow
|
|
||||||
var row = statementDeleteTiddlerFindShadow.get({});
|
var row = statementDeleteTiddlerFindShadow.get({});
|
||||||
|
statementDeleteTiddlerFindShadow.reset();
|
||||||
// Replace the tiddler with the shadow
|
// Replace the tiddler with the shadow
|
||||||
self.db.exec({
|
self.db.exec({
|
||||||
sql: "insert or replace into titles (title, plugintitle) values ($title, $plugintitle)",
|
sql: "insert or replace into titles (title, plugintitle) values ($title, $plugintitle)",
|
||||||
@ -202,8 +184,8 @@ $tw.SqlFunctions = function(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// There is no corresponding shadow
|
statementDeleteTiddlerFindShadow.reset();
|
||||||
// Delete the tiddler
|
// There is no shadow tiddler, so just delete the tiddler
|
||||||
self.db.exec({
|
self.db.exec({
|
||||||
sql: "delete from titles where title = $title",
|
sql: "delete from titles where title = $title",
|
||||||
bind: {
|
bind: {
|
||||||
@ -211,23 +193,22 @@ $tw.SqlFunctions = function(options) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
statementDeleteTiddlerFindShadow.reset();
|
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
Remove all shadow tiddlers
|
Remove all shadow tiddlers
|
||||||
*/
|
*/
|
||||||
this.sqlClearShadows = function() {
|
this.sqlClearShadows = function() {
|
||||||
self.db.exec({
|
self.db.exec({
|
||||||
sql: "delete from tiddlers where plugintitle is not null"
|
sql: "delete from tiddlers where plugintitle != '';"
|
||||||
});
|
});
|
||||||
self.db.exec({
|
self.db.exec({
|
||||||
sql: "delete from titles where plugintitle is not null"
|
sql: "delete from titles where plugintitle != '';"
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
Check whether a tiddler exists
|
Check whether a tiddler exists
|
||||||
*/
|
*/
|
||||||
var statementTiddlerExists = self.db.prepare(`select title from titles where title = $title and plugintitle is null;`)
|
var statementTiddlerExists = self.db.prepare(`select title from titles where title = $title and plugintitle = '';`)
|
||||||
this.sqlTiddlerExists = function(title) {
|
this.sqlTiddlerExists = function(title) {
|
||||||
statementTiddlerExists.bind({
|
statementTiddlerExists.bind({
|
||||||
$title: title
|
$title: title
|
||||||
@ -247,7 +228,7 @@ $tw.SqlFunctions = function(options) {
|
|||||||
select t.title, ti.meta, ti.text
|
select t.title, ti.meta, ti.text
|
||||||
FROM titles AS t
|
FROM titles AS t
|
||||||
JOIN tiddlers AS ti
|
JOIN tiddlers AS ti
|
||||||
ON t.title = ti.title AND (t.plugintitle = ti.plugintitle OR (t.plugintitle IS NULL AND ti.plugintitle IS NULL))
|
ON t.title = ti.title AND t.plugintitle = ti.plugintitle
|
||||||
WHERE t.title = $title;
|
WHERE t.title = $title;
|
||||||
`);
|
`);
|
||||||
this.sqlGetTiddler = function(title) {
|
this.sqlGetTiddler = function(title) {
|
||||||
@ -267,25 +248,12 @@ $tw.SqlFunctions = function(options) {
|
|||||||
Get the plugin from which a tiddler came
|
Get the plugin from which a tiddler came
|
||||||
*/
|
*/
|
||||||
var statementGetShadowSource = self.db.prepare(`
|
var statementGetShadowSource = self.db.prepare(`
|
||||||
WITH HighestPriority AS (
|
SELECT t.title, t.plugintitle
|
||||||
SELECT
|
FROM tiddlers AS t
|
||||||
plugintitle,
|
LEFT JOIN plugins AS p ON t.plugintitle = p.plugintitle
|
||||||
MAX(priority) AS max_priority
|
WHERE t.title = $title AND t.plugintitle <> ''
|
||||||
FROM
|
ORDER BY p.priority DESC
|
||||||
plugins
|
LIMIT 1;
|
||||||
WHERE
|
|
||||||
plugintitle IS NOT NULL
|
|
||||||
GROUP BY
|
|
||||||
plugintitle
|
|
||||||
)
|
|
||||||
SELECT
|
|
||||||
t.plugintitle
|
|
||||||
FROM
|
|
||||||
tiddlers AS t
|
|
||||||
JOIN
|
|
||||||
HighestPriority AS ho ON t.plugintitle = ho.plugintitle
|
|
||||||
WHERE
|
|
||||||
t.title = $title;
|
|
||||||
`);
|
`);
|
||||||
this.sqlGetShadowSource = function(title) {
|
this.sqlGetShadowSource = function(title) {
|
||||||
statementGetShadowSource.bind({
|
statementGetShadowSource.bind({
|
||||||
@ -319,7 +287,7 @@ $tw.SqlFunctions = function(options) {
|
|||||||
var statementAllShadowTitles = self.db.prepare(`
|
var statementAllShadowTitles = self.db.prepare(`
|
||||||
SELECT title
|
SELECT title
|
||||||
FROM tiddlers
|
FROM tiddlers
|
||||||
WHERE plugintitle IS NOT NULL
|
WHERE plugintitle != ''
|
||||||
ORDER BY title ${COLLATION_CLAUSE}
|
ORDER BY title ${COLLATION_CLAUSE}
|
||||||
`);
|
`);
|
||||||
this.sqlAllShadowTitles = function() {
|
this.sqlAllShadowTitles = function() {
|
||||||
@ -337,8 +305,8 @@ $tw.SqlFunctions = function(options) {
|
|||||||
var statementEachTiddler = self.db.prepare(`
|
var statementEachTiddler = self.db.prepare(`
|
||||||
SELECT t.title, ti.meta, ti.text
|
SELECT t.title, ti.meta, ti.text
|
||||||
FROM titles AS t
|
FROM titles AS t
|
||||||
LEFT JOIN tiddlers AS ti ON t.title = ti.title AND t.plugintitle IS NULL AND ti.plugintitle IS NULL
|
LEFT JOIN tiddlers AS ti ON t.title = ti.title AND t.plugintitle = ti.plugintitle
|
||||||
WHERE t.plugintitle IS NULL
|
WHERE t.plugintitle == ''
|
||||||
ORDER BY t.title ${COLLATION_CLAUSE}
|
ORDER BY t.title ${COLLATION_CLAUSE}
|
||||||
`);
|
`);
|
||||||
this.sqlEachTiddler = function(callback) {
|
this.sqlEachTiddler = function(callback) {
|
||||||
@ -356,7 +324,7 @@ $tw.SqlFunctions = function(options) {
|
|||||||
SELECT DISTINCT t.title, td.meta, td.text
|
SELECT DISTINCT t.title, td.meta, td.text
|
||||||
FROM titles AS t
|
FROM titles AS t
|
||||||
JOIN tiddlers AS td ON t.title = td.title
|
JOIN tiddlers AS td ON t.title = td.title
|
||||||
WHERE td.plugintitle IS NOT NULL
|
WHERE td.plugintitle != ''
|
||||||
ORDER BY t.title ${COLLATION_CLAUSE};
|
ORDER BY t.title ${COLLATION_CLAUSE};
|
||||||
`);
|
`);
|
||||||
this.sqlEachShadowTiddler = function(callback) {
|
this.sqlEachShadowTiddler = function(callback) {
|
||||||
|
@ -13,6 +13,7 @@ This file is spliced into the HTML file to be executed before the boot kernel ha
|
|||||||
$tw.Wiki = function(options) {
|
$tw.Wiki = function(options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
this.sqlFunctions = new $tw.SqlFunctions();
|
this.sqlFunctions = new $tw.SqlFunctions();
|
||||||
|
this.sqlFunctions.sqlSetPluginPriorities([]);
|
||||||
// Adapted version of the boot.js wiki store implementation follows
|
// Adapted version of the boot.js wiki store implementation follows
|
||||||
var self = this,
|
var self = this,
|
||||||
getTiddlerTitles = function() {
|
getTiddlerTitles = function() {
|
||||||
@ -158,7 +159,7 @@ $tw.Wiki = function(options) {
|
|||||||
var title = tiddler.fields.title;
|
var title = tiddler.fields.title;
|
||||||
if(title) {
|
if(title) {
|
||||||
// Save the new tiddler
|
// Save the new tiddler
|
||||||
self.sqlFunctions.sqlSaveTiddler(tiddler.getFieldStrings());
|
self.sqlFunctions.sqlSaveTiddler(tiddler.fields);
|
||||||
// Update caches
|
// Update caches
|
||||||
this.clearCache(title);
|
this.clearCache(title);
|
||||||
this.clearGlobalCache();
|
this.clearGlobalCache();
|
||||||
|
@ -104,6 +104,8 @@ test("Instantiating the database", function () {
|
|||||||
const titles = sqlFunctions.sqlAllShadowTitles();
|
const titles = sqlFunctions.sqlAllShadowTitles();
|
||||||
assert.equal(titles,result,message);
|
assert.equal(titles,result,message);
|
||||||
}
|
}
|
||||||
|
// Set priorities for the plugins we'll use
|
||||||
|
sqlFunctions.sqlSetPluginPriorities([]);
|
||||||
// Save and verify an ordinary tiddler
|
// Save and verify an ordinary tiddler
|
||||||
sqlFunctions.sqlSaveTiddler({
|
sqlFunctions.sqlSaveTiddler({
|
||||||
title: "HelloThere",
|
title: "HelloThere",
|
||||||
|
Loading…
Reference in New Issue
Block a user