changeset 1395:9dfff82dfc59

finish postgres work
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 09 Sep 2019 01:22:23 -0600
parents 8fe777ba5045
children a5f61890ad84
files conv.txt examples/blog/src/lib/Db.luan src/luan/modules/Luan.luan src/luan/modules/lucene/Lucene.luan src/luan/modules/lucene/LuceneIndex.java src/luan/modules/lucene/Web_search.luan website/src/manual.html
diffstat 7 files changed, 159 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/conv.txt	Sun Sep 08 22:13:08 2019 -0600
+++ b/conv.txt	Mon Sep 09 01:22:23 2019 -0600
@@ -1,3 +1,4 @@
+Lucene.index
 stringify
 
 (%>
--- a/examples/blog/src/lib/Db.luan	Sun Sep 08 22:13:08 2019 -0600
+++ b/examples/blog/src/lib/Db.luan	Mon Sep 09 01:22:23 2019 -0600
@@ -8,15 +8,19 @@
 local Db = {}
 
 local postgres_spec = Hosting.postgres_spec and Hosting.postgres_spec()
-if postgres_spec ~= nil then
-	function postgres_spec.completer(doc)
-		return doc
-	end
+
+local function completer(doc)
+	return doc
 end
 
 function Db.new(lucene_dir)
 	local dir = Io.uri(lucene_dir)
-	local db = Lucene.index( dir, Lucene.type.english, {"subject","content"}, postgres_spec )
+	local db = Lucene.index( dir, {
+		default_type = Lucene.type.english
+		default_fields = {"subject","content"}
+		completer = completer
+		postgres_spec = postgres_spec
+	} )
 	
 --	this is how you index a field
 --	db.indexed_fields.post_date = Lucene.type.long
--- a/src/luan/modules/Luan.luan	Sun Sep 08 22:13:08 2019 -0600
+++ b/src/luan/modules/Luan.luan	Mon Sep 09 01:22:23 2019 -0600
@@ -33,8 +33,8 @@
 
 Luan.VERSION = Luan.do_file "classpath:luan/version.luan"
 
-function Luan.eval(s,source_name)
-	return Luan.load( "return "..s, source_name or "eval" )()
+function Luan.eval(s,source_name,env)
+	return Luan.load( "return "..s, source_name or "eval", env )()
 end
 
 return Luan
--- a/src/luan/modules/lucene/Lucene.luan	Sun Sep 08 22:13:08 2019 -0600
+++ b/src/luan/modules/lucene/Lucene.luan	Mon Sep 09 01:22:23 2019 -0600
@@ -35,16 +35,20 @@
 
 Lucene.literal = SaneQueryParser.literal
 
-function Lucene.index(index_dir,default_type,default_fields,postgres_spec)
+-- function Lucene.index(index_dir,default_type,default_fields)
+
+function Lucene.index(index_dir,options)
 	type(index_dir)=="table" or error "index_dir must be table"
 	index_dir.to_uri_string and matches(index_dir.to_uri_string(),"^file:") or error "must be file"
-	postgres_spec==nil or type(postgres_spec)=="table" or error "postgres_spec must be table"
+	options = options or {}
+	options.postgres_spec==nil or type(options.postgres_spec)=="table" or error "postgres_spec must be table"
+	options.completer==nil or type(options.completer)=="function" or error "completer must be table"
 	local index = {}
 	index.dir = index_dir
-	local java_index, closer = LuceneIndex.getLuceneIndex(index_dir.java.file,default_type,default_fields,postgres_spec)
+	local java_index, closer = LuceneIndex.getLuceneIndex(index_dir.java.file,options.default_type,options.default_fields,options.completer,options.postgres_spec)
 	index.java = java_index
 	index.closer = closer or error()
-	index.completer = postgres_spec and postgres_spec.completer
+	index.completer = options.completer
 
 	index.indexed_fields = {}
 	local mt = {}
--- a/src/luan/modules/lucene/LuceneIndex.java	Sun Sep 08 22:13:08 2019 -0600
+++ b/src/luan/modules/lucene/LuceneIndex.java	Mon Sep 09 01:22:23 2019 -0600
@@ -118,14 +118,14 @@
 
 	private static Map<String,LuceneIndex> indexes = new HashMap<String,LuceneIndex>();
 
-	public static Object[] getLuceneIndex(Luan luan,File indexDir,FieldParser defaultFieldParser,String[] defaultFields,LuanTable postgresSpec)
+	public static Object[] getLuceneIndex(Luan luan,File indexDir,FieldParser defaultFieldParser,String[] defaultFields,LuanFunction completer,LuanTable postgresSpec)
 		throws LuanException, IOException, ClassNotFoundException, SQLException
 	{
 		String key = indexDir.getCanonicalPath();
 		synchronized(indexes) {
 			LuceneIndex li = indexes.get(key);
 			if( li == null ) {
-				li = new LuceneIndex(luan,indexDir,defaultFieldParser,defaultFields,key,postgresSpec);
+				li = new LuceneIndex(luan,indexDir,defaultFieldParser,defaultFields,key,completer,postgresSpec);
 				li.openCount = 1;
 				indexes.put(key,li);
 			} else {
@@ -169,7 +169,7 @@
 
 	private final PostgresBackup postgresBackup;
 
-	private LuceneIndex(Luan luan,File indexDir,FieldParser defaultFieldParser,String[] defaultFields,String key,LuanTable postgresSpec)
+	private LuceneIndex(Luan luan,File indexDir,FieldParser defaultFieldParser,String[] defaultFields,String key,LuanFunction completer,LuanTable postgresSpec)
 		throws LuanException, IOException, ClassNotFoundException, SQLException
 	{
 		this.luanLogger = luan.getLogger(LuceneIndex.class);
@@ -190,8 +190,9 @@
 		if( postgresSpec == null ) {
 			postgresBackup = null;
 		} else {
+			if( completer == null )
+				throw new LuanException("completer is required for postgres_spec");
 			Map spec = postgresSpec.asMap();
-			LuanFunction completer = Utils.removeRequiredFunction(spec,"completer");
 			postgresBackup = new PostgresBackup(luan,spec);
 			if( postgresBackup != null ) {
 				if( !wasCreated && postgresBackup.wasCreated ) {
@@ -876,6 +877,7 @@
 			long nextId = postgresBackup.maxId() + 1;
 			postgresBackup.restoreLucene(this);
 			id = idLim = nextId;
+			saveNextId(nextId);
 			ok = true;
 			writer.commit();
 		} finally {
@@ -906,6 +908,7 @@
 	}
 
 	private void checkPostgres(LuanFunction completer) throws IOException, SQLException, LuanException {
+		luanLogger.info("start postgres check");
 		final PostgresBackup.Checker postgresChecker;
 		final IndexSearcher searcher;
 		writeLock.lock();
--- a/src/luan/modules/lucene/Web_search.luan	Sun Sep 08 22:13:08 2019 -0600
+++ b/src/luan/modules/lucene/Web_search.luan	Mon Sep 09 01:22:23 2019 -0600
@@ -5,18 +5,22 @@
 local range = Luan.range or error()
 local to_string = Luan.to_string or error()
 local stringify = Luan.stringify or error()
+local eval = Luan.eval or error()
 local Io = require "luan:Io.luan"
 local Http = require "luan:http/Http.luan"
 local String = require "luan:String.luan"
 local string_to_number = String.to_number or error()
 local Html = require "luan:Html.luan"
+local html_encode = Html.encode or error()
+local Number = require "luan:Number.luan"
 
 
 local Web_search = {}
 
-local function style() %>
+local function style()
+%>
 			body {
-				font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+				font-family: sans-serif;
 				margin: 2em 5%;
 			}
 			h2 {
@@ -28,53 +32,38 @@
 				display: inline-block;
 				margin-right: .5em;
 			}
-<%
-end
-
-local function form() %>
-<!doctype html>
-<html>
-	<head>
-		<title>Lucene Query</title>
-		<style>
-			<% style() %>
-			input {
+			input, textarea {
 				margin-top: 1em;
-			}
-			input[type="text"] {
 				font: inherit;
-				padding: .5em .8em;
-				border-radius: 8px;
-				border-style: groove;
-			}
-			input[type="text"]:focus {
-				border-color: #66afe9;
-				outline: none;
 			}
 			span[tip] {
 				color: #888;
 				font-size: smaller;
-				margin-left: .5em;
 			}
 			input[type="submit"] {
-				color: white;
-				background: #337ab7;
-				border-color: #337ab7;
-				font: inherit;
+				cursor: pointer;
 				padding: .5em;
 				border-radius: 4px;
 			}
-			input[type="submit"]:hover {
-				background: #236aa7 !important;
-			}
+<%
+end
+
+local function form()
+%>
+<!doctype html>
+<html>
+	<head>
+		<title>Lucene</title>
+		<style>
+<%			style() %>
 		</style>
 	</head>
 	<body>
 		<h2>Lucene Query</h2>
-		<form horizontal method="post">
+		<form>
 			<div>
 				<label>Query:</label>
-				<input type=text name="query" size="80" autofocus />
+				<input type=text name="query" size="80" autofocus>
 			</div>
 			<div>
 				<label></label>
@@ -82,11 +71,11 @@
 			</div>
 			<div>
 				<label>Max Rows:</label>
-				<input type=text name="rows" value="100" size="3" maxlength="5" />
+				<input type=text name="rows" value="100" size="3" maxlength="5">
 			</div>
 			<div>
 				<label>Sort:</label>
-				<input type=text name="sort" size="60" />
+				<input type=text name="sort" size="60">
 			</div>
 			<div>
 				<label></label>
@@ -94,21 +83,49 @@
 			</div>
 			<div>
 				<label></label>
-				<input type="submit" />
+				<input type="submit">
 			</div>
 		</form>
 	</body>
 </html>
-<% end
+<%
+end
 
 
-local function result(query,sort,headers,table) %>
+local function index_of(tbl,val)
+	for i, v in ipairs(tbl) do
+		if v == val then
+			return i
+		end
+	end
+	local n = #tbl + 1
+	tbl[n] = val
+	return n
+end
+
+local function result(index)
+	local query = Http.request.parameters.query
+	local rows = string_to_number(Http.request.parameters.rows)
+	local sort = Http.request.parameters.sort
+	local results = index.search(query,1,rows,{sort=sort})
+	local headers = {}
+	local table = {}
+	for _, doc in ipairs(results) do
+		local row = {}
+		for field, value in pairs(doc) do
+			row[index_of(headers,field)] = value
+		end
+		row.doc = doc
+		table[#table+1] = row
+	end
+	local can_edit = index.completer ~= nil
+%>
 <!doctype html>
 <html>
 	<head>
-		<title>Lucene Query</title>
+		<title>Lucene</title>
 		<style>
-			<% style() %>
+<%			style() %>
 			table {
 				border-collapse: collapse;
 				width: 100%;
@@ -122,42 +139,88 @@
 		</style>
 	</head>
 	<body>
-		<h2>Lucene Query Results</h2>
-		<p><label>Query:</label> <b><%=Html.encode(to_string(query))%></b></p>
-		<p><label>Sort:</label> <b><%=Html.encode(to_string(sort))%></b></p>
+		<h2>Lucene Results</h2>
+		<p><label>Query:</label> <b><%=html_encode(to_string(query))%></b></p>
+		<p><label>Sort:</label> <b><%=html_encode(to_string(sort))%></b></p>
 		<table>
 			<tr>
 				<th></th>
-				<% for _, header in ipairs(headers) do %>
+<%				for _, header in ipairs(headers) do %>
 					<th><%=header%></th>
-				<% end %>
+<%				end %>
 			</tr>
-			<% for i, row in ipairs(table) do %>
+<%
+			for i, row in ipairs(table) do
+				local id = row.doc.id
+%>
 				<tr>
-					<td><%=i%></td>
-					<%
+					<td>
+<%					if can_edit and id~=nil then %>
+						<a href="?id=<%=id%>"><%=i%></a>
+<%					else %>
+						<%=i%>
+<%					end %>
+					</td>
+<%
 					for col in range(1, #headers) do
 						local val = row[col]
 						%><td><%= val and stringify(val) or "" %></td><%
 					end
-					%>
+%>
 				</tr>
-			<% end %>
+<%			end %>
 		</table>
 	</body>
 </html>
-<% end
+<%
+end
 
 
-local function index_of(tbl,val)
-	for i, v in ipairs(tbl) do
-		if v == val then
-			return i
-		end
-	end
-	local n = #tbl + 1
-	tbl[n] = val
-	return n
+local function edit(index)
+	local id = string_to_number(Http.request.parameters.id)
+	local doc = index.get_document("id:"..id)
+	doc = stringify(doc,{strict=true,number_types=true})
+%>
+<!doctype html>
+<html>
+	<head>
+		<title>Lucene</title>
+		<style>
+<%			style() %>
+		</style>
+	</head>
+	<body>
+		<h2>Lucene Edit</h2>
+		<form action="?" method=post>
+			<div><textarea name="doc" rows="20" cols="90" autofocus><%=html_encode(doc)%></textarea></div>
+			<div><input type="submit" value="Update"></div>
+		</form>
+	</body>
+</html>
+<%
+end
+
+
+local function update(index)
+	local doc = Http.request.parameters.doc
+	local completer = index.completer or error()
+	doc = eval( doc, "lucene", Number )
+	doc = completer(doc)
+	index.save(doc)
+%>
+<!doctype html>
+<html>
+	<head>
+		<title>Lucene</title>
+		<style>
+<%			style() %>
+		</style>
+	</head>
+	<body>
+		<h2>Lucene Updated</h2>
+	</body>
+</html>
+<%
 end
 
 
@@ -167,23 +230,15 @@
 	return function()
 		Io.stdout = Http.response.text_writer()
 		local query = Http.request.parameters.query
-		if query == nil then
+		if Http.request.parameters.query ~= nil then
+			result(index)
+		elseif Http.request.parameters.id ~= nil then
+			edit(index)
+		elseif Http.request.parameters.doc ~= nil then
+			update(index)
+		else
 			form()
-			return
 		end
-		local rows = string_to_number(Http.request.parameters.rows)
-		local sort = Http.request.parameters.sort
-		local results = index.search(query,1,rows,{sort=sort})
-		local headers = {}
-		local table = {}
-		for _, doc in ipairs(results) do
-			local row = {}
-			for field, value in pairs(doc) do
-				row[index_of(headers,field)] = value
-			end
-			table[#table+1] = row
-		end
-		result(query,sort,headers,table)
 	end
 
 end
--- a/website/src/manual.html	Sun Sep 08 22:13:08 2019 -0600
+++ b/website/src/manual.html	Mon Sep 09 01:22:23 2019 -0600
@@ -1812,7 +1812,7 @@
 
 
 
-<h4 heading><a name="Luan.eval" href="#Luan.eval"><code>Luan.eval (text [, source_name])</code></a></h4>
+<h4 heading><a name="Luan.eval" href="#Luan.eval"><code>Luan.eval (text [, source_name] [, env])</code></a></h4>
 
 <p>
 Evaluates <code>text</code> as a Luan expression.
@@ -1821,8 +1821,8 @@
 Could be defined as:
 
 <pre>
-	function Luan.eval(text,source_name)
-		return Luan.load( "return "..text, source_name or "eval" )()
+	function Luan.eval(text,source_name, env)
+		return <a href="#Luan.load">Luan.load</a>( "return "..text, source_name or "eval", env )()
 	end
 </pre>