NoiseFilter: Dont drop last word of apparent hostnames. Too many non-hostnames can...
[beagle.git] / Util / SemWeb / RSquary.cs
bloba853c789db22a64de3f9c2c191f7fffc3970b3fe
1 using System;
2 using System.Collections;
3 using System.IO;
4 using System.Text;
6 using SemWeb;
7 using SemWeb.Stores;
9 namespace SemWeb.Query {
10 public class RSquary : QueryEngine {
12 // TODO: Optional statements
13 // TODO: Grouping and disjunctions
15 public static Entity qSelect = "http://purl.oclc.org/NET/rsquary/select";
16 public static Entity qLimit = "http://purl.oclc.org/NET/rsquary/returnLimit";
17 public static Entity qStart = "http://purl.oclc.org/NET/rsquary/returnStart";
18 public static Entity qDistinctFrom = "http://purl.oclc.org/NET/rsquary/distinctFrom";
19 public static Entity qOptional = "http://purl.oclc.org/NET/rsquary/optional";
21 public RSquary(Store queryModel, string queryUri) : this(queryModel, queryUri, null) {
24 public RSquary(Store queryModel, string queryUri, Hashtable extraValueFilters) {
25 Entity query = new Entity(queryUri);
27 // Find the query options
28 ReturnStart = GetIntOption(queryModel, query, qStart);
29 ReturnLimit = GetIntOption(queryModel, query, qLimit);
31 // Search the query for 'select'
32 foreach (Resource r in queryModel.SelectObjects(query, qSelect)) {
33 if (!(r is Entity)) throw new QueryException("Query variables cannot be literals.");
34 Select((Entity)r);
37 // Search the query for 'distinct' predicates between variables.
38 foreach (Statement s in queryModel.Select(new Statement(null, qDistinctFrom, null))) {
39 if (!(s.Object is Entity)) throw new QueryException("The distinctFrom predicate cannot have a literal as its object.");
40 MakeDistinct(s.Subject, (Entity)s.Object);
43 // Add all statements except the query predicates and value filters into a
44 // new store with just the statements relevant to the search.
45 foreach (Statement s in queryModel.Select(new Statement(null,null,null))) {
46 if (IsQueryPredicate(s.Predicate)) continue;
48 if (s.Predicate.Uri != null && extraValueFilters != null && extraValueFilters.ContainsKey(s.Predicate.Uri)) {
49 ValueFilterFactory f = (ValueFilterFactory)extraValueFilters[s.Predicate.Uri];
50 AddValueFilter(s.Subject, f.GetValueFilter(s.Predicate.Uri, s.Object));
51 continue;
52 } else {
53 ValueFilter f = ValueFilter.GetValueFilter(s.Predicate, s.Object);
54 if (f != null) {
55 AddValueFilter(s.Subject, f);
56 continue;
60 if (s.Meta == Statement.DefaultMeta)
61 AddFilter(s);
62 else if (queryModel.Contains(new Statement(query, qOptional, s.Meta)))
63 AddOptionalFilter(s);
67 private int GetIntOption(Store queryModel, Entity query, Entity predicate) {
68 Resource[] rr = queryModel.SelectObjects(query, predicate);
69 if (rr.Length == 0) return -1;
70 Resource r = rr[0];
71 if (r == null || !(r is Literal)) return -1;
72 try {
73 return int.Parse(((Literal)r).Value);
74 } catch (Exception e) {
75 throw new QueryException("Invalid integer value for <" + predicate + ">, '" + ((Literal)r).Value + "'.", e);
79 private bool IsQueryPredicate(Entity e) {
80 if (e == qSelect) return true;
81 if (e == qDistinctFrom) return true;
82 if (e == qLimit) return true;
83 if (e == qStart) return true;
84 if (e == qOptional) return true;
85 return false;
89 public class PrintQuerySink : QueryResultSink {
90 public override void Init(Entity[] variables) { }
91 public override void Finished() { }
92 public override bool Add(VariableBinding[] result) {
93 foreach (VariableBinding var in result)
94 if (var.Variable.Uri != null && var.Target != null)
95 Console.WriteLine(var.Variable + " ==> " + var.Target.ToString());
96 Console.WriteLine();
97 return true;
101 public class HTMLQuerySink : QueryResultSink {
102 TextWriter output;
104 public HTMLQuerySink(TextWriter output) { this.output = output; }
106 public override void Init(Entity[] variables) {
107 output.WriteLine("<tr>");
108 foreach (Entity var in variables)
109 if (var.Uri != null)
110 output.WriteLine("<th>" + var + "</th>");
111 output.WriteLine("</tr>");
114 public override void Finished() { }
116 public override bool Add(VariableBinding[] result) {
117 output.WriteLine("<tr>");
118 foreach (VariableBinding var in result) {
119 if (var.Variable.Uri == null) continue;
120 string t = var.Target.ToString();
121 if (var.Target is Literal) t = ((Literal)var.Target).Value;
122 output.WriteLine("<td>" + t + "</td>");
124 output.WriteLine("</tr>");
125 return true;
129 public class SQLQuerySink : QueryResultSink {
130 TextWriter output;
131 string table;
133 public SQLQuerySink(TextWriter output, string table) { this.output = output; this.table = table; }
135 public override void Finished() { }
137 private string GetFieldType(string datatype) {
138 switch (datatype) {
139 case "http://www.w3.org/2001/XMLSchema#string":
140 case "http://www.w3.org/2001/XMLSchema#normalizedString":
141 return "TEXT";
143 case "http://www.w3.org/2001/XMLSchema#float":
144 return "FLOAT";
146 case "http://www.w3.org/2001/XMLSchema#double":
147 return "DOUBLE PRECISION";
149 case "http://www.w3.org/2001/XMLSchema#decimal":
150 return "DECIMAL";
152 case "http://www.w3.org/2001/XMLSchema#integer":
153 case "http://www.w3.org/2001/XMLSchema#nonPositiveInteger":
154 case "http://www.w3.org/2001/XMLSchema#negativeInteger":
155 case "http://www.w3.org/2001/XMLSchema#int":
156 case "http://www.w3.org/2001/XMLSchema#short":
157 return "INT";
159 case "http://www.w3.org/2001/XMLSchema#long":
160 return "BIGINT";
163 case "http://www.w3.org/2001/XMLSchema#boolean":
164 case "http://www.w3.org/2001/XMLSchema#byte":
165 case "http://www.w3.org/2001/XMLSchema#unsignedByte":
166 return "SMALLINT";
168 case "http://www.w3.org/2001/XMLSchema#nonNegativeInteger":
169 case "http://www.w3.org/2001/XMLSchema#unsignedInt":
170 case "http://www.w3.org/2001/XMLSchema#unsignedShort":
171 case "http://www.w3.org/2001/XMLSchema#positiveInteger":
172 return "UNSIGNED INT";
174 case "http://www.w3.org/2001/XMLSchema#unsignedLong":
175 return "UNSIGNED BIGINT";
177 case "http://www.w3.org/2001/XMLSchema#dateTime":
178 return "DATETIME";
180 case "http://www.w3.org/2001/XMLSchema#date":
181 return "DATE";
183 case "http://www.w3.org/2001/XMLSchema#time":
184 case "http://www.w3.org/2001/XMLSchema#duration":
185 return "TIME";
187 case "http://www.w3.org/2001/XMLSchema#base64Binary":
188 return "BLOB";
190 case "http://www.w3.org/2001/XMLSchema#anyURI":
191 // shouldn't be case-insensitive, but using BLOB
192 // instead seems to make things too complex.
193 return "TEXT";
196 return "TEXT";
199 public override void Init(Entity[] variables) {
200 output.Write("CREATE TABLE " + table + " (");
202 bool f = true;
203 foreach (Entity var in variables) {
204 if (var.Uri == null) continue;
205 string name;
206 int hash = var.Uri.LastIndexOf("#");
207 if (hash == -1) name = "`" + var.Uri + "`";
208 else name = var.Uri.Substring(hash+1);
210 string type = "BLOB";
211 //if (var.Target is Literal && ((Literal)var.Target).DataType != null)
212 // type = GetFieldType(((Literal)var.Target).DataType);
214 if (!f) { output.Write(", "); } f = false;
215 output.Write(name + " " + type);
218 output.WriteLine(");");
221 public override bool Add(VariableBinding[] result) {
222 output.Write("INSERT INTO " + table + " VALUES (");
223 bool firstx = true;
224 foreach (VariableBinding var in result) {
225 if (var.Variable.Uri == null) continue;
227 if (!firstx) { output.Write(", "); } firstx = false;
228 if (var.Target == null)
229 output.Write("NULL");
230 else if (var.Target is Literal)
231 output.Write(Escape(((Literal)var.Target).Value));
232 else if (var.Target.Uri != null)
233 output.Write("\"" + var.Target.Uri + "\"");
234 else
235 output.Write("\"\"");
237 output.WriteLine(");");
239 return true;
242 private string Escape(string str) {
243 if (str == null) return "NULL";
244 return "\"" + EscapeUnquoted(str) + "\"";
247 StringBuilder EscapeUnquotedBuffer = new StringBuilder();
248 private string EscapeUnquoted(string str) {
249 StringBuilder b = EscapeUnquotedBuffer;
250 b.Length = 0;
251 b.Append(str);
252 SQLStore.Escape(b);
253 return b.ToString();
258 public class SparqlXmlQuerySink : QueryResultSink {
259 System.Xml.XmlWriter output;
260 string variableNamespace;
262 int blankNodeCounter = 0;
263 Hashtable blankNodes = new Hashtable();
265 private static System.Xml.XmlWriter GetWriter(System.IO.TextWriter writer) {
266 System.Xml.XmlTextWriter w = new System.Xml.XmlTextWriter(writer);
267 w.Formatting = System.Xml.Formatting.Indented;
268 return w;
271 public SparqlXmlQuerySink(TextWriter output, string variableNamespace)
272 : this(GetWriter(output), variableNamespace) {
275 public SparqlXmlQuerySink(System.Xml.XmlWriter output, string variableNamespace) {
276 this.output = output;
277 this.variableNamespace = variableNamespace;
278 output.WriteStartElement("sparql");
279 output.WriteAttributeString("xmlns", "http://www.w3.org/2001/sw/DataAccess/rf1/result");
280 output.WriteStartElement("head");
283 string GetName(string uri) {
284 if (uri.StartsWith(variableNamespace))
285 uri = uri.Substring(variableNamespace.Length);
286 if (uri.StartsWith("?") || uri.StartsWith("$"))
287 uri = uri.Substring(1);
288 return uri;
291 public override void Init(Entity[] variables) {
292 foreach (Entity var in variables) {
293 if (var.Uri == null) continue;
294 output.WriteStartElement("variable");
295 output.WriteAttributeString("name", GetName(var.Uri));
296 output.WriteEndElement();
298 output.WriteEndElement(); // head
299 output.WriteStartElement("results");
302 public override bool Add(VariableBinding[] result) {
303 output.WriteStartElement("result");
304 foreach (VariableBinding var in result) {
305 if (var.Variable.Uri == null) continue;
307 output.WriteStartElement(GetName(var.Variable.Uri));
308 if (var.Target == null) {
309 output.WriteAttributeString("bound", "false");
310 } else if (var.Target.Uri != null) {
311 output.WriteAttributeString("uri", var.Target.Uri);
312 } else if (var.Target is Literal) {
313 Literal literal = (Literal)var.Target;
314 if (literal.DataType != null)
315 output.WriteAttributeString("datatype", literal.DataType);
316 if (literal.Language != null)
317 output.WriteAttributeString("language", literal.Language);
318 output.WriteString(literal.Value);
319 } else {
320 string id;
321 if (blankNodes.ContainsKey(var.Target))
322 id = (string)blankNodes[var.Target];
323 else {
324 id = "r" + (++blankNodeCounter);
325 blankNodes[var.Target] = id;
327 output.WriteAttributeString("bnodeid", id);
330 output.WriteEndElement();
332 output.WriteEndElement();
334 return true;
337 public override void Finished() {
338 output.WriteEndElement(); // results
339 output.WriteEndElement(); // sparql
340 output.Close();