private void Select(Resource templateSubject, Resource templatePredicate, Resource templateObject, Resource templateMeta, LiteralFilter[] litFilters, StatementSink result, int limit) { if (result == null) throw new ArgumentNullException(); lock (syncroot) { Init(); RunAddBuffer(); // Don't select on columns that we already know from the template. // But grab the URIs and literal values for MultiRes selection. SelectColumnFilter columns = new SelectColumnFilter(); columns.SubjectId = (templateSubject == null) || templateSubject is MultiRes; columns.PredicateId = (templatePredicate == null) || templatePredicate is MultiRes; columns.ObjectId = (templateObject == null) || templateObject is MultiRes; columns.MetaId = (templateMeta == null) || templateMeta is MultiRes; columns.SubjectUri = templateSubject == null; columns.PredicateUri = templatePredicate == null; columns.ObjectData = templateObject == null || (templateObject is MultiRes && ((MultiRes)templateObject).ContainsLiterals()); columns.MetaUri = templateMeta == null; if (isOrContains(templatePredicate, rdfs_member)) { columns.PredicateId = true; columns.PredicateUri = true; } // Meta URIs tend to be repeated a lot, so we don't // want to ever select them from the database. // This preloads them, although it makes the first // select quite slow. /*if (templateMeta == null && SupportsSubquery) { LoadMetaEntities(); columns.MetaUri = false; }*/ // Have to select something bool fakeSubjectIdSelect = false; if (!columns.SubjectId && !columns.PredicateId && !columns.ObjectId && !columns.MetaId) { columns.SubjectId = true; fakeSubjectIdSelect = true; } // Pre-cache the IDs of resources in a MultiRes. TODO: Pool these into one array. foreach (Resource r in new Resource[] { templateSubject, templatePredicate, templateObject, templateMeta }) { MultiRes mr = r as MultiRes; if (mr == null) continue; PrefetchResourceIds(mr.items); CleanMultiRes(mr); if (mr.items.Length == 0) // no possible values return; } // SQLite has a problem with LEFT JOIN: When a condition is made on the // first table in the ON clause (q.objecttype=0/1), when it fails, // it excludes the row from the first table, whereas it should only // exclude the results of the join. System.Text.StringBuilder cmd = new System.Text.StringBuilder("SELECT "); if (!SupportsLimitClause && limit >= 1) { cmd.Append("TOP "); cmd.Append(limit); cmd.Append(' '); } if (!HasUniqueStatementsConstraint) cmd.Append("DISTINCT "); SelectFilterColumns(columns, cmd); cmd.Append(" FROM "); cmd.Append(table); cmd.Append("_statements AS q"); SelectFilterTables(columns, cmd); cmd.Append(' '); bool wroteWhere; if (!WhereClause(templateSubject, templatePredicate, templateObject, templateMeta, cmd, out wroteWhere)) return; // Transform literal filters into SQL. if (litFilters != null) { foreach (LiteralFilter f in litFilters) { string s = FilterToSQL(f, "lit.value"); if (s != null) { if (!wroteWhere) { cmd.Append(" WHERE "); wroteWhere = true; } else { cmd.Append(" AND "); } cmd.Append(' '); cmd.Append(s); } } } if (SupportsLimitClause && limit >= 1) { cmd.Append(" LIMIT "); cmd.Append(limit); } cmd.Append(';'); if (Debug) { string cmd2 = cmd.ToString(); //if (cmd2.Length > 80) cmd2 = cmd2.Substring(0, 80); Console.Error.WriteLine(cmd2); } Hashtable entMap = new Hashtable(); // Be sure if a MultiRes is involved we hash the // ids of the entities so we can return them // without creating new ones. CacheMultiObjects(entMap, templateSubject); CacheMultiObjects(entMap, templatePredicate); CacheMultiObjects(entMap, templateObject); CacheMultiObjects(entMap, templateMeta); using (IDataReader reader = RunReader(cmd.ToString())) { while (reader.Read()) { int col = 0; Int64 sid = -1, pid = -1, ot = -1, oid = -1, mid = -1; string suri = null, puri = null, ouri = null, muri = null; string lv = null, ll = null, ld = null; if (columns.SubjectId) { sid = reader.GetInt64(col++); } if (columns.PredicateId) { pid = reader.GetInt64(col++); } if (columns.ObjectId) { oid = reader.GetInt64(col++); } if (columns.MetaId) { mid = reader.GetInt64(col++); } if (columns.SubjectUri) { suri = AsString(reader[col++]); } if (columns.PredicateUri) { puri = AsString(reader[col++]); } if (columns.ObjectData) { ot = reader.GetInt64(col++); ouri = AsString(reader[col++]); lv = AsString(reader[col++]); ll = AsString(reader[col++]); ld = AsString(reader[col++]);} if (columns.MetaUri) { muri = AsString(reader[col++]); } Entity subject = GetSelectedEntity(sid, suri, templateSubject, columns.SubjectId && !fakeSubjectIdSelect, columns.SubjectUri, entMap); Entity predicate = GetSelectedEntity(pid, puri, templatePredicate, columns.PredicateId, columns.PredicateUri, entMap); Resource objec = GetSelectedResource(oid, ot, ouri, lv, ll, ld, templateObject, columns.ObjectId, columns.ObjectData, entMap); Entity meta = GetSelectedEntity(mid, muri, templateMeta, columns.MetaId, columns.MetaUri, templateMeta != null ? entMap : null); if (litFilters != null && !LiteralFilter.MatchesFilters(objec, litFilters, this)) continue; bool ret = result.Add(new Statement(subject, predicate, objec, meta)); if (!ret) break; } } } // lock }
private void SelectFilterTables(SelectColumnFilter filter, StringBuilder cmd) { if (filter.SubjectUri) { cmd.Append(" LEFT JOIN "); cmd.Append(table); cmd.Append("_entities AS suri ON q.subject = suri.id"); } if (filter.PredicateUri) { cmd.Append(" LEFT JOIN "); cmd.Append(table); cmd.Append("_entities AS puri ON q.predicate = puri.id"); } if (filter.ObjectData) { cmd.Append(" LEFT JOIN "); cmd.Append(table); cmd.Append("_entities AS ouri ON q.object = ouri.id"); cmd.Append(" LEFT JOIN "); cmd.Append(table); cmd.Append("_literals AS lit ON q.object=lit.id"); } if (filter.MetaUri) { cmd.Append(" LEFT JOIN "); cmd.Append(table); cmd.Append("_entities AS muri ON q.meta = muri.id"); } }
private void Select2(SelectFilter filter, StatementSink result) { // Don't select on columns that we already know from the template. SelectColumnFilter columns = new SelectColumnFilter(); columns.Subject = (filter.Subjects == null) || (filter.Subjects.Length > 1); columns.Predicate = (filter.Predicates == null) || (filter.Predicates.Length > 1); columns.Object = (filter.Objects == null) || (filter.Objects.Length > 1); columns.Meta = (filter.Metas == null) || (filter.Metas.Length > 1);; if (filter.Predicates != null | Array.IndexOf(filter.Predicates, rdfs_member) != 1) { columns.Predicate = true; } // Have to select something if (!columns.Subject && !columns.Predicate && !columns.Object && !columns.Meta) { columns.Subject = true; } System.Text.StringBuilder cmd = new System.Text.StringBuilder("SELECT "); if (!connection.AreStatementsUnique) { cmd.Append("DISTINCT "); } ArrayList cols = new ArrayList(); if (columns.Subject) { cols.Add("sinfo.type"); cols.Add("sinfo.value"); } if (columns.Predicate) { cols.Add("pinfo.type"); cols.Add("pinfo.value"); } if (columns.Object) { cols.Add("oinfo.type"); cols.Add("oinfo.value"); cols.Add("oinfo.language"); cols.Add("oinfo.datatype"); } if (columns.Meta) { cols.Add("minfo.type"); cols.Add("minfo.value"); } cmd.Append(String.Join(", ", (String[])cols.ToArray(typeof(String)))); cmd.Append(" FROM "); cmd.Append(prefix); cmd.Append("_statements AS q"); if (columns.Subject) { cmd.Append(" LEFT JOIN "); cmd.Append(prefix); cmd.Append("_values AS sinfo ON q.subject = sinfo.id"); } if (columns.Predicate) { cmd.Append(" LEFT JOIN "); cmd.Append(prefix); cmd.Append("_values AS pinfo ON q.predicate = pinfo.id"); } if (columns.Object) { cmd.Append(" LEFT JOIN "); cmd.Append(prefix); cmd.Append("_values AS oinfo ON q.object = oinfo.id"); } if (columns.Meta) { cmd.Append(" LEFT JOIN "); cmd.Append(prefix); cmd.Append("_values AS minfo ON q.meta = minfo.id"); } cmd.Append(' '); bool wroteWhere = WhereClause(filter, cmd); // Transform literal filters into SQL. if (filter.LiteralFilters != null) { foreach (LiteralFilter f in filter.LiteralFilters) { string s = FilterToSQL(f, "oinfo.value"); if (s != null) { if (!wroteWhere) { cmd.Append(" WHERE "); wroteWhere = true; } else { cmd.Append(" AND "); } cmd.Append(' '); cmd.Append(s); } } } if (filter.Limit >= 1) { cmd.Append(" LIMIT "); cmd.Append(filter.Limit); } cmd.Append(';'); if (Debug) { string cmd2 = cmd.ToString(); //if (cmd2.Length > 80) cmd2 = cmd2.Substring(0, 80); Console.Error.WriteLine(cmd2); } using (IDataReader reader = connection.RunReader(cmd.ToString())) { while (reader.Read()) { Entity s = columns.Subject ? null : filter.Subjects[0]; Entity p = columns.Predicate ? null : filter.Predicates[0]; Resource o = columns.Object ? null : filter.Objects[0]; Entity m = columns.Meta ? null : filter.Metas[0]; int col = 0; if (columns.Subject) { s = SelectEntity(reader.GetInt32(col++), reader.GetString(col++)); } if (columns.Predicate) { p = SelectEntity(reader.GetInt32(col++), reader.GetString(col++)); } if (columns.Object) { o = SelectResource(reader.GetInt32(col++), reader.GetString(col++), reader.GetString(col++), reader.GetString(col++)); } if (columns.Meta) { m = SelectEntity(reader.GetInt32(col++), reader.GetString(col++)); } if (filter.LiteralFilters != null && !LiteralFilter.MatchesFilters(o, filter.LiteralFilters, this)) { continue; } bool ret = result.Add(new Statement(s, p, o, m)); if (!ret) { break; } } } }
private static void SelectFilterColumns(SelectColumnFilter filter, StringBuilder cmd) { bool f = true; if (filter.SubjectId) { cmd.Append("q.subject"); f = false; } if (filter.PredicateId) { AppendComma(cmd, "q.predicate", !f); f = false; } if (filter.ObjectId) { AppendComma(cmd, "q.object", !f); f = false; } if (filter.MetaId) { AppendComma(cmd, "q.meta", !f); f = false; } if (filter.SubjectUri) { AppendComma(cmd, "suri.value", !f); f = false; } if (filter.PredicateUri) { AppendComma(cmd, "puri.value", !f); f = false; } if (filter.ObjectData) { AppendComma(cmd, "q.objecttype, ouri.value, lit.value, lit.language, lit.datatype", !f); f = false; } if (filter.MetaUri) { AppendComma(cmd, "muri.value", !f); f = false; } }
private void Select2(SelectFilter filter, StatementSink result) { // Don't select on columns that we already know from the template. SelectColumnFilter columns = new SelectColumnFilter(); columns.Subject = (filter.Subjects == null) || (filter.Subjects.Length > 1); columns.Predicate = (filter.Predicates == null) || (filter.Predicates.Length > 1); columns.Object = (filter.Objects == null) || (filter.Objects.Length > 1); columns.Meta = (filter.Metas == null) || (filter.Metas.Length > 1);; if (filter.Predicates != null | Array.IndexOf(filter.Predicates, rdfs_member) != 1) columns.Predicate = true; // Have to select something if (!columns.Subject && !columns.Predicate && !columns.Object && !columns.Meta) columns.Subject = true; System.Text.StringBuilder cmd = new System.Text.StringBuilder("SELECT "); if (!connection.AreStatementsUnique) cmd.Append("DISTINCT "); ArrayList cols = new ArrayList(); if (columns.Subject) { cols.Add("sinfo.type"); cols.Add("sinfo.value"); } if (columns.Predicate) { cols.Add("pinfo.type"); cols.Add("pinfo.value"); } if (columns.Object) { cols.Add("oinfo.type"); cols.Add("oinfo.value"); cols.Add("oinfo.language"); cols.Add("oinfo.datatype"); } if (columns.Meta) { cols.Add("minfo.type"); cols.Add("minfo.value"); } cmd.Append(String.Join(", ", (String[])cols.ToArray(typeof(String)))); cmd.Append(" FROM "); cmd.Append(prefix); cmd.Append("_statements AS q"); if (columns.Subject) { cmd.Append(" LEFT JOIN "); cmd.Append(prefix); cmd.Append("_values AS sinfo ON q.subject = sinfo.id"); } if (columns.Predicate) { cmd.Append(" LEFT JOIN "); cmd.Append(prefix); cmd.Append("_values AS pinfo ON q.predicate = pinfo.id"); } if (columns.Object) { cmd.Append(" LEFT JOIN "); cmd.Append(prefix); cmd.Append("_values AS oinfo ON q.object = oinfo.id"); } if (columns.Meta) { cmd.Append(" LEFT JOIN "); cmd.Append(prefix); cmd.Append("_values AS minfo ON q.meta = minfo.id"); } cmd.Append(' '); bool wroteWhere = WhereClause(filter, cmd); // Transform literal filters into SQL. if (filter.LiteralFilters != null) { foreach (LiteralFilter f in filter.LiteralFilters) { string s = FilterToSQL(f, "oinfo.value"); if (s != null) { if (!wroteWhere) { cmd.Append(" WHERE "); wroteWhere = true; } else { cmd.Append(" AND "); } cmd.Append(' '); cmd.Append(s); } } } if (filter.Limit >= 1) { cmd.Append(" LIMIT "); cmd.Append(filter.Limit); } cmd.Append(';'); if (Debug) { string cmd2 = cmd.ToString(); //if (cmd2.Length > 80) cmd2 = cmd2.Substring(0, 80); Console.Error.WriteLine(cmd2); } using (IDataReader reader = connection.RunReader(cmd.ToString())) { while (reader.Read()) { Entity s = columns.Subject ? null : filter.Subjects[0]; Entity p = columns.Predicate ? null : filter.Predicates[0]; Resource o = columns.Object ? null : filter.Objects[0]; Entity m = columns.Meta ? null : filter.Metas[0]; int col = 0; if (columns.Subject) { s = SelectEntity(reader.GetInt32(col++), reader.GetString(col++)); } if (columns.Predicate) { p = SelectEntity(reader.GetInt32(col++), reader.GetString(col++)); } if (columns.Object) { o = SelectResource(reader.GetInt32(col++), reader.GetString(col++), reader.GetString(col++), reader.GetString(col++)); } if (columns.Meta) { m = SelectEntity(reader.GetInt32(col++), reader.GetString(col++)); } if (filter.LiteralFilters != null && !LiteralFilter.MatchesFilters(o, filter.LiteralFilters, this)) continue; bool ret = result.Add(new Statement(s, p, o, m)); if (!ret) break; } } }