From 93534fa5bbefc2d38f7f6eb76683975af8186139 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Mon, 20 Mar 2017 16:59:42 +0100 Subject: [PATCH 1/8] Remove 'compiler' ivar from TermMatcher TermMatcher only needs the compiler's weight. --- core/Lucy/Index/Posting.cfh | 2 +- core/Lucy/Index/Posting/MatchPosting.c | 9 ++++----- core/Lucy/Index/Posting/MatchPosting.cfh | 4 ++-- core/Lucy/Index/Posting/RichPosting.c | 9 ++++----- core/Lucy/Index/Posting/RichPosting.cfh | 4 ++-- core/Lucy/Index/Posting/ScorePosting.c | 9 ++++----- core/Lucy/Index/Posting/ScorePosting.cfh | 4 ++-- core/Lucy/Index/PostingList.cfh | 4 ++-- core/Lucy/Index/SegPostingList.c | 6 +++--- core/Lucy/Index/SegPostingList.cfh | 4 ++-- core/Lucy/Search/TermMatcher.c | 6 ++---- core/Lucy/Search/TermMatcher.cfh | 3 +-- core/Lucy/Search/TermQuery.c | 5 +++-- 13 files changed, 32 insertions(+), 37 deletions(-) diff --git a/core/Lucy/Index/Posting.cfh b/core/Lucy/Index/Posting.cfh index 2d88cb683..63fcbcc44 100644 --- a/core/Lucy/Index/Posting.cfh +++ b/core/Lucy/Index/Posting.cfh @@ -63,7 +63,7 @@ class Lucy::Index::Posting nickname Post inherits Lucy::Util::Stepper { */ abstract incremented Matcher* Make_Matcher(Posting *self, Similarity *sim, PostingList *plist, - Compiler *compiler, bool need_score); + float weight, bool need_score); } abstract class Lucy::Index::Posting::PostingWriter nickname PostWriter diff --git a/core/Lucy/Index/Posting/MatchPosting.c b/core/Lucy/Index/Posting/MatchPosting.c index 77931c1e4..5c43bf52f 100644 --- a/core/Lucy/Index/Posting/MatchPosting.c +++ b/core/Lucy/Index/Posting/MatchPosting.c @@ -144,21 +144,20 @@ MatchPost_Add_Inversion_To_Pool_IMP(MatchPosting *self, MatchPostingMatcher* MatchPost_Make_Matcher_IMP(MatchPosting *self, Similarity *sim, - PostingList *plist, Compiler *compiler, - bool need_score) { + PostingList *plist, float weight, bool need_score) { MatchPostingMatcher *matcher = (MatchPostingMatcher*)Class_Make_Obj(MATCHPOSTINGMATCHER); UNUSED_VAR(self); UNUSED_VAR(need_score); - return MatchPostMatcher_init(matcher, sim, plist, compiler); + return MatchPostMatcher_init(matcher, sim, plist, weight); } /***************************************************************************/ MatchPostingMatcher* MatchPostMatcher_init(MatchPostingMatcher *self, Similarity *sim, - PostingList *plist, Compiler *compiler) { - TermMatcher_init((TermMatcher*)self, sim, plist, compiler); + PostingList *plist, float weight) { + TermMatcher_init((TermMatcher*)self, sim, plist, weight); return self; } diff --git a/core/Lucy/Index/Posting/MatchPosting.cfh b/core/Lucy/Index/Posting/MatchPosting.cfh index a92dd3dd6..c09caee62 100644 --- a/core/Lucy/Index/Posting/MatchPosting.cfh +++ b/core/Lucy/Index/Posting/MatchPosting.cfh @@ -59,7 +59,7 @@ class Lucy::Index::Posting::MatchPosting nickname MatchPost incremented MatchPostingMatcher* Make_Matcher(MatchPosting *self, Similarity *sim, PostingList *plist, - Compiler *compiler, bool need_score); + float weight, bool need_score); } class Lucy::Index::Posting::MatchPostingMatcher nickname MatchPostMatcher @@ -67,7 +67,7 @@ class Lucy::Index::Posting::MatchPostingMatcher nickname MatchPostMatcher inert MatchPostingMatcher* init(MatchPostingMatcher *self, Similarity *similarity, - PostingList *posting_list, Compiler *compiler); + PostingList *posting_list, float weight); public float Score(MatchPostingMatcher *self); diff --git a/core/Lucy/Index/Posting/RichPosting.c b/core/Lucy/Index/Posting/RichPosting.c index 242995ee3..43b223b3d 100644 --- a/core/Lucy/Index/Posting/RichPosting.c +++ b/core/Lucy/Index/Posting/RichPosting.c @@ -192,20 +192,19 @@ RichPost_Read_Raw_IMP(RichPosting *self, InStream *instream, RichPostingMatcher* RichPost_Make_Matcher_IMP(RichPosting *self, Similarity *sim, - PostingList *plist, Compiler *compiler, - bool need_score) { + PostingList *plist, float weight, bool need_score) { RichPostingMatcher* matcher = (RichPostingMatcher*)Class_Make_Obj(RICHPOSTINGMATCHER); UNUSED_VAR(self); UNUSED_VAR(need_score); - return RichPostMatcher_init(matcher, sim, plist, compiler); + return RichPostMatcher_init(matcher, sim, plist, weight); } RichPostingMatcher* RichPostMatcher_init(RichPostingMatcher *self, Similarity *sim, - PostingList *plist, Compiler *compiler) { + PostingList *plist, float weight) { return (RichPostingMatcher*)ScorePostMatcher_init((ScorePostingMatcher*)self, - sim, plist, compiler); + sim, plist, weight); } diff --git a/core/Lucy/Index/Posting/RichPosting.cfh b/core/Lucy/Index/Posting/RichPosting.cfh index d2cde9f51..c9c1c1d9c 100644 --- a/core/Lucy/Index/Posting/RichPosting.cfh +++ b/core/Lucy/Index/Posting/RichPosting.cfh @@ -57,7 +57,7 @@ class Lucy::Index::Posting::RichPosting nickname RichPost incremented RichPostingMatcher* Make_Matcher(RichPosting *self, Similarity *sim, PostingList *plist, - Compiler *compiler, bool need_score); + float weight, bool need_score); } class Lucy::Index::Posting::RichPostingMatcher nickname RichPostMatcher @@ -65,7 +65,7 @@ class Lucy::Index::Posting::RichPostingMatcher nickname RichPostMatcher inert RichPostingMatcher* init(RichPostingMatcher *self, Similarity *similarity, - PostingList *posting_list, Compiler *compiler); + PostingList *posting_list, float weight); } diff --git a/core/Lucy/Index/Posting/ScorePosting.c b/core/Lucy/Index/Posting/ScorePosting.c index ea333469f..66fb968d0 100644 --- a/core/Lucy/Index/Posting/ScorePosting.c +++ b/core/Lucy/Index/Posting/ScorePosting.c @@ -213,20 +213,19 @@ ScorePost_Read_Raw_IMP(ScorePosting *self, InStream *instream, ScorePostingMatcher* ScorePost_Make_Matcher_IMP(ScorePosting *self, Similarity *sim, - PostingList *plist, Compiler *compiler, - bool need_score) { + PostingList *plist, float weight, bool need_score) { ScorePostingMatcher *matcher = (ScorePostingMatcher*)Class_Make_Obj(SCOREPOSTINGMATCHER); UNUSED_VAR(self); UNUSED_VAR(need_score); - return ScorePostMatcher_init(matcher, sim, plist, compiler); + return ScorePostMatcher_init(matcher, sim, plist, weight); } ScorePostingMatcher* ScorePostMatcher_init(ScorePostingMatcher *self, Similarity *sim, - PostingList *plist, Compiler *compiler) { + PostingList *plist, float weight) { // Init. - TermMatcher_init((TermMatcher*)self, sim, plist, compiler); + TermMatcher_init((TermMatcher*)self, sim, plist, weight); ScorePostingMatcherIVARS *const ivars = ScorePostMatcher_IVARS(self); // Fill score cache. diff --git a/core/Lucy/Index/Posting/ScorePosting.cfh b/core/Lucy/Index/Posting/ScorePosting.cfh index 5ed29e75e..2f585f30e 100644 --- a/core/Lucy/Index/Posting/ScorePosting.cfh +++ b/core/Lucy/Index/Posting/ScorePosting.cfh @@ -57,7 +57,7 @@ class Lucy::Index::Posting::ScorePosting nickname ScorePost incremented ScorePostingMatcher* Make_Matcher(ScorePosting *self, Similarity *sim, PostingList *plist, - Compiler *compiler, bool need_score); + float weight, bool need_score); nullable uint32_t* Get_Prox(ScorePosting *self); @@ -70,7 +70,7 @@ class Lucy::Index::Posting::ScorePostingMatcher nickname ScorePostMatcher inert ScorePostingMatcher* init(ScorePostingMatcher *self, Similarity *sim, PostingList *plist, - Compiler *compiler); + float weight); public float Score(ScorePostingMatcher* self); diff --git a/core/Lucy/Index/PostingList.cfh b/core/Lucy/Index/PostingList.cfh index 3429c97de..cd1ba807b 100644 --- a/core/Lucy/Index/PostingList.cfh +++ b/core/Lucy/Index/PostingList.cfh @@ -60,8 +60,8 @@ public class Lucy::Index::PostingList nickname PList /** Invoke [](cfish:.Post_Make_Matcher) for this PostingList's posting. */ abstract Matcher* - Make_Matcher(PostingList *self, Similarity *similarity, - Compiler *compiler, bool need_score); + Make_Matcher(PostingList *self, Similarity *similarity, float weight, + bool need_score); /** Indexing helper function. */ diff --git a/core/Lucy/Index/SegPostingList.c b/core/Lucy/Index/SegPostingList.c index 39b3aabee..d2a3a2dd3 100644 --- a/core/Lucy/Index/SegPostingList.c +++ b/core/Lucy/Index/SegPostingList.c @@ -301,10 +301,10 @@ S_seek_tinfo(SegPostingList *self, TermInfo *tinfo) { } Matcher* -SegPList_Make_Matcher_IMP(SegPostingList *self, Similarity *sim, - Compiler *compiler, bool need_score) { +SegPList_Make_Matcher_IMP(SegPostingList *self, Similarity *sim, float weight, + bool need_score) { SegPostingListIVARS *const ivars = SegPList_IVARS(self); - return Post_Make_Matcher(ivars->posting, sim, (PostingList*)self, compiler, + return Post_Make_Matcher(ivars->posting, sim, (PostingList*)self, weight, need_score); } diff --git a/core/Lucy/Index/SegPostingList.cfh b/core/Lucy/Index/SegPostingList.cfh index 4683bfe63..1fef34477 100644 --- a/core/Lucy/Index/SegPostingList.cfh +++ b/core/Lucy/Index/SegPostingList.cfh @@ -75,8 +75,8 @@ class Lucy::Index::SegPostingList nickname SegPList Seek_Lex(SegPostingList *self, Lexicon *lexicon); Matcher* - Make_Matcher(SegPostingList *self, Similarity *similarity, - Compiler *compiler, bool need_score); + Make_Matcher(SegPostingList *self, Similarity *similarity, float weight, + bool need_score); RawPosting* Read_Raw(SegPostingList *self, int32_t last_doc_id, String *term_text, diff --git a/core/Lucy/Search/TermMatcher.c b/core/Lucy/Search/TermMatcher.c index e8df550c5..fad1507a4 100644 --- a/core/Lucy/Search/TermMatcher.c +++ b/core/Lucy/Search/TermMatcher.c @@ -25,15 +25,14 @@ TermMatcher* TermMatcher_init(TermMatcher *self, Similarity *similarity, PostingList *plist, - Compiler *compiler) { + float weight) { Matcher_init((Matcher*)self); TermMatcherIVARS *const ivars = TermMatcher_IVARS(self); // Assign. ivars->sim = (Similarity*)INCREF(similarity); ivars->plist = (PostingList*)INCREF(plist); - ivars->compiler = (Compiler*)INCREF(compiler); - ivars->weight = Compiler_Get_Weight(compiler); + ivars->weight = weight; // Init. ivars->posting = NULL; @@ -46,7 +45,6 @@ TermMatcher_Destroy_IMP(TermMatcher *self) { TermMatcherIVARS *const ivars = TermMatcher_IVARS(self); DECREF(ivars->sim); DECREF(ivars->plist); - DECREF(ivars->compiler); SUPER_DESTROY(self, TERMMATCHER); } diff --git a/core/Lucy/Search/TermMatcher.cfh b/core/Lucy/Search/TermMatcher.cfh index 0398f37f9..7b133c2e1 100644 --- a/core/Lucy/Search/TermMatcher.cfh +++ b/core/Lucy/Search/TermMatcher.cfh @@ -25,14 +25,13 @@ parcel Lucy; class Lucy::Search::TermMatcher inherits Lucy::Search::Matcher { float weight; - Compiler *compiler; Similarity *sim; PostingList *plist; Posting *posting; inert TermMatcher* init(TermMatcher *self, Similarity *similarity, PostingList *posting_list, - Compiler *compiler); + float weight); public void Destroy(TermMatcher *self); diff --git a/core/Lucy/Search/TermQuery.c b/core/Lucy/Search/TermQuery.c index c15a57607..28f29a3cc 100644 --- a/core/Lucy/Search/TermQuery.c +++ b/core/Lucy/Search/TermQuery.c @@ -275,8 +275,9 @@ TermCompiler_Make_Matcher_IMP(TermCompiler *self, SegReader *reader, return NULL; } else { - Matcher *retval = PList_Make_Matcher(plist, ivars->sim, - (Compiler*)self, need_score); + float weight = ivars->normalized_weight; + Matcher *retval = PList_Make_Matcher(plist, ivars->sim, weight, + need_score); DECREF(plist); return retval; } From 19fa8371439b75fbec5eb0a62de53f98064ba045 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Mon, 20 Mar 2017 17:06:09 +0100 Subject: [PATCH 2/8] Remove 'similarity' param from PList_Make_Matcher The Similarity can be retrieved from the PListReader's schema. --- core/Lucy/Index/PostingList.cfh | 8 ++++++-- core/Lucy/Index/SegPostingList.c | 11 ++++++++++- core/Lucy/Index/SegPostingList.cfh | 6 ++++-- core/Lucy/Search/TermQuery.c | 3 +-- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/core/Lucy/Index/PostingList.cfh b/core/Lucy/Index/PostingList.cfh index cd1ba807b..54f77faf3 100644 --- a/core/Lucy/Index/PostingList.cfh +++ b/core/Lucy/Index/PostingList.cfh @@ -45,6 +45,11 @@ public class Lucy::Index::PostingList nickname PList public abstract uint32_t Get_Doc_Freq(PostingList *self); + /** Return the similarity. + */ + abstract Similarity* + Get_Similarity(PostingList *self); + /** Prepare the PostingList object to iterate over matches for documents * that match `target`. * @@ -60,8 +65,7 @@ public class Lucy::Index::PostingList nickname PList /** Invoke [](cfish:.Post_Make_Matcher) for this PostingList's posting. */ abstract Matcher* - Make_Matcher(PostingList *self, Similarity *similarity, float weight, - bool need_score); + Make_Matcher(PostingList *self, float weight, bool need_score); /** Indexing helper function. */ diff --git a/core/Lucy/Index/SegPostingList.c b/core/Lucy/Index/SegPostingList.c index d2a3a2dd3..06e243c25 100644 --- a/core/Lucy/Index/SegPostingList.c +++ b/core/Lucy/Index/SegPostingList.c @@ -301,9 +301,10 @@ S_seek_tinfo(SegPostingList *self, TermInfo *tinfo) { } Matcher* -SegPList_Make_Matcher_IMP(SegPostingList *self, Similarity *sim, float weight, +SegPList_Make_Matcher_IMP(SegPostingList *self, float weight, bool need_score) { SegPostingListIVARS *const ivars = SegPList_IVARS(self); + Similarity *sim = SegPList_Get_Similarity(self); return Post_Make_Matcher(ivars->posting, sim, (PostingList*)self, weight, need_score); } @@ -316,5 +317,13 @@ SegPList_Read_Raw_IMP(SegPostingList *self, int32_t last_doc_id, last_doc_id, term_text, mem_pool); } +Similarity* +SegPList_Get_Similarity_IMP(SegPostingList *self) { + SegPostingListIVARS *const ivars = SegPList_IVARS(self); + Schema *schema = PListReader_Get_Schema(ivars->plist_reader); + Similarity *sim = Schema_Fetch_Sim(schema, ivars->field); + if (!sim) { sim = Schema_Get_Similarity(schema); } + return sim; +} diff --git a/core/Lucy/Index/SegPostingList.cfh b/core/Lucy/Index/SegPostingList.cfh index 1fef34477..711a0dfcd 100644 --- a/core/Lucy/Index/SegPostingList.cfh +++ b/core/Lucy/Index/SegPostingList.cfh @@ -60,6 +60,9 @@ class Lucy::Index::SegPostingList nickname SegPList Posting* Get_Posting(SegPostingList *self); + Similarity* + Get_Similarity(SegPostingList *self); + public int32_t Next(SegPostingList *self); @@ -75,8 +78,7 @@ class Lucy::Index::SegPostingList nickname SegPList Seek_Lex(SegPostingList *self, Lexicon *lexicon); Matcher* - Make_Matcher(SegPostingList *self, Similarity *similarity, float weight, - bool need_score); + Make_Matcher(SegPostingList *self, float weight, bool need_score); RawPosting* Read_Raw(SegPostingList *self, int32_t last_doc_id, String *term_text, diff --git a/core/Lucy/Search/TermQuery.c b/core/Lucy/Search/TermQuery.c index 28f29a3cc..5cc16dcbc 100644 --- a/core/Lucy/Search/TermQuery.c +++ b/core/Lucy/Search/TermQuery.c @@ -276,8 +276,7 @@ TermCompiler_Make_Matcher_IMP(TermCompiler *self, SegReader *reader, } else { float weight = ivars->normalized_weight; - Matcher *retval = PList_Make_Matcher(plist, ivars->sim, weight, - need_score); + Matcher *retval = PList_Make_Matcher(plist, weight, need_score); DECREF(plist); return retval; } From ada2681213b7ebbc0e0a7d17ed002a7a777f6fbf Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Mon, 20 Mar 2017 15:59:12 +0100 Subject: [PATCH 3/8] Remove more args from {Post|PList}_Make_Matcher Remove 'sim' and 'need_score' from Post_Make_Matcher. Remove 'need_score' from PList_Make_Matcher. Also move 'sim' ivar from TermMatcher to ScorePostingMatcher. --- core/Lucy/Index/Posting.cfh | 3 +-- core/Lucy/Index/Posting/MatchPosting.c | 13 ++++++------- core/Lucy/Index/Posting/MatchPosting.cfh | 6 ++---- core/Lucy/Index/Posting/RichPosting.c | 13 ++++++------- core/Lucy/Index/Posting/RichPosting.cfh | 6 ++---- core/Lucy/Index/Posting/ScorePosting.c | 17 ++++++++++------- core/Lucy/Index/Posting/ScorePosting.cfh | 9 ++++----- core/Lucy/Index/PostingList.cfh | 2 +- core/Lucy/Index/SegPostingList.c | 7 ++----- core/Lucy/Index/SegPostingList.cfh | 2 +- core/Lucy/Search/TermMatcher.c | 5 +---- core/Lucy/Search/TermMatcher.cfh | 4 +--- core/Lucy/Search/TermQuery.c | 3 ++- 13 files changed, 39 insertions(+), 51 deletions(-) diff --git a/core/Lucy/Index/Posting.cfh b/core/Lucy/Index/Posting.cfh index 63fcbcc44..cb8bdbce1 100644 --- a/core/Lucy/Index/Posting.cfh +++ b/core/Lucy/Index/Posting.cfh @@ -62,8 +62,7 @@ class Lucy::Index::Posting nickname Post inherits Lucy::Util::Stepper { /** Factory method for creating a Matcher. */ abstract incremented Matcher* - Make_Matcher(Posting *self, Similarity *sim, PostingList *plist, - float weight, bool need_score); + Make_Matcher(Posting *self, PostingList *plist, float weight); } abstract class Lucy::Index::Posting::PostingWriter nickname PostWriter diff --git a/core/Lucy/Index/Posting/MatchPosting.c b/core/Lucy/Index/Posting/MatchPosting.c index 5c43bf52f..3d4fb92ea 100644 --- a/core/Lucy/Index/Posting/MatchPosting.c +++ b/core/Lucy/Index/Posting/MatchPosting.c @@ -143,21 +143,20 @@ MatchPost_Add_Inversion_To_Pool_IMP(MatchPosting *self, } MatchPostingMatcher* -MatchPost_Make_Matcher_IMP(MatchPosting *self, Similarity *sim, - PostingList *plist, float weight, bool need_score) { +MatchPost_Make_Matcher_IMP(MatchPosting *self, PostingList *plist, + float weight) { MatchPostingMatcher *matcher = (MatchPostingMatcher*)Class_Make_Obj(MATCHPOSTINGMATCHER); UNUSED_VAR(self); - UNUSED_VAR(need_score); - return MatchPostMatcher_init(matcher, sim, plist, weight); + return MatchPostMatcher_init(matcher, plist, weight); } /***************************************************************************/ MatchPostingMatcher* -MatchPostMatcher_init(MatchPostingMatcher *self, Similarity *sim, - PostingList *plist, float weight) { - TermMatcher_init((TermMatcher*)self, sim, plist, weight); +MatchPostMatcher_init(MatchPostingMatcher *self, PostingList *plist, + float weight) { + TermMatcher_init((TermMatcher*)self, plist, weight); return self; } diff --git a/core/Lucy/Index/Posting/MatchPosting.cfh b/core/Lucy/Index/Posting/MatchPosting.cfh index c09caee62..5b3d85e3e 100644 --- a/core/Lucy/Index/Posting/MatchPosting.cfh +++ b/core/Lucy/Index/Posting/MatchPosting.cfh @@ -58,16 +58,14 @@ class Lucy::Index::Posting::MatchPosting nickname MatchPost Reset(MatchPosting *self); incremented MatchPostingMatcher* - Make_Matcher(MatchPosting *self, Similarity *sim, PostingList *plist, - float weight, bool need_score); + Make_Matcher(MatchPosting *self, PostingList *plist, float weight); } class Lucy::Index::Posting::MatchPostingMatcher nickname MatchPostMatcher inherits Lucy::Search::TermMatcher { inert MatchPostingMatcher* - init(MatchPostingMatcher *self, Similarity *similarity, - PostingList *posting_list, float weight); + init(MatchPostingMatcher *self, PostingList *posting_list, float weight); public float Score(MatchPostingMatcher *self); diff --git a/core/Lucy/Index/Posting/RichPosting.c b/core/Lucy/Index/Posting/RichPosting.c index 43b223b3d..344c8f083 100644 --- a/core/Lucy/Index/Posting/RichPosting.c +++ b/core/Lucy/Index/Posting/RichPosting.c @@ -191,20 +191,19 @@ RichPost_Read_Raw_IMP(RichPosting *self, InStream *instream, } RichPostingMatcher* -RichPost_Make_Matcher_IMP(RichPosting *self, Similarity *sim, - PostingList *plist, float weight, bool need_score) { +RichPost_Make_Matcher_IMP(RichPosting *self, PostingList *plist, + float weight) { RichPostingMatcher* matcher = (RichPostingMatcher*)Class_Make_Obj(RICHPOSTINGMATCHER); UNUSED_VAR(self); - UNUSED_VAR(need_score); - return RichPostMatcher_init(matcher, sim, plist, weight); + return RichPostMatcher_init(matcher, plist, weight); } RichPostingMatcher* -RichPostMatcher_init(RichPostingMatcher *self, Similarity *sim, - PostingList *plist, float weight) { +RichPostMatcher_init(RichPostingMatcher *self, PostingList *plist, + float weight) { return (RichPostingMatcher*)ScorePostMatcher_init((ScorePostingMatcher*)self, - sim, plist, weight); + plist, weight); } diff --git a/core/Lucy/Index/Posting/RichPosting.cfh b/core/Lucy/Index/Posting/RichPosting.cfh index c9c1c1d9c..e9b6119ae 100644 --- a/core/Lucy/Index/Posting/RichPosting.cfh +++ b/core/Lucy/Index/Posting/RichPosting.cfh @@ -56,16 +56,14 @@ class Lucy::Index::Posting::RichPosting nickname RichPost float length_norm); incremented RichPostingMatcher* - Make_Matcher(RichPosting *self, Similarity *sim, PostingList *plist, - float weight, bool need_score); + Make_Matcher(RichPosting *self, PostingList *plist, float weight); } class Lucy::Index::Posting::RichPostingMatcher nickname RichPostMatcher inherits Lucy::Index::Posting::ScorePostingMatcher { inert RichPostingMatcher* - init(RichPostingMatcher *self, Similarity *similarity, - PostingList *posting_list, float weight); + init(RichPostingMatcher *self, PostingList *posting_list, float weight); } diff --git a/core/Lucy/Index/Posting/ScorePosting.c b/core/Lucy/Index/Posting/ScorePosting.c index 66fb968d0..8a4b4439d 100644 --- a/core/Lucy/Index/Posting/ScorePosting.c +++ b/core/Lucy/Index/Posting/ScorePosting.c @@ -212,22 +212,24 @@ ScorePost_Read_Raw_IMP(ScorePosting *self, InStream *instream, } ScorePostingMatcher* -ScorePost_Make_Matcher_IMP(ScorePosting *self, Similarity *sim, - PostingList *plist, float weight, bool need_score) { +ScorePost_Make_Matcher_IMP(ScorePosting *self, PostingList *plist, + float weight) { ScorePostingMatcher *matcher = (ScorePostingMatcher*)Class_Make_Obj(SCOREPOSTINGMATCHER); UNUSED_VAR(self); - UNUSED_VAR(need_score); - return ScorePostMatcher_init(matcher, sim, plist, weight); + return ScorePostMatcher_init(matcher, plist, weight); } ScorePostingMatcher* -ScorePostMatcher_init(ScorePostingMatcher *self, Similarity *sim, - PostingList *plist, float weight) { +ScorePostMatcher_init(ScorePostingMatcher *self, PostingList *plist, + float weight) { // Init. - TermMatcher_init((TermMatcher*)self, sim, plist, weight); + TermMatcher_init((TermMatcher*)self, (PostingList*)plist, weight); ScorePostingMatcherIVARS *const ivars = ScorePostMatcher_IVARS(self); + Similarity *sim = PList_Get_Similarity(plist); + ivars->sim = (Similarity*)INCREF(sim); + // Fill score cache. ivars->score_cache = (float*)MALLOCATE(TERMMATCHER_SCORE_CACHE_SIZE * sizeof(float)); for (uint32_t i = 0; i < TERMMATCHER_SCORE_CACHE_SIZE; i++) { @@ -258,6 +260,7 @@ ScorePostMatcher_Score_IMP(ScorePostingMatcher* self) { void ScorePostMatcher_Destroy_IMP(ScorePostingMatcher *self) { ScorePostingMatcherIVARS *const ivars = ScorePostMatcher_IVARS(self); + DECREF(ivars->sim); FREEMEM(ivars->score_cache); SUPER_DESTROY(self, SCOREPOSTINGMATCHER); } diff --git a/core/Lucy/Index/Posting/ScorePosting.cfh b/core/Lucy/Index/Posting/ScorePosting.cfh index 2f585f30e..ac69804e0 100644 --- a/core/Lucy/Index/Posting/ScorePosting.cfh +++ b/core/Lucy/Index/Posting/ScorePosting.cfh @@ -56,8 +56,7 @@ class Lucy::Index::Posting::ScorePosting nickname ScorePost Reset(ScorePosting *self); incremented ScorePostingMatcher* - Make_Matcher(ScorePosting *self, Similarity *sim, PostingList *plist, - float weight, bool need_score); + Make_Matcher(ScorePosting *self, PostingList *plist, float weight); nullable uint32_t* Get_Prox(ScorePosting *self); @@ -66,11 +65,11 @@ class Lucy::Index::Posting::ScorePosting nickname ScorePost class Lucy::Index::Posting::ScorePostingMatcher nickname ScorePostMatcher inherits Lucy::Search::TermMatcher { - float *score_cache; + Similarity *sim; + float *score_cache; inert ScorePostingMatcher* - init(ScorePostingMatcher *self, Similarity *sim, PostingList *plist, - float weight); + init(ScorePostingMatcher *self, PostingList *plist, float weight); public float Score(ScorePostingMatcher* self); diff --git a/core/Lucy/Index/PostingList.cfh b/core/Lucy/Index/PostingList.cfh index 54f77faf3..d617fadd1 100644 --- a/core/Lucy/Index/PostingList.cfh +++ b/core/Lucy/Index/PostingList.cfh @@ -65,7 +65,7 @@ public class Lucy::Index::PostingList nickname PList /** Invoke [](cfish:.Post_Make_Matcher) for this PostingList's posting. */ abstract Matcher* - Make_Matcher(PostingList *self, float weight, bool need_score); + Make_Matcher(PostingList *self, float weight); /** Indexing helper function. */ diff --git a/core/Lucy/Index/SegPostingList.c b/core/Lucy/Index/SegPostingList.c index 06e243c25..427b82a1b 100644 --- a/core/Lucy/Index/SegPostingList.c +++ b/core/Lucy/Index/SegPostingList.c @@ -301,12 +301,9 @@ S_seek_tinfo(SegPostingList *self, TermInfo *tinfo) { } Matcher* -SegPList_Make_Matcher_IMP(SegPostingList *self, float weight, - bool need_score) { +SegPList_Make_Matcher_IMP(SegPostingList *self, float weight) { SegPostingListIVARS *const ivars = SegPList_IVARS(self); - Similarity *sim = SegPList_Get_Similarity(self); - return Post_Make_Matcher(ivars->posting, sim, (PostingList*)self, weight, - need_score); + return Post_Make_Matcher(ivars->posting, (PostingList*)self, weight); } RawPosting* diff --git a/core/Lucy/Index/SegPostingList.cfh b/core/Lucy/Index/SegPostingList.cfh index 711a0dfcd..a04d5aafe 100644 --- a/core/Lucy/Index/SegPostingList.cfh +++ b/core/Lucy/Index/SegPostingList.cfh @@ -78,7 +78,7 @@ class Lucy::Index::SegPostingList nickname SegPList Seek_Lex(SegPostingList *self, Lexicon *lexicon); Matcher* - Make_Matcher(SegPostingList *self, float weight, bool need_score); + Make_Matcher(SegPostingList *self, float weight); RawPosting* Read_Raw(SegPostingList *self, int32_t last_doc_id, String *term_text, diff --git a/core/Lucy/Search/TermMatcher.c b/core/Lucy/Search/TermMatcher.c index fad1507a4..a37c0012f 100644 --- a/core/Lucy/Search/TermMatcher.c +++ b/core/Lucy/Search/TermMatcher.c @@ -24,13 +24,11 @@ #include "Lucy/Search/Compiler.h" TermMatcher* -TermMatcher_init(TermMatcher *self, Similarity *similarity, PostingList *plist, - float weight) { +TermMatcher_init(TermMatcher *self, PostingList *plist, float weight) { Matcher_init((Matcher*)self); TermMatcherIVARS *const ivars = TermMatcher_IVARS(self); // Assign. - ivars->sim = (Similarity*)INCREF(similarity); ivars->plist = (PostingList*)INCREF(plist); ivars->weight = weight; @@ -43,7 +41,6 @@ TermMatcher_init(TermMatcher *self, Similarity *similarity, PostingList *plist, void TermMatcher_Destroy_IMP(TermMatcher *self) { TermMatcherIVARS *const ivars = TermMatcher_IVARS(self); - DECREF(ivars->sim); DECREF(ivars->plist); SUPER_DESTROY(self, TERMMATCHER); } diff --git a/core/Lucy/Search/TermMatcher.cfh b/core/Lucy/Search/TermMatcher.cfh index 7b133c2e1..0ff34cf42 100644 --- a/core/Lucy/Search/TermMatcher.cfh +++ b/core/Lucy/Search/TermMatcher.cfh @@ -25,13 +25,11 @@ parcel Lucy; class Lucy::Search::TermMatcher inherits Lucy::Search::Matcher { float weight; - Similarity *sim; PostingList *plist; Posting *posting; inert TermMatcher* - init(TermMatcher *self, Similarity *similarity, PostingList *posting_list, - float weight); + init(TermMatcher *self, PostingList *posting_list, float weight); public void Destroy(TermMatcher *self); diff --git a/core/Lucy/Search/TermQuery.c b/core/Lucy/Search/TermQuery.c index 5cc16dcbc..e9d6c8f4d 100644 --- a/core/Lucy/Search/TermQuery.c +++ b/core/Lucy/Search/TermQuery.c @@ -258,6 +258,7 @@ TermCompiler_Get_Weight_IMP(TermCompiler *self) { Matcher* TermCompiler_Make_Matcher_IMP(TermCompiler *self, SegReader *reader, bool need_score) { + UNUSED_VAR(need_score); TermCompilerIVARS *const ivars = TermCompiler_IVARS(self); TermQueryIVARS *const parent_ivars = TermQuery_IVARS((TermQuery*)ivars->parent); @@ -276,7 +277,7 @@ TermCompiler_Make_Matcher_IMP(TermCompiler *self, SegReader *reader, } else { float weight = ivars->normalized_weight; - Matcher *retval = PList_Make_Matcher(plist, weight, need_score); + Matcher *retval = PList_Make_Matcher(plist, weight); DECREF(plist); return retval; } From 104cdc429fe7dfc3c503dc9b82867707b6ba3eae Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Fri, 24 Mar 2017 11:52:01 +0100 Subject: [PATCH 4/8] Implement Make_Root_Compiler Make_Root_Compiler calls Make_Compiler and normalizes the returned Compiler. It's equivalent to calling Make_Compiler with 'subordinate' set to false. Remove 'subordinate' param from Make_Compiler, but keep it in the Perl API for backward compatibility. CFC doesn't support custom callbacks, so alias 'make_compiler' to 'Make_Compiler_Compat'. --- core/Lucy/Docs/Cookbook/CustomQuery.md | 5 +-- core/Lucy/Highlight/Highlighter.c | 4 +-- core/Lucy/Index/DeletionsWriter.c | 4 +-- core/Lucy/Search/ANDQuery.c | 9 ++---- core/Lucy/Search/ANDQuery.cfh | 3 +- core/Lucy/Search/Compiler.cfh | 3 +- core/Lucy/Search/IndexSearcher.c | 3 +- core/Lucy/Search/LeafQuery.c | 4 +-- core/Lucy/Search/LeafQuery.cfh | 3 +- core/Lucy/Search/MatchAllQuery.c | 8 ++--- core/Lucy/Search/MatchAllQuery.cfh | 3 +- core/Lucy/Search/NOTQuery.c | 9 ++---- core/Lucy/Search/NOTQuery.cfh | 3 +- core/Lucy/Search/NoMatchQuery.c | 8 ++--- core/Lucy/Search/NoMatchQuery.cfh | 3 +- core/Lucy/Search/ORQuery.c | 9 ++---- core/Lucy/Search/ORQuery.cfh | 3 +- core/Lucy/Search/PhraseQuery.c | 11 ++----- core/Lucy/Search/PhraseQuery.cfh | 3 +- core/Lucy/Search/PolyQuery.c | 2 +- core/Lucy/Search/PolySearcher.c | 4 +-- core/Lucy/Search/Query.c | 37 ++++++++++++++++++++++ core/Lucy/Search/Query.cfh | 20 ++++++++---- core/Lucy/Search/RangeQuery.c | 8 ++--- core/Lucy/Search/RangeQuery.cfh | 3 +- core/Lucy/Search/RequiredOptionalQuery.c | 9 ++---- core/Lucy/Search/RequiredOptionalQuery.cfh | 2 +- core/Lucy/Search/TermQuery.c | 10 ++---- core/Lucy/Search/TermQuery.cfh | 3 +- core/LucyX/Search/ProximityQuery.c | 12 +++---- core/LucyX/Search/ProximityQuery.cfh | 3 +- go/build.go | 2 +- go/lucy/search.go | 5 ++- go/lucy/search_test.go | 24 +++++++------- perl/buildlib/Lucy/Build/Binding/Search.pm | 14 +++++--- perl/lib/LucyX/Remote/ClusterSearcher.pm | 5 +-- perl/lib/LucyX/Search/Filter.pm | 6 +--- perl/sample/PrefixQuery.pm | 5 +-- perl/t/501-termquery.t | 5 +-- perl/t/502-phrasequery.t | 5 +-- perl/t/515-range_query.t | 5 +-- perl/t/523-and_query.t | 15 +++------ perl/t/524-poly_query.t | 15 +++------ perl/t/525-match_all_query.t | 5 +-- perl/t/526-not_query.t | 5 +-- perl/t/527-req_opt_query.t | 10 ++---- perl/t/529-no_match_query.t | 5 +-- perl/t/613-proximityquery.t | 5 +-- perl/t/binding/303-highlighter.t | 5 +-- perl/t/binding/800-stack.t | 10 ++---- 50 files changed, 144 insertions(+), 218 deletions(-) diff --git a/core/Lucy/Docs/Cookbook/CustomQuery.md b/core/Lucy/Docs/Cookbook/CustomQuery.md index e4864b6c5..9147cb840 100644 --- a/core/Lucy/Docs/Cookbook/CustomQuery.md +++ b/core/Lucy/Docs/Cookbook/CustomQuery.md @@ -119,10 +119,7 @@ a subclass of [](cfish:lucy.Compiler). ~~~ perl sub make_compiler { my ( $self, %args ) = @_; - my $subordinate = delete $args{subordinate}; - my $compiler = PrefixCompiler->new( %args, parent => $self ); - $compiler->normalize unless $subordinate; - return $compiler; + return PrefixCompiler->new( %args, parent => $self ); } ~~~ diff --git a/core/Lucy/Highlight/Highlighter.c b/core/Lucy/Highlight/Highlighter.c index 62e2828f3..33df5dfe7 100644 --- a/core/Lucy/Highlight/Highlighter.c +++ b/core/Lucy/Highlight/Highlighter.c @@ -66,9 +66,7 @@ Highlighter_init(Highlighter *self, Searcher *searcher, Obj *query, ivars->compiler = (Compiler*)INCREF(ivars->query); } else { - ivars->compiler = Query_Make_Compiler(ivars->query, searcher, - Query_Get_Boost(ivars->query), - false); + ivars->compiler = Query_Make_Root_Compiler(ivars->query, searcher); } return self; } diff --git a/core/Lucy/Index/DeletionsWriter.c b/core/Lucy/Index/DeletionsWriter.c index fb60be330..616ec2ad3 100644 --- a/core/Lucy/Index/DeletionsWriter.c +++ b/core/Lucy/Index/DeletionsWriter.c @@ -280,8 +280,8 @@ DefDelWriter_Delete_By_Term_IMP(DefaultDeletionsWriter *self, void DefDelWriter_Delete_By_Query_IMP(DefaultDeletionsWriter *self, Query *query) { DefaultDeletionsWriterIVARS *const ivars = DefDelWriter_IVARS(self); - Compiler *compiler = Query_Make_Compiler(query, (Searcher*)ivars->searcher, - Query_Get_Boost(query), false); + Compiler *compiler + = Query_Make_Root_Compiler(query, (Searcher*)ivars->searcher); for (size_t i = 0, max = Vec_Get_Size(ivars->seg_readers); i < max; i++) { SegReader *seg_reader = (SegReader*)Vec_Fetch(ivars->seg_readers, i); diff --git a/core/Lucy/Search/ANDQuery.c b/core/Lucy/Search/ANDQuery.c index 470cac65d..4fb373f02 100644 --- a/core/Lucy/Search/ANDQuery.c +++ b/core/Lucy/Search/ANDQuery.c @@ -79,13 +79,8 @@ ANDQuery_Equals_IMP(ANDQuery *self, Obj *other) { } Compiler* -ANDQuery_Make_Compiler_IMP(ANDQuery *self, Searcher *searcher, float boost, - bool subordinate) { - ANDCompiler *compiler = ANDCompiler_new(self, searcher, boost); - if (!subordinate) { - ANDCompiler_Normalize(compiler); - } - return (Compiler*)compiler; +ANDQuery_Make_Compiler_IMP(ANDQuery *self, Searcher *searcher, float boost) { + return (Compiler*)ANDCompiler_new(self, searcher, boost); } /**********************************************************************/ diff --git a/core/Lucy/Search/ANDQuery.cfh b/core/Lucy/Search/ANDQuery.cfh index bc91b3925..3f4b5a6ee 100644 --- a/core/Lucy/Search/ANDQuery.cfh +++ b/core/Lucy/Search/ANDQuery.cfh @@ -39,8 +39,7 @@ public class Lucy::Search::ANDQuery inherits Lucy::Search::PolyQuery { init(ANDQuery *self, Vector *children = NULL); public incremented Compiler* - Make_Compiler(ANDQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(ANDQuery *self, Searcher *searcher, float boost); public incremented String* To_String(ANDQuery *self); diff --git a/core/Lucy/Search/Compiler.cfh b/core/Lucy/Search/Compiler.cfh index 77805897c..92c5a8924 100644 --- a/core/Lucy/Search/Compiler.cfh +++ b/core/Lucy/Search/Compiler.cfh @@ -121,8 +121,7 @@ public class Lucy::Search::Compiler inherits Lucy::Search::Query { Apply_Norm_Factor(Compiler *self, float factor); /** Take a newly minted Compiler object and apply query-specific - * normalization factors. Should be invoked by Query subclasses during - * [](cfish:.Make_Compiler) for top-level nodes. + * normalization factors. * * For a TermQuery, the scoring formula is approximately: * diff --git a/core/Lucy/Search/IndexSearcher.c b/core/Lucy/Search/IndexSearcher.c index ccdb1638b..cc26848de 100644 --- a/core/Lucy/Search/IndexSearcher.c +++ b/core/Lucy/Search/IndexSearcher.c @@ -135,8 +135,7 @@ IxSearcher_Collect_IMP(IndexSearcher *self, Query *query, Collector *collector) bool need_score = Coll_Need_Score(collector); Compiler *compiler = Query_is_a(query, COMPILER) ? (Compiler*)INCREF(query) - : Query_Make_Compiler(query, (Searcher*)self, - Query_Get_Boost(query), false); + : Query_Make_Root_Compiler(query, (Searcher*)self); // Accumulate hits into the Collector. for (size_t i = 0, max = Vec_Get_Size(seg_readers); i < max; i++) { diff --git a/core/Lucy/Search/LeafQuery.c b/core/Lucy/Search/LeafQuery.c index 32c56d613..4f83b102b 100644 --- a/core/Lucy/Search/LeafQuery.c +++ b/core/Lucy/Search/LeafQuery.c @@ -142,12 +142,10 @@ LeafQuery_Load_IMP(LeafQuery *self, Obj *dump) { } Compiler* -LeafQuery_Make_Compiler_IMP(LeafQuery *self, Searcher *searcher, float boost, - bool subordinate) { +LeafQuery_Make_Compiler_IMP(LeafQuery *self, Searcher *searcher, float boost) { UNUSED_VAR(self); UNUSED_VAR(searcher); UNUSED_VAR(boost); - UNUSED_VAR(subordinate); THROW(ERR, "Can't Make_Compiler() from LeafQuery"); UNREACHABLE_RETURN(Compiler*); } diff --git a/core/Lucy/Search/LeafQuery.cfh b/core/Lucy/Search/LeafQuery.cfh index fbe8e967d..2be1b2a26 100644 --- a/core/Lucy/Search/LeafQuery.cfh +++ b/core/Lucy/Search/LeafQuery.cfh @@ -77,8 +77,7 @@ public class Lucy::Search::LeafQuery inherits Lucy::Search::Query { /** Throws an error. */ public incremented Compiler* - Make_Compiler(LeafQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(LeafQuery *self, Searcher *searcher, float boost); public void Destroy(LeafQuery *self); diff --git a/core/Lucy/Search/MatchAllQuery.c b/core/Lucy/Search/MatchAllQuery.c index 97c72b8f2..985b02c74 100644 --- a/core/Lucy/Search/MatchAllQuery.c +++ b/core/Lucy/Search/MatchAllQuery.c @@ -57,12 +57,8 @@ MatchAllQuery_To_String_IMP(MatchAllQuery *self) { Compiler* MatchAllQuery_Make_Compiler_IMP(MatchAllQuery *self, Searcher *searcher, - float boost, bool subordinate) { - MatchAllCompiler *compiler = MatchAllCompiler_new(self, searcher, boost); - if (!subordinate) { - MatchAllCompiler_Normalize(compiler); - } - return (Compiler*)compiler; + float boost) { + return (Compiler*)MatchAllCompiler_new(self, searcher, boost); } /**********************************************************************/ diff --git a/core/Lucy/Search/MatchAllQuery.cfh b/core/Lucy/Search/MatchAllQuery.cfh index bdcf6ef9f..99f620a9d 100644 --- a/core/Lucy/Search/MatchAllQuery.cfh +++ b/core/Lucy/Search/MatchAllQuery.cfh @@ -42,8 +42,7 @@ public class Lucy::Search::MatchAllQuery inherits Lucy::Search::Query { To_String(MatchAllQuery *self); public incremented Compiler* - Make_Compiler(MatchAllQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(MatchAllQuery *self, Searcher *searcher, float boost); } class Lucy::Search::MatchAllCompiler diff --git a/core/Lucy/Search/NOTQuery.c b/core/Lucy/Search/NOTQuery.c index 51a46fa7f..3b84e4868 100644 --- a/core/Lucy/Search/NOTQuery.c +++ b/core/Lucy/Search/NOTQuery.c @@ -72,13 +72,8 @@ NOTQuery_Equals_IMP(NOTQuery *self, Obj *other) { } Compiler* -NOTQuery_Make_Compiler_IMP(NOTQuery *self, Searcher *searcher, float boost, - bool subordinate) { - NOTCompiler *compiler = NOTCompiler_new(self, searcher, boost); - if (!subordinate) { - NOTCompiler_Normalize(compiler); - } - return (Compiler*)compiler; +NOTQuery_Make_Compiler_IMP(NOTQuery *self, Searcher *searcher, float boost) { + return (Compiler*)NOTCompiler_new(self, searcher, boost); } /**********************************************************************/ diff --git a/core/Lucy/Search/NOTQuery.cfh b/core/Lucy/Search/NOTQuery.cfh index 8e6e77247..9ae65ac4a 100644 --- a/core/Lucy/Search/NOTQuery.cfh +++ b/core/Lucy/Search/NOTQuery.cfh @@ -52,8 +52,7 @@ public class Lucy::Search::NOTQuery inherits Lucy::Search::PolyQuery { Set_Negated_Query(NOTQuery *self, Query *negated_query); public incremented Compiler* - Make_Compiler(NOTQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(NOTQuery *self, Searcher *searcher, float boost); public incremented String* To_String(NOTQuery *self); diff --git a/core/Lucy/Search/NoMatchQuery.c b/core/Lucy/Search/NoMatchQuery.c index 533f271d9..6a1924821 100644 --- a/core/Lucy/Search/NoMatchQuery.c +++ b/core/Lucy/Search/NoMatchQuery.c @@ -61,12 +61,8 @@ NoMatchQuery_To_String_IMP(NoMatchQuery *self) { Compiler* NoMatchQuery_Make_Compiler_IMP(NoMatchQuery *self, Searcher *searcher, - float boost, bool subordinate) { - NoMatchCompiler *compiler = NoMatchCompiler_new(self, searcher, boost); - if (!subordinate) { - NoMatchCompiler_Normalize(compiler); - } - return (Compiler*)compiler; + float boost) { + return (Compiler*)NoMatchCompiler_new(self, searcher, boost); } void diff --git a/core/Lucy/Search/NoMatchQuery.cfh b/core/Lucy/Search/NoMatchQuery.cfh index b9f93903a..53aff1fe4 100644 --- a/core/Lucy/Search/NoMatchQuery.cfh +++ b/core/Lucy/Search/NoMatchQuery.cfh @@ -62,8 +62,7 @@ public class Lucy::Search::NoMatchQuery inherits Lucy::Search::Query { To_String(NoMatchQuery *self); public incremented Compiler* - Make_Compiler(NoMatchQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(NoMatchQuery *self, Searcher *searcher, float boost); } class Lucy::Search::NoMatchCompiler diff --git a/core/Lucy/Search/ORQuery.c b/core/Lucy/Search/ORQuery.c index 4a6fb3231..7bcf39646 100644 --- a/core/Lucy/Search/ORQuery.c +++ b/core/Lucy/Search/ORQuery.c @@ -40,13 +40,8 @@ ORQuery_init(ORQuery *self, Vector *children) { } Compiler* -ORQuery_Make_Compiler_IMP(ORQuery *self, Searcher *searcher, float boost, - bool subordinate) { - ORCompiler *compiler = ORCompiler_new(self, searcher, boost); - if (!subordinate) { - ORCompiler_Normalize(compiler); - } - return (Compiler*)compiler; +ORQuery_Make_Compiler_IMP(ORQuery *self, Searcher *searcher, float boost) { + return (Compiler*)ORCompiler_new(self, searcher, boost); } bool diff --git a/core/Lucy/Search/ORQuery.cfh b/core/Lucy/Search/ORQuery.cfh index 66c747182..d9c12edb0 100644 --- a/core/Lucy/Search/ORQuery.cfh +++ b/core/Lucy/Search/ORQuery.cfh @@ -41,8 +41,7 @@ public class Lucy::Search::ORQuery inherits Lucy::Search::PolyQuery { init(ORQuery *self, Vector *children = NULL); public incremented Compiler* - Make_Compiler(ORQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(ORQuery *self, Searcher *searcher, float boost); public incremented String* To_String(ORQuery *self); diff --git a/core/Lucy/Search/PhraseQuery.c b/core/Lucy/Search/PhraseQuery.c index 960590387..1c5363854 100644 --- a/core/Lucy/Search/PhraseQuery.c +++ b/core/Lucy/Search/PhraseQuery.c @@ -159,7 +159,7 @@ PhraseQuery_To_String_IMP(PhraseQuery *self) { Compiler* PhraseQuery_Make_Compiler_IMP(PhraseQuery *self, Searcher *searcher, - float boost, bool subordinate) { + float boost) { PhraseQueryIVARS *const ivars = PhraseQuery_IVARS(self); if (Vec_Get_Size(ivars->terms) == 1) { // Optimize for one-term "phrases". @@ -169,17 +169,12 @@ PhraseQuery_Make_Compiler_IMP(PhraseQuery *self, Searcher *searcher, TermQuery_Set_Boost(term_query, ivars->boost); term_compiler = (TermCompiler*)TermQuery_Make_Compiler(term_query, searcher, - boost, subordinate); + boost); DECREF(term_query); return (Compiler*)term_compiler; } else { - PhraseCompiler *compiler - = PhraseCompiler_new(self, searcher, boost); - if (!subordinate) { - PhraseCompiler_Normalize(compiler); - } - return (Compiler*)compiler; + return (Compiler*)PhraseCompiler_new(self, searcher, boost); } } diff --git a/core/Lucy/Search/PhraseQuery.cfh b/core/Lucy/Search/PhraseQuery.cfh index 587b36c43..df95e936d 100644 --- a/core/Lucy/Search/PhraseQuery.cfh +++ b/core/Lucy/Search/PhraseQuery.cfh @@ -54,8 +54,7 @@ public class Lucy::Search::PhraseQuery inherits Lucy::Search::Query { Get_Terms(PhraseQuery *self); public incremented Compiler* - Make_Compiler(PhraseQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(PhraseQuery *self, Searcher *searcher, float boost); public bool Equals(PhraseQuery *self, Obj *other); diff --git a/core/Lucy/Search/PolyQuery.c b/core/Lucy/Search/PolyQuery.c index 2bc5daa03..13de25eb9 100644 --- a/core/Lucy/Search/PolyQuery.c +++ b/core/Lucy/Search/PolyQuery.c @@ -144,7 +144,7 @@ PolyCompiler_init(PolyCompiler *self, PolyQuery *parent, Query *child_query = (Query*)Vec_Fetch(parent_ivars->children, i); float sub_boost = boost * Query_Get_Boost(child_query); Compiler *child_compiler - = Query_Make_Compiler(child_query, searcher, sub_boost, true); + = Query_Make_Compiler(child_query, searcher, sub_boost); Vec_Push(ivars->children, (Obj*)child_compiler); } diff --git a/core/Lucy/Search/PolySearcher.c b/core/Lucy/Search/PolySearcher.c index 002b73601..8ae818b32 100644 --- a/core/Lucy/Search/PolySearcher.c +++ b/core/Lucy/Search/PolySearcher.c @@ -148,9 +148,7 @@ PolySearcher_Top_Docs_IMP(PolySearcher *self, Query *query, uint32_t total_hits = 0; Compiler *compiler = Query_is_a(query, COMPILER) ? ((Compiler*)INCREF(query)) - : Query_Make_Compiler(query, (Searcher*)self, - Query_Get_Boost(query), - false); + : Query_Make_Root_Compiler(query, (Searcher*)self); for (size_t i = 0, max = Vec_Get_Size(searchers); i < max; i++) { Searcher *searcher = (Searcher*)Vec_Fetch(searchers, i); diff --git a/core/Lucy/Search/Query.c b/core/Lucy/Search/Query.c index 85fa672f4..75b1258ab 100644 --- a/core/Lucy/Search/Query.c +++ b/core/Lucy/Search/Query.c @@ -31,6 +31,43 @@ Query_init(Query *self, float boost) { return self; } +Compiler* +Query_Make_Root_Compiler_IMP(Query *self, Searcher *searcher) { + Compiler *compiler + = Query_Make_Compiler(self, searcher, Query_Get_Boost(self)); + Compiler_Normalize(compiler); + return compiler; +} + +// Default implementation for old Perl API. +Compiler* +Query_Make_Compiler_IMP(Query *self, Searcher *searcher, float boost) { + return Query_Make_Compiler_Compat(self, searcher, boost, true); +} + +// For old Perl API. +Compiler* +Query_Make_Compiler_Compat_IMP(Query *self, Searcher *searcher, float boost, + bool subordinate) { + Class *klass = Query_get_class(self); + LUCY_Query_Make_Compiler_t make_compiler + = METHOD_PTR(klass, LUCY_Query_Make_Compiler); + if (make_compiler == Query_Make_Compiler_IMP) { + // Detect infinite recursion. + THROW(ERR, "Method 'Make_Compiler' not defined by %o", + Class_Get_Name(klass)); + } + Compiler *compiler = make_compiler(self, searcher, boost); + + if (!subordinate) { + Schema *schema = Searcher_Get_Schema(searcher); + Similarity *sim = Schema_Get_Similarity(schema); + Compiler_Normalize(compiler, sim); + } + + return compiler; +} + void Query_Set_Boost_IMP(Query *self, float boost) { Query_IVARS(self)->boost = boost; diff --git a/core/Lucy/Search/Query.cfh b/core/Lucy/Search/Query.cfh index 8b19d4b5e..ee7a5a7c4 100644 --- a/core/Lucy/Search/Query.cfh +++ b/core/Lucy/Search/Query.cfh @@ -48,18 +48,24 @@ public class Lucy::Search::Query inherits Clownfish::Obj { public inert Query* init(Query *self, float boost = 1.0); + /** Derive a Compiler from the Query and normalize it. + */ + public incremented Compiler* + Make_Root_Compiler(Query *self, Searcher *searcher); + /** Abstract factory method returning a Compiler derived from this Query. * * @param searcher A Searcher. * @param boost A scoring multiplier. - * @param subordinate Indicates whether the Query is a subquery (as - * opposed to a top-level query). If false, the implementation must - * invoke [](cfish:Compiler.Normalize) on the newly minted Compiler object before returning - * it. */ - public abstract incremented Compiler* - Make_Compiler(Query *self, Searcher *searcher, float boost, - bool subordinate = false); + public incremented Compiler* + Make_Compiler(Query *self, Searcher *searcher, float boost); + + /** For backward compatibility with old API. + */ + incremented Compiler* + Make_Compiler_Compat(Query *self, Searcher *searcher, float boost, + bool subordinate = false); /** Set the Query's boost. */ diff --git a/core/Lucy/Search/RangeQuery.c b/core/Lucy/Search/RangeQuery.c index 18c6c1055..4b61686de 100644 --- a/core/Lucy/Search/RangeQuery.c +++ b/core/Lucy/Search/RangeQuery.c @@ -214,12 +214,8 @@ RangeQuery_Load_IMP(RangeQuery *self, Obj *dump) { Compiler* RangeQuery_Make_Compiler_IMP(RangeQuery *self, Searcher *searcher, - float boost, bool subordinate) { - RangeCompiler *compiler = RangeCompiler_new(self, searcher, boost); - if (!subordinate) { - RangeCompiler_Normalize(compiler); - } - return (Compiler*)compiler; + float boost) { + return (Compiler*)RangeCompiler_new(self, searcher, boost); } /**********************************************************************/ diff --git a/core/Lucy/Search/RangeQuery.cfh b/core/Lucy/Search/RangeQuery.cfh index 2c4624c95..ea8a1fdcf 100644 --- a/core/Lucy/Search/RangeQuery.cfh +++ b/core/Lucy/Search/RangeQuery.cfh @@ -64,8 +64,7 @@ public class Lucy::Search::RangeQuery inherits Lucy::Search::Query { To_String(RangeQuery *self); public incremented Compiler* - Make_Compiler(RangeQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(RangeQuery *self, Searcher *searcher, float boost); void Serialize(RangeQuery *self, OutStream *outstream); diff --git a/core/Lucy/Search/RequiredOptionalQuery.c b/core/Lucy/Search/RequiredOptionalQuery.c index 0f76a1aa7..901453509 100644 --- a/core/Lucy/Search/RequiredOptionalQuery.c +++ b/core/Lucy/Search/RequiredOptionalQuery.c @@ -91,13 +91,8 @@ ReqOptQuery_Equals_IMP(RequiredOptionalQuery *self, Obj *other) { Compiler* ReqOptQuery_Make_Compiler_IMP(RequiredOptionalQuery *self, Searcher *searcher, - float boost, bool subordinate) { - RequiredOptionalCompiler *compiler - = ReqOptCompiler_new(self, searcher, boost); - if (!subordinate) { - ReqOptCompiler_Normalize(compiler); - } - return (Compiler*)compiler; + float boost) { + return (Compiler*)ReqOptCompiler_new(self, searcher, boost); } /**********************************************************************/ diff --git a/core/Lucy/Search/RequiredOptionalQuery.cfh b/core/Lucy/Search/RequiredOptionalQuery.cfh index 35481a40d..bb09182a4 100644 --- a/core/Lucy/Search/RequiredOptionalQuery.cfh +++ b/core/Lucy/Search/RequiredOptionalQuery.cfh @@ -61,7 +61,7 @@ public class Lucy::Search::RequiredOptionalQuery nickname ReqOptQuery public incremented Compiler* Make_Compiler(RequiredOptionalQuery *self, Searcher *searcher, - float boost, bool subordinate = false); + float boost); public incremented String* To_String(RequiredOptionalQuery *self); diff --git a/core/Lucy/Search/TermQuery.c b/core/Lucy/Search/TermQuery.c index e9d6c8f4d..ddf609eda 100644 --- a/core/Lucy/Search/TermQuery.c +++ b/core/Lucy/Search/TermQuery.c @@ -131,14 +131,8 @@ TermQuery_To_String_IMP(TermQuery *self) { } Compiler* -TermQuery_Make_Compiler_IMP(TermQuery *self, Searcher *searcher, float boost, - bool subordinate) { - TermCompiler *compiler = TermCompiler_new((Query*)self, searcher, boost); - if (!subordinate) { - TermCompiler_Normalize(compiler); - } - return (Compiler*)compiler; - +TermQuery_Make_Compiler_IMP(TermQuery *self, Searcher *searcher, float boost) { + return (Compiler*)TermCompiler_new((Query*)self, searcher, boost); } /******************************************************************/ diff --git a/core/Lucy/Search/TermQuery.cfh b/core/Lucy/Search/TermQuery.cfh index b2fc00fbf..d9ee6223c 100644 --- a/core/Lucy/Search/TermQuery.cfh +++ b/core/Lucy/Search/TermQuery.cfh @@ -55,8 +55,7 @@ public class Lucy::Search::TermQuery inherits Lucy::Search::Query { Get_Term(TermQuery *self); public incremented Compiler* - Make_Compiler(TermQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(TermQuery *self, Searcher *searcher, float boost); public incremented String* To_String(TermQuery *self); diff --git a/core/LucyX/Search/ProximityQuery.c b/core/LucyX/Search/ProximityQuery.c index 7c4e215c4..29fdbfa55 100644 --- a/core/LucyX/Search/ProximityQuery.c +++ b/core/LucyX/Search/ProximityQuery.c @@ -172,7 +172,7 @@ ProximityQuery_To_String_IMP(ProximityQuery *self) { Compiler* ProximityQuery_Make_Compiler_IMP(ProximityQuery *self, Searcher *searcher, - float boost, bool subordinate) { + float boost) { ProximityQueryIVARS *const ivars = ProximityQuery_IVARS(self); if (Vec_Get_Size(ivars->terms) == 1) { // Optimize for one-term "phrases". @@ -181,17 +181,13 @@ ProximityQuery_Make_Compiler_IMP(ProximityQuery *self, Searcher *searcher, TermQuery_Set_Boost(term_query, ivars->boost); TermCompiler *term_compiler = (TermCompiler*)TermQuery_Make_Compiler(term_query, searcher, - boost, subordinate); + boost); DECREF(term_query); return (Compiler*)term_compiler; } else { - ProximityCompiler *compiler - = ProximityCompiler_new(self, searcher, boost, ivars->within); - if (!subordinate) { - ProximityCompiler_Normalize(compiler); - } - return (Compiler*)compiler; + return (Compiler*)ProximityCompiler_new(self, searcher, boost, + ivars->within); } } diff --git a/core/LucyX/Search/ProximityQuery.cfh b/core/LucyX/Search/ProximityQuery.cfh index c3798ffb5..106ebbc93 100644 --- a/core/LucyX/Search/ProximityQuery.cfh +++ b/core/LucyX/Search/ProximityQuery.cfh @@ -60,8 +60,7 @@ public class LucyX::Search::ProximityQuery inherits Lucy::Search::Query { Get_Within(ProximityQuery *self); public incremented Compiler* - Make_Compiler(ProximityQuery *self, Searcher *searcher, float boost, - bool subordinate = false); + Make_Compiler(ProximityQuery *self, Searcher *searcher, float boost); public bool Equals(ProximityQuery *self, Obj *other); diff --git a/go/build.go b/go/build.go index 095efb2b3..416dfe962 100644 --- a/go/build.go +++ b/go/build.go @@ -315,7 +315,7 @@ func specClasses(parcel *cfc.Parcel) { hitsBinding.Register() queryBinding := cfc.NewGoClass(parcel, "Lucy::Search::Query") - queryBinding.SpecMethod("Make_Compiler", "MakeCompiler(Searcher, float32, bool) (Compiler, error)") + queryBinding.SpecMethod("Make_Root_Compiler", "MakeRootCompiler(Searcher) (Compiler, error)") queryBinding.Register() compilerBinding := cfc.NewGoClass(parcel, "Lucy::Search::Compiler") diff --git a/go/lucy/search.go b/go/lucy/search.go index d0a1dbec7..097905453 100644 --- a/go/lucy/search.go +++ b/go/lucy/search.go @@ -291,12 +291,11 @@ func (td *TopDocsIMP) GetMatchDocs() []MatchDoc { return slice } -func (q *QueryIMP) MakeCompiler(searcher Searcher, boost float32, - subordinate bool) (retval Compiler, err error) { +func (q *QueryIMP) MakeRootCompiler(searcher Searcher) (retval Compiler, err error) { err = clownfish.TrapErr(func() { self := (*C.lucy_Query)(clownfish.Unwrap(q, "q")) searcherCF := (*C.lucy_Searcher)(clownfish.Unwrap(searcher, "searcher")) - retvalCF := C.LUCY_Query_Make_Compiler(self, searcherCF, C.float(boost), C.bool(subordinate)) + retvalCF := C.LUCY_Query_Make_Root_Compiler(self, searcherCF) if retvalCF != nil { retval = clownfish.WRAPAny(unsafe.Pointer(retvalCF)).(Compiler) } diff --git a/go/lucy/search_test.go b/go/lucy/search_test.go index a135975e6..25da159b6 100644 --- a/go/lucy/search_test.go +++ b/go/lucy/search_test.go @@ -52,12 +52,12 @@ func checkQueryEquals(t *testing.T, query Query) { } } -func checkQueryMakeCompiler(t *testing.T, query Query) { +func checkQueryMakeRootCompiler(t *testing.T, query Query) { index := createTestIndex("foo", "bar", "baz") searcher, _ := OpenIndexSearcher(index) - compiler, err := query.MakeCompiler(searcher, 1.0, false) + compiler, err := query.MakeRootCompiler(searcher) if _, ok := compiler.(Compiler); !ok || err != nil { - t.Error("MakeCompiler for %v failed: %v", query, err) + t.Error("MakeRootCompiler for %v failed: %v", query, err) } } @@ -73,7 +73,7 @@ func TestTermQueryMisc(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -118,7 +118,7 @@ func TestPhraseQueryMisc(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -164,7 +164,7 @@ func TestANDQueryBasics(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -177,7 +177,7 @@ func TestORQueryBasics(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -188,7 +188,7 @@ func TestReqOptQueryBasics(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -210,7 +210,7 @@ func TestNOTQueryBasics(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -227,7 +227,7 @@ func TestMatchAllQueryBasics(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) } func TestNOMatchQueryBasics(t *testing.T) { @@ -235,7 +235,7 @@ func TestNOMatchQueryBasics(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) } func TestRangeQueryBasics(t *testing.T) { @@ -243,7 +243,7 @@ func TestRangeQueryBasics(t *testing.T) { checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) checkQueryEquals(t, query) - checkQueryMakeCompiler(t, query) + checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } diff --git a/perl/buildlib/Lucy/Build/Binding/Search.pm b/perl/buildlib/Lucy/Build/Binding/Search.pm index 3ceace765..6d3ddcb0e 100644 --- a/perl/buildlib/Lucy/Build/Binding/Search.pm +++ b/perl/buildlib/Lucy/Build/Binding/Search.pm @@ -574,10 +574,7 @@ sub bind_query { sub make_compiler { my ( $self, %args ) = @_; - my $subordinate = delete $args{subordinate}; - my $compiler = MyCompiler->new( %args, parent => $self ); - $compiler->normalize unless $subordinate; - return $compiler; + return MyCompiler->new; } package MyCompiler; @@ -606,11 +603,20 @@ and MatchAllQuery default to 0.0 instead. END_CONSTRUCTOR_POD $pod_spec->set_synopsis($synopsis); $pod_spec->add_constructor( alias => 'new', pod => $constructor, ); + $pod_spec->add_method( + alias => 'make_compiler', + method => 'Make_Compiler', + ); my $binding = Clownfish::CFC::Binding::Perl::Class->new( parcel => "Lucy", class_name => "Lucy::Search::Query", ); + $binding->exclude_method('Make_Compiler'); + $binding->bind_method( + alias => 'make_compiler', + method => 'Make_Compiler_Compat', + ); $binding->set_pod_spec($pod_spec); Clownfish::CFC::Binding::Perl::Class->register($binding); diff --git a/perl/lib/LucyX/Remote/ClusterSearcher.pm b/perl/lib/LucyX/Remote/ClusterSearcher.pm index 1e7543eda..675eafaca 100644 --- a/perl/lib/LucyX/Remote/ClusterSearcher.pm +++ b/perl/lib/LucyX/Remote/ClusterSearcher.pm @@ -267,10 +267,7 @@ sub top_docs { my $compiler = $query->isa("Lucy::Search::Compiler") ? $query - : $query->make_compiler( - searcher => $self, - boost => $query->get_boost, - ); + : $query->make_root_compiler($self); # Create HitQueue. my $hit_q; diff --git a/perl/lib/LucyX/Search/Filter.pm b/perl/lib/LucyX/Search/Filter.pm index 63789d384..84248db0f 100644 --- a/perl/lib/LucyX/Search/Filter.pm +++ b/perl/lib/LucyX/Search/Filter.pm @@ -52,11 +52,7 @@ sub DESTROY { sub make_compiler { my ( $self, %args ) = @_; - my $subordinate = delete $args{subordinate}; - my $compiler - = LucyX::Search::FilterCompiler->new( %args, parent => $self ); - $compiler->normalize unless $subordinate; - return $compiler; + return LucyX::Search::FilterCompiler->new( %args, parent => $self ); } sub serialize { diff --git a/perl/sample/PrefixQuery.pm b/perl/sample/PrefixQuery.pm index 0cf41bf55..bdaa75959 100644 --- a/perl/sample/PrefixQuery.pm +++ b/perl/sample/PrefixQuery.pm @@ -69,10 +69,7 @@ sub to_string { sub make_compiler { my ( $self, %args ) = @_; - my $subordinate = delete $args{subordinate}; - my $compiler = PrefixCompiler->new( %args, parent => $self ); - $compiler->normalize unless $subordinate; - return $compiler; + return PrefixCompiler->new( %args, parent => $self ); } package PrefixCompiler; diff --git a/perl/t/501-termquery.t b/perl/t/501-termquery.t index 68ad90eb1..3882c378b 100644 --- a/perl/t/501-termquery.t +++ b/perl/t/501-termquery.t @@ -58,10 +58,7 @@ my $different_field = Lucy::Search::TermQuery->new( ok( !$term_query->equals($different_term), "!equals (term)" ); ok( !$term_query->equals($different_field), "!equals (field)" ); -my $term_compiler = $term_query->make_compiler( - searcher => $searcher, - boost => $term_query->get_boost, -); +my $term_compiler = $term_query->make_root_compiler($searcher); $frozen = freeze($term_compiler); $thawed = thaw($frozen); ok( $term_compiler->equals($thawed), "freeze/thaw compiler" ); diff --git a/perl/t/502-phrasequery.t b/perl/t/502-phrasequery.t index b924ac1b3..6f5a7dbf9 100644 --- a/perl/t/502-phrasequery.t +++ b/perl/t/502-phrasequery.t @@ -78,10 +78,7 @@ my $thawed = thaw($frozen); $hits = $searcher->hits( query => $thawed ); is( $hits->total_hits, 3, 'freeze/thaw' ); -my $phrase_compiler = $phrase_query->make_compiler( - searcher => $searcher, - boost => $phrase_query->get_boost, -); +my $phrase_compiler = $phrase_query->make_root_compiler($searcher); $frozen = freeze($phrase_compiler); $thawed = thaw($frozen); ok( $phrase_compiler->equals($thawed), "freeze/thaw compiler" ); diff --git a/perl/t/515-range_query.t b/perl/t/515-range_query.t index 81c51e891..867eee800 100644 --- a/perl/t/515-range_query.t +++ b/perl/t/515-range_query.t @@ -288,10 +288,7 @@ sub test_range_search { my $thawed = thaw($frozen); ok( $query->equals($thawed), 'equals' ); - my $compiler = $query->make_compiler( - searcher => $searcher, - boost => $query->get_boost, - ); + my $compiler = $query->make_root_compiler($searcher); $frozen = nfreeze($compiler); $thawed = thaw($frozen); ok( $compiler->equals($thawed), "freeze/thaw compiler" ); diff --git a/perl/t/523-and_query.t b/perl/t/523-and_query.t index e7557c66e..8d0247bd8 100644 --- a/perl/t/523-and_query.t +++ b/perl/t/523-and_query.t @@ -56,10 +56,7 @@ ok( !$and_query->equals($different_children), my $one_child = Lucy::Search::ANDQuery->new( children => [$a_query] ); ok( !$and_query->equals($one_child), '!equals (too few children)' ); -my $and_compiler = $and_query->make_compiler( - searcher => $searcher, - boost => $and_query->get_boost, -); +my $and_compiler = $and_query->make_root_compiler($searcher); isa_ok( $and_compiler, "Lucy::Search::ANDCompiler", "make_compiler" ); $frozen = freeze($and_compiler); $thawed = thaw($frozen); @@ -71,9 +68,8 @@ my $and_matcher = $and_compiler->make_matcher( ); isa_ok( $and_matcher, "Lucy::Search::ANDMatcher", "make_matcher" ); -my $term_matcher = $one_child->make_compiler( - searcher => $searcher, - boost => $one_child->get_boost, +my $term_matcher = $one_child->make_root_compiler( + $searcher, )->make_matcher( reader => $reader, need_score => 0 ); isa_ok( $term_matcher, "Lucy::Search::TermMatcher", "make_matcher compiles to child's Matcher if there's only one child" ); @@ -83,9 +79,8 @@ my $hopeless_query = Lucy::Search::TermQuery->new( term => 'nein', ); $and_query->add_child($hopeless_query); -my $nope = $and_query->make_compiler( - searcher => $searcher, - boost => $and_query->get_boost, +my $nope = $and_query->make_root_compiler( + $searcher, )->make_matcher( reader => $reader, need_score => 0 ); ok( !defined $nope, "If matcher wouldn't return any docs, make_matcher returns undef" ); diff --git a/perl/t/524-poly_query.t b/perl/t/524-poly_query.t index 7f886c013..35980cd95 100644 --- a/perl/t/524-poly_query.t +++ b/perl/t/524-poly_query.t @@ -52,10 +52,7 @@ for my $conjunction (qw( AND OR )) { my $one_child = $class->new( children => [$a_query] ); ok( !$polyquery->equals($one_child), '!equals (too few children)' ); - my $compiler = $polyquery->make_compiler( - searcher => $searcher, - boost => $polyquery->get_boost, - ); + my $compiler = $polyquery->make_root_compiler($searcher); isa_ok( $compiler, "Lucy::Search::${conjunction}Compiler", "make_compiler" ); $frozen = freeze($compiler); @@ -70,9 +67,8 @@ for my $conjunction (qw( AND OR )) { : 'Lucy::Search::ORScorer'; isa_ok( $matcher, $wanted_class, "make_matcher with need_score" ); - my $term_matcher = $one_child->make_compiler( - searcher => $searcher, - boost => $one_child->get_boost, + my $term_matcher = $one_child->make_root_compiler( + $searcher, )->make_matcher( reader => $reader, need_score => 0 ); isa_ok( $term_matcher, "Lucy::Search::TermMatcher", "make_matcher compiles to child's Matcher if there's only one child" @@ -88,9 +84,8 @@ for my $conjunction (qw( AND OR )) { ); $polyquery = $class->new( children => [ $hopeless_query, $doomed_query ] ); - my $nope = $polyquery->make_compiler( - searcher => $searcher, - boost => $polyquery->get_boost, + my $nope = $polyquery->make_root_compiler( + $searcher, )->make_matcher( reader => $reader, need_score => 0 ); ok( !defined $nope, "If Matcher wouldn't return any docs, make_matcher returns undef" ); diff --git a/perl/t/525-match_all_query.t b/perl/t/525-match_all_query.t index f45d5ba9d..99ab4a52a 100644 --- a/perl/t/525-match_all_query.t +++ b/perl/t/525-match_all_query.t @@ -52,10 +52,7 @@ ok( $match_all_query->equals($thawed), "equals" ); $thawed->set_boost(10); ok( !$match_all_query->equals($thawed), '!equals (boost)' ); -my $compiler = $match_all_query->make_compiler( - searcher => $searcher, - boost => $match_all_query->get_boost, -); +my $compiler = $match_all_query->make_root_compiler($searcher); $frozen = freeze($compiler); $thawed = thaw($frozen); ok( $thawed->equals($compiler), "freeze/thaw compiler" ); diff --git a/perl/t/526-not_query.t b/perl/t/526-not_query.t index c5541c512..67b389792 100644 --- a/perl/t/526-not_query.t +++ b/perl/t/526-not_query.t @@ -60,10 +60,7 @@ ok( !$not_b_query->equals($thawed), '!equals (boost)' ); ok( !$not_b_query->equals($not_c_query), "!equals (different negated query)" ); -my $compiler = $not_b_query->make_compiler( - searcher => $searcher, - boost => $not_b_query->get_boost, -); +my $compiler = $not_b_query->make_root_compiler($searcher); $frozen = freeze($compiler); $thawed = thaw($frozen); ok( $thawed->equals($compiler), 'freeze/thaw compiler' ); diff --git a/perl/t/527-req_opt_query.t b/perl/t/527-req_opt_query.t index 3b3f48dae..fed371902 100644 --- a/perl/t/527-req_opt_query.t +++ b/perl/t/527-req_opt_query.t @@ -44,10 +44,7 @@ my $req_opt_query = Lucy::Search::RequiredOptionalQuery->new( ); is( $req_opt_query->to_string, "(+content:b content:c)", "to_string" ); -my $compiler = $req_opt_query->make_compiler( - searcher => $searcher, - boost => $req_opt_query->get_boost, -); +my $compiler = $req_opt_query->make_root_compiler($searcher); my $frozen = freeze($compiler); my $thawed = thaw($frozen); ok( $thawed->equals($compiler), "freeze/thaw compiler" ); @@ -58,9 +55,8 @@ $req_opt_query = Lucy::Search::RequiredOptionalQuery->new( required_query => $x_query, optional_query => $b_query, ); -$matcher = $req_opt_query->make_compiler( - searcher => $searcher, - boost => $req_opt_query->get_boost, +$matcher = $req_opt_query->make_root_compiler( + $searcher, )->make_matcher( reader => $reader, need_score => 0 ); ok( !defined($matcher), "if required matcher has no match, return undef" ); diff --git a/perl/t/529-no_match_query.t b/perl/t/529-no_match_query.t index e983d688f..1f31cf705 100644 --- a/perl/t/529-no_match_query.t +++ b/perl/t/529-no_match_query.t @@ -36,10 +36,7 @@ ok( $no_match_query->equals($thawed), "equals" ); $thawed->set_boost(10); ok( !$no_match_query->equals($thawed), '!equals (boost)' ); -my $compiler = $no_match_query->make_compiler( - searcher => $searcher, - boost => $no_match_query->get_boost, -); +my $compiler = $no_match_query->make_root_compiler($searcher); $frozen = freeze($compiler); $thawed = thaw($frozen); ok( $compiler->equals($thawed), "freeze/thaw compiler" ); diff --git a/perl/t/613-proximityquery.t b/perl/t/613-proximityquery.t index b571e09eb..63b748736 100644 --- a/perl/t/613-proximityquery.t +++ b/perl/t/613-proximityquery.t @@ -86,10 +86,7 @@ my $thawed = thaw($frozen); $hits = $searcher->hits( query => $thawed ); is( $hits->total_hits, 4, 'freeze/thaw' ); -my $proximity_compiler = $proximity_query->make_compiler( - searcher => $searcher, - boost => $proximity_query->get_boost, -); +my $proximity_compiler = $proximity_query->make_root_compiler($searcher); $frozen = freeze($proximity_compiler); $thawed = thaw($frozen); ok( $proximity_compiler->equals($thawed), "freeze/thaw compiler" ); diff --git a/perl/t/binding/303-highlighter.t b/perl/t/binding/303-highlighter.t index 5ff0d7e5a..bf905276d 100644 --- a/perl/t/binding/303-highlighter.t +++ b/perl/t/binding/303-highlighter.t @@ -109,10 +109,7 @@ like( ); $q = $searcher->glean_query("foo"); -my $compiler = $q->make_compiler( - searcher => $searcher, - boost => $q->get_boost, -); +my $compiler = $q->make_root_compiler($searcher); $hl = Lucy::Highlight::Highlighter->new( searcher => $searcher, query => $compiler, diff --git a/perl/t/binding/800-stack.t b/perl/t/binding/800-stack.t index ed84821d5..3bda4f41c 100644 --- a/perl/t/binding/800-stack.t +++ b/perl/t/binding/800-stack.t @@ -24,10 +24,7 @@ use base qw( Lucy::Search::Query ); sub make_compiler { my ( $self, %args ) = @_; - my $subordinate = delete $args{subordinate}; - my $compiler = MyCompiler->new( %args, parent => $self ); - $compiler->normalize unless $subordinate; - return $compiler; + return MyCompiler->new( %args, parent => $self ); } package MyCompiler; @@ -47,10 +44,7 @@ for ( 1 .. 50 ) { $q = Lucy::Search::ORQuery->new( children => \@kids ); } my $searcher = MockSearcher->new( schema => Lucy::Plan::Schema->new ); -my $compiler = $q->make_compiler( - searcher => $searcher, - boost => $q->get_boost, -); +my $compiler = $q->make_root_compiler($searcher); pass("Made it through deep recursion with multiple stack reallocations"); From 5f1cdc99a6a49387efbeff11d76f2cfdbe20d27d Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Mon, 20 Mar 2017 16:06:49 +0100 Subject: [PATCH 5/8] Remove Compiler ivars Also make Compiler inherit directly from Obj instead of Query. This requires separate Equals and serialization methods for all Compilers. Add 'sim' parameter to Compiler_Normalize. Remove Highlighter_Get_Query. Keep the Perl API backward compatible. --- core/Lucy/Highlight/Highlighter.c | 15 ++-- core/Lucy/Highlight/Highlighter.cfh | 10 +-- core/Lucy/Search/ANDQuery.c | 25 ++++-- core/Lucy/Search/ANDQuery.cfh | 7 +- core/Lucy/Search/Compiler.c | 85 +----------------- core/Lucy/Search/Compiler.cfh | 50 ++--------- core/Lucy/Search/IndexSearcher.c | 19 ++-- core/Lucy/Search/IndexSearcher.cfh | 4 +- core/Lucy/Search/MatchAllQuery.c | 43 ++++++--- core/Lucy/Search/MatchAllQuery.cfh | 16 +++- core/Lucy/Search/NOTQuery.c | 22 +++-- core/Lucy/Search/NOTQuery.cfh | 7 +- core/Lucy/Search/NoMatchQuery.c | 36 ++++++-- core/Lucy/Search/NoMatchQuery.cfh | 14 ++- core/Lucy/Search/ORQuery.c | 29 ++++-- core/Lucy/Search/ORQuery.cfh | 7 +- core/Lucy/Search/PhraseMatcher.c | 12 ++- core/Lucy/Search/PhraseMatcher.cfh | 5 +- core/Lucy/Search/PhraseQuery.c | 94 ++++++++++--------- core/Lucy/Search/PhraseQuery.cfh | 20 +++-- core/Lucy/Search/PolyQuery.c | 42 +++++---- core/Lucy/Search/PolyQuery.cfh | 6 +- core/Lucy/Search/PolySearcher.c | 23 +++-- core/Lucy/Search/PolySearcher.cfh | 4 +- core/Lucy/Search/Query.c | 8 +- core/Lucy/Search/RangeQuery.c | 76 +++++++++++----- core/Lucy/Search/RangeQuery.cfh | 20 ++++- core/Lucy/Search/RequiredOptionalQuery.c | 18 ++-- core/Lucy/Search/RequiredOptionalQuery.cfh | 7 +- core/Lucy/Search/Searcher.c | 2 +- core/Lucy/Search/Searcher.cfh | 6 +- core/Lucy/Search/TermQuery.c | 67 +++++++------- core/Lucy/Search/TermQuery.cfh | 20 +++-- core/Lucy/Util/Freezer.c | 7 ++ core/LucyX/Search/ProximityMatcher.c | 12 ++- core/LucyX/Search/ProximityMatcher.cfh | 5 +- core/LucyX/Search/ProximityQuery.c | 100 +++++++++++---------- core/LucyX/Search/ProximityQuery.cfh | 24 ++--- go/lucy/highlight_test.go | 4 - go/lucy/search.go | 2 +- go/lucy/search_test.go | 51 ++++++----- perl/buildlib/Lucy/Build/Binding/Search.pm | 5 ++ perl/lib/Lucy.pm | 61 +++++++++++-- perl/t/binding/303-highlighter.t | 4 +- test/Lucy/Test/Search/TestPolySearcher.c | 2 +- 45 files changed, 621 insertions(+), 475 deletions(-) diff --git a/core/Lucy/Highlight/Highlighter.c b/core/Lucy/Highlight/Highlighter.c index 33df5dfe7..11e4c9f2b 100644 --- a/core/Lucy/Highlight/Highlighter.c +++ b/core/Lucy/Highlight/Highlighter.c @@ -55,18 +55,19 @@ Highlighter* Highlighter_init(Highlighter *self, Searcher *searcher, Obj *query, String *field, uint32_t excerpt_length) { HighlighterIVARS *const ivars = Highlighter_IVARS(self); - ivars->query = Searcher_Glean_Query(searcher, query); ivars->searcher = (Searcher*)INCREF(searcher); ivars->field = Str_Clone(field); ivars->excerpt_length = excerpt_length; ivars->slop = excerpt_length / 3; ivars->pre_tag = Str_new_from_trusted_utf8("", 8); ivars->post_tag = Str_new_from_trusted_utf8("", 9); - if (Query_is_a(ivars->query, COMPILER)) { - ivars->compiler = (Compiler*)INCREF(ivars->query); + if (Obj_is_a(query, COMPILER)) { + ivars->compiler = (Compiler*)INCREF(query); } else { - ivars->compiler = Query_Make_Root_Compiler(ivars->query, searcher); + Query *real_query = Searcher_Glean_Query(searcher, query); + ivars->compiler = Query_Make_Root_Compiler(real_query, searcher); + DECREF(real_query); } return self; } @@ -75,7 +76,6 @@ void Highlighter_Destroy_IMP(Highlighter *self) { HighlighterIVARS *const ivars = Highlighter_IVARS(self); DECREF(ivars->searcher); - DECREF(ivars->query); DECREF(ivars->compiler); DECREF(ivars->field); DECREF(ivars->pre_tag); @@ -129,11 +129,6 @@ Highlighter_Get_Field_IMP(Highlighter *self) { return Highlighter_IVARS(self)->field; } -Query* -Highlighter_Get_Query_IMP(Highlighter *self) { - return Highlighter_IVARS(self)->query; -} - Searcher* Highlighter_Get_Searcher_IMP(Highlighter *self) { return Highlighter_IVARS(self)->searcher; diff --git a/core/Lucy/Highlight/Highlighter.cfh b/core/Lucy/Highlight/Highlighter.cfh index f31337cc8..320480af4 100644 --- a/core/Lucy/Highlight/Highlighter.cfh +++ b/core/Lucy/Highlight/Highlighter.cfh @@ -26,7 +26,6 @@ parcel Lucy; public class Lucy::Highlight::Highlighter inherits Clownfish::Obj { Searcher *searcher; - Query *query; String *field; uint32_t excerpt_length; uint32_t slop; @@ -39,7 +38,7 @@ public class Lucy::Highlight::Highlighter inherits Clownfish::Obj { * @param searcher An object which inherits from * [](cfish:Searcher), such as an * [](cfish:IndexSearcher). - * @param query Query object or a query string. + * @param query Query object, Compiler object, or a query string. * @param field The name of the field from which to draw the excerpt. The * field must marked as be `highlightable` (see * [](cfish:FieldType)). @@ -54,7 +53,7 @@ public class Lucy::Highlight::Highlighter inherits Clownfish::Obj { * @param searcher An object which inherits from * [](cfish:Searcher), such as an * [](cfish:IndexSearcher). - * @param query Query object or a query string. + * @param query Query object, Compiler object, or a query string. * @param field The name of the field from which to draw the excerpt. The * field must marked as be `highlightable` (see * [](cfish:FieldType)). @@ -120,11 +119,6 @@ public class Lucy::Highlight::Highlighter inherits Clownfish::Obj { public Searcher* Get_Searcher(Highlighter *self); - /** Accessor. - */ - public Query* - Get_Query(Highlighter *self); - /** Accessor for the Lucy::Search::Compiler object derived from * `query` and `searcher`. */ diff --git a/core/Lucy/Search/ANDQuery.c b/core/Lucy/Search/ANDQuery.c index 4fb373f02..92e336b6a 100644 --- a/core/Lucy/Search/ANDQuery.c +++ b/core/Lucy/Search/ANDQuery.c @@ -86,19 +86,28 @@ ANDQuery_Make_Compiler_IMP(ANDQuery *self, Searcher *searcher, float boost) { /**********************************************************************/ ANDCompiler* -ANDCompiler_new(ANDQuery *parent, Searcher *searcher, float boost) { +ANDCompiler_new(ANDQuery *query, Searcher *searcher, float boost) { ANDCompiler *self = (ANDCompiler*)Class_Make_Obj(ANDCOMPILER); - return ANDCompiler_init(self, parent, searcher, boost); + return ANDCompiler_init(self, query, searcher, boost); } ANDCompiler* -ANDCompiler_init(ANDCompiler *self, ANDQuery *parent, Searcher *searcher, +ANDCompiler_init(ANDCompiler *self, ANDQuery *query, Searcher *searcher, float boost) { - PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)parent, searcher, - boost); + PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)query, searcher, boost); return self; } +bool +ANDCompiler_Equals_IMP(ANDCompiler *self, Obj *other) { + if ((ANDCompiler*)other == self) { return true; } + if (!Obj_is_a(other, ANDCOMPILER)) { return false; } + ANDCompiler_Equals_t super_equals + = (ANDCompiler_Equals_t)SUPER_METHOD_PTR(ANDCOMPILER, + LUCY_ANDCompiler_Equals); + return super_equals(self, other); +} + Matcher* ANDCompiler_Make_Matcher_IMP(ANDCompiler *self, SegReader *reader, bool need_score) { @@ -128,9 +137,9 @@ ANDCompiler_Make_Matcher_IMP(ANDCompiler *self, SegReader *reader, } } - Matcher *retval - = (Matcher*)ANDMatcher_new(child_matchers, - ANDCompiler_Get_Similarity(self)); + Schema *schema = SegReader_Get_Schema(reader); + Similarity *sim = Schema_Get_Similarity(schema); + Matcher *retval = (Matcher*)ANDMatcher_new(child_matchers, sim); DECREF(child_matchers); return retval; diff --git a/core/Lucy/Search/ANDQuery.cfh b/core/Lucy/Search/ANDQuery.cfh index 3f4b5a6ee..c636470a9 100644 --- a/core/Lucy/Search/ANDQuery.cfh +++ b/core/Lucy/Search/ANDQuery.cfh @@ -52,14 +52,17 @@ class Lucy::Search::ANDCompiler inherits Lucy::Search::PolyCompiler { inert incremented ANDCompiler* - new(ANDQuery *parent, Searcher *searcher, float boost); + new(ANDQuery *query, Searcher *searcher, float boost); inert ANDCompiler* - init(ANDCompiler *self, ANDQuery *parent, Searcher *searcher, + init(ANDCompiler *self, ANDQuery *query, Searcher *searcher, float boost); public incremented nullable Matcher* Make_Matcher(ANDCompiler *self, SegReader *reader, bool need_score); + + public bool + Equals(ANDCompiler *self, Obj *other); } diff --git a/core/Lucy/Search/Compiler.c b/core/Lucy/Search/Compiler.c index cea70f6e3..91db8e312 100644 --- a/core/Lucy/Search/Compiler.c +++ b/core/Lucy/Search/Compiler.c @@ -32,43 +32,11 @@ #include "Lucy/Util/Freezer.h" Compiler* -Compiler_init(Compiler *self, Query *parent, Searcher *searcher, - Similarity *sim, float boost) { - CompilerIVARS *const ivars = Compiler_IVARS(self); - Query_init((Query*)self, boost); - if (!sim) { - Schema *schema = Searcher_Get_Schema(searcher); - sim = Schema_Get_Similarity(schema); - } - ivars->parent = (Query*)INCREF(parent); - ivars->sim = (Similarity*)INCREF(sim); +Compiler_init(Compiler *self) { ABSTRACT_CLASS_CHECK(self, COMPILER); return self; } -void -Compiler_Destroy_IMP(Compiler *self) { - CompilerIVARS *const ivars = Compiler_IVARS(self); - DECREF(ivars->parent); - DECREF(ivars->sim); - SUPER_DESTROY(self, COMPILER); -} - -float -Compiler_Get_Weight_IMP(Compiler *self) { - return Compiler_Get_Boost(self); -} - -Similarity* -Compiler_Get_Similarity_IMP(Compiler *self) { - return Compiler_IVARS(self)->sim; -} - -Query* -Compiler_Get_Parent_IMP(Compiler *self) { - return Compiler_IVARS(self)->parent; -} - float Compiler_Sum_Of_Squared_Weights_IMP(Compiler *self) { UNUSED_VAR(self); @@ -82,14 +50,12 @@ Compiler_Apply_Norm_Factor_IMP(Compiler *self, float factor) { } void -Compiler_Normalize_IMP(Compiler *self) { - CompilerIVARS *const ivars = Compiler_IVARS(self); - +Compiler_Normalize_IMP(Compiler *self, Similarity *sim) { // factor = (tf_q * idf_t) float factor = Compiler_Sum_Of_Squared_Weights(self); // factor /= norm_q - factor = Sim_Query_Norm(ivars->sim, factor); + factor = Sim_Query_Norm(sim, factor); // weight *= factor Compiler_Apply_Norm_Factor(self, factor); @@ -105,48 +71,3 @@ Compiler_Highlight_Spans_IMP(Compiler *self, Searcher *searcher, return Vec_new(0); } -String* -Compiler_To_String_IMP(Compiler *self) { - CompilerIVARS *const ivars = Compiler_IVARS(self); - String *stringified_query = Query_To_String(ivars->parent); - CharBuf *buf = CB_new(0); - CB_Cat_Trusted_Utf8(buf, "compiler(", 9); - CB_Cat(buf, stringified_query); - CB_Cat_Trusted_Utf8(buf, ")", 1); - String *string = CB_Yield_String(buf); - DECREF(buf); - DECREF(stringified_query); - return string; -} - -bool -Compiler_Equals_IMP(Compiler *self, Obj *other) { - if ((Compiler*)other == self) { return true; } - if (!Obj_is_a(other, COMPILER)) { return false; } - CompilerIVARS *const ivars = Compiler_IVARS(self); - CompilerIVARS *const ovars = Compiler_IVARS((Compiler*)other); - if (ivars->boost != ovars->boost) { return false; } - if (!Query_Equals(ivars->parent, (Obj*)ovars->parent)) { return false; } - if (!Sim_Equals(ivars->sim, (Obj*)ovars->sim)) { return false; } - return true; -} - -void -Compiler_Serialize_IMP(Compiler *self, OutStream *outstream) { - CompilerIVARS *const ivars = Compiler_IVARS(self); - ABSTRACT_CLASS_CHECK(self, COMPILER); - OutStream_Write_F32(outstream, ivars->boost); - FREEZE(ivars->parent, outstream); - FREEZE(ivars->sim, outstream); -} - -Compiler* -Compiler_Deserialize_IMP(Compiler *self, InStream *instream) { - CompilerIVARS *const ivars = Compiler_IVARS(self); - ivars->boost = InStream_Read_F32(instream); - ivars->parent = (Query*)THAW(instream); - ivars->sim = (Similarity*)THAW(instream); - return self; -} - - diff --git a/core/Lucy/Search/Compiler.cfh b/core/Lucy/Search/Compiler.cfh index 92c5a8924..b4b64efcd 100644 --- a/core/Lucy/Search/Compiler.cfh +++ b/core/Lucy/Search/Compiler.cfh @@ -30,7 +30,7 @@ parcel Lucy; * However it is common for the Compiler to perform some calculations which * affect it's "weight" -- a floating point multiplier that the Matcher will * factor into each document's score. If that is the case, then the Compiler - * subclass may wish to override [](cfish:.Get_Weight), [](cfish:.Sum_Of_Squared_Weights), and + * subclass may wish to override [](cfish:.Sum_Of_Squared_Weights) and * [](cfish:.Apply_Norm_Factor). * * Compiling a Matcher is a two stage process. @@ -57,23 +57,12 @@ parcel Lucy; * the Matchers's constructor, or whether [](cfish:.Make_Matcher) should return a * Matcher at all. */ -public class Lucy::Search::Compiler inherits Lucy::Search::Query { - - Query *parent; - Similarity *sim; +public class Lucy::Search::Compiler { /** Abstract initializer. - * - * @param parent The parent Query. - * @param searcher A Lucy::Search::Searcher, such as an - * IndexSearcher. - * @param similarity A Similarity. - * @param boost An arbitrary scoring multiplier. Defaults to the boost of - * the parent Query. */ public inert Compiler* - init(Compiler *self, Query *parent, Searcher *searcher, - Similarity *similarity = NULL, float boost); + init(Compiler *self); /** Factory method returning a Matcher. * @@ -85,22 +74,6 @@ public class Lucy::Search::Compiler inherits Lucy::Search::Query { public abstract incremented nullable Matcher* Make_Matcher(Compiler *self, SegReader *reader, bool need_score); - /** Return the Compiler's numerical weight, a scoring multiplier. By - * default, returns the object's boost. - */ - public float - Get_Weight(Compiler *self); - - /** Accessor for the Compiler's Similarity object. - */ - public nullable Similarity* - Get_Similarity(Compiler *self); - - /** Accessor for the Compiler's parent Query object. - */ - public Query* - Get_Parent(Compiler *self); - /** Compute and return a raw weighting factor. (This quantity is used by * [](cfish:.Normalize)). By default, simply returns 1.0. */ @@ -133,10 +106,10 @@ public class Lucy::Search::Compiler inherits Lucy::Search::Query { * implemented. */ public void - Normalize(Compiler *self); + Normalize(Compiler *self, Similarity *sim); /** Return an array of Span objects, indicating where in the given field - * the text that matches the parent Query occurs and how well each snippet + * the text that matches the Query occurs and how well each snippet * matches. The Span's offset and length are measured in Unicode code * points. * @@ -150,20 +123,11 @@ public class Lucy::Search::Compiler inherits Lucy::Search::Query { Highlight_Spans(Compiler *self, Searcher *searcher, DocVector *doc_vec, String *field); - void + abstract void Serialize(Compiler *self, OutStream *outstream); - incremented Compiler* + abstract incremented Compiler* Deserialize(decremented Compiler *self, InStream *instream); - - public bool - Equals(Compiler *self, Obj *other); - - public incremented String* - To_String(Compiler *self); - - public void - Destroy(Compiler *self); } diff --git a/core/Lucy/Search/IndexSearcher.c b/core/Lucy/Search/IndexSearcher.c index cc26848de..48672b616 100644 --- a/core/Lucy/Search/IndexSearcher.c +++ b/core/Lucy/Search/IndexSearcher.c @@ -112,7 +112,7 @@ IxSearcher_Doc_Freq_IMP(IndexSearcher *self, String *field, Obj *term) { } TopDocs* -IxSearcher_Top_Docs_IMP(IndexSearcher *self, Query *query, uint32_t num_wanted, +IxSearcher_Top_Docs_IMP(IndexSearcher *self, Obj *query, uint32_t num_wanted, SortSpec *sort_spec) { Schema *schema = IxSearcher_Get_Schema(self); uint32_t doc_max = (uint32_t)IxSearcher_Doc_Max(self); @@ -128,14 +128,23 @@ IxSearcher_Top_Docs_IMP(IndexSearcher *self, Query *query, uint32_t num_wanted, } void -IxSearcher_Collect_IMP(IndexSearcher *self, Query *query, Collector *collector) { +IxSearcher_Collect_IMP(IndexSearcher *self, Obj *query, Collector *collector) { IndexSearcherIVARS *const ivars = IxSearcher_IVARS(self); Vector *const seg_readers = ivars->seg_readers; I32Array *const seg_starts = ivars->seg_starts; bool need_score = Coll_Need_Score(collector); - Compiler *compiler = Query_is_a(query, COMPILER) - ? (Compiler*)INCREF(query) - : Query_Make_Root_Compiler(query, (Searcher*)self); + Compiler *compiler; + + if (Obj_is_a(query, QUERY)) { + compiler = Query_Make_Root_Compiler((Query*)query, (Searcher*)self); + } + else if (Obj_is_a(query, COMPILER)) { + compiler = (Compiler*)INCREF(query); + } + else { + THROW(ERR, "Invalid query type: %o", Obj_get_class_name(query)); + return; + } // Accumulate hits into the Collector. for (size_t i = 0, max = Vec_Get_Size(seg_readers); i < max; i++) { diff --git a/core/Lucy/Search/IndexSearcher.cfh b/core/Lucy/Search/IndexSearcher.cfh index 77fb4c921..1c791613d 100644 --- a/core/Lucy/Search/IndexSearcher.cfh +++ b/core/Lucy/Search/IndexSearcher.cfh @@ -59,10 +59,10 @@ public class Lucy::Search::IndexSearcher nickname IxSearcher Doc_Freq(IndexSearcher *self, String *field, Obj *term); public void - Collect(IndexSearcher *self, Query *query, Collector *collector); + Collect(IndexSearcher *self, Obj *query, Collector *collector); incremented TopDocs* - Top_Docs(IndexSearcher *self, Query *query, uint32_t num_wanted, + Top_Docs(IndexSearcher *self, Obj *query, uint32_t num_wanted, SortSpec *sort_spec = NULL); public incremented HitDoc* diff --git a/core/Lucy/Search/MatchAllQuery.c b/core/Lucy/Search/MatchAllQuery.c index 985b02c74..2210e9725 100644 --- a/core/Lucy/Search/MatchAllQuery.c +++ b/core/Lucy/Search/MatchAllQuery.c @@ -15,6 +15,7 @@ */ #define C_LUCY_MATCHALLQUERY +#define C_LUCY_MATCHALLCOMPILER #include "Lucy/Util/ToolSet.h" #include "Lucy/Search/MatchAllQuery.h" @@ -58,32 +59,54 @@ MatchAllQuery_To_String_IMP(MatchAllQuery *self) { Compiler* MatchAllQuery_Make_Compiler_IMP(MatchAllQuery *self, Searcher *searcher, float boost) { - return (Compiler*)MatchAllCompiler_new(self, searcher, boost); + UNUSED_VAR(self); + UNUSED_VAR(searcher); + return (Compiler*)MatchAllCompiler_new(boost); } /**********************************************************************/ MatchAllCompiler* -MatchAllCompiler_new(MatchAllQuery *parent, Searcher *searcher, - float boost) { +MatchAllCompiler_new(float boost) { MatchAllCompiler *self = (MatchAllCompiler*)Class_Make_Obj(MATCHALLCOMPILER); - return MatchAllCompiler_init(self, parent, searcher, boost); + return MatchAllCompiler_init(self, boost); +} + +MatchAllCompiler* +MatchAllCompiler_init(MatchAllCompiler *self, float boost) { + MatchAllCompiler_IVARS(self)->boost = boost; + return (MatchAllCompiler*)Compiler_init((Compiler*)self); +} + +bool +MatchAllCompiler_Equals_IMP(MatchAllCompiler *self, Obj *other) { + if ((MatchAllCompiler*)other == self) { return true; } + if (!Obj_is_a(other, MATCHALLCOMPILER)) { return false; } + MatchAllCompilerIVARS *const ivars = MatchAllCompiler_IVARS(self); + MatchAllCompilerIVARS *const ovars + = MatchAllCompiler_IVARS((MatchAllCompiler*)other); + if (ivars->boost != ovars->boost) { return false; } + return true; +} + +void +MatchAllCompiler_Serialize_IMP(MatchAllCompiler *self, OutStream *outstream) { + OutStream_Write_F32(outstream, MatchAllCompiler_IVARS(self)->boost); } MatchAllCompiler* -MatchAllCompiler_init(MatchAllCompiler *self, MatchAllQuery *parent, - Searcher *searcher, float boost) { - return (MatchAllCompiler*)Compiler_init((Compiler*)self, (Query*)parent, - searcher, NULL, boost); +MatchAllCompiler_Deserialize_IMP(MatchAllCompiler *self, InStream *instream) { + MatchAllCompiler_IVARS(self)->boost = InStream_Read_F32(instream); + return self; } Matcher* MatchAllCompiler_Make_Matcher_IMP(MatchAllCompiler *self, SegReader *reader, bool need_score) { - float weight = MatchAllCompiler_Get_Weight(self); + UNUSED_VAR(self); UNUSED_VAR(need_score); + float weight = MatchAllCompiler_IVARS(self)->boost; return (Matcher*)MatchAllMatcher_new(weight, SegReader_Doc_Max(reader)); } - diff --git a/core/Lucy/Search/MatchAllQuery.cfh b/core/Lucy/Search/MatchAllQuery.cfh index 99f620a9d..f412a0202 100644 --- a/core/Lucy/Search/MatchAllQuery.cfh +++ b/core/Lucy/Search/MatchAllQuery.cfh @@ -48,16 +48,26 @@ public class Lucy::Search::MatchAllQuery inherits Lucy::Search::Query { class Lucy::Search::MatchAllCompiler inherits Lucy::Search::Compiler { + float boost; + inert incremented MatchAllCompiler* - new(MatchAllQuery *parent, Searcher *searcher, float boost); + new(float boost); inert MatchAllCompiler* - init(MatchAllCompiler *self, MatchAllQuery *parent, - Searcher *searcher, float boost); + init(MatchAllCompiler *self, float boost); public incremented nullable Matcher* Make_Matcher(MatchAllCompiler *self, SegReader *reader, bool need_score); + + void + Serialize(MatchAllCompiler *self, OutStream *outstream); + + incremented MatchAllCompiler* + Deserialize(decremented MatchAllCompiler *self, InStream *instream); + + public bool + Equals(MatchAllCompiler *self, Obj *other); } diff --git a/core/Lucy/Search/NOTQuery.c b/core/Lucy/Search/NOTQuery.c index 3b84e4868..deca6792f 100644 --- a/core/Lucy/Search/NOTQuery.c +++ b/core/Lucy/Search/NOTQuery.c @@ -21,6 +21,8 @@ #include "Lucy/Search/NOTQuery.h" #include "Lucy/Index/DocVector.h" #include "Lucy/Index/SegReader.h" +#include "Lucy/Index/Similarity.h" +#include "Lucy/Plan/Schema.h" #include "Lucy/Search/MatchAllMatcher.h" #include "Lucy/Search/NOTMatcher.h" #include "Lucy/Search/Searcher.h" @@ -79,19 +81,29 @@ NOTQuery_Make_Compiler_IMP(NOTQuery *self, Searcher *searcher, float boost) { /**********************************************************************/ NOTCompiler* -NOTCompiler_new(NOTQuery *parent, Searcher *searcher, float boost) { +NOTCompiler_new(NOTQuery *query, Searcher *searcher, float boost) { NOTCompiler *self = (NOTCompiler*)Class_Make_Obj(NOTCOMPILER); - return NOTCompiler_init(self, parent, searcher, boost); + return NOTCompiler_init(self, query, searcher, boost); } NOTCompiler* -NOTCompiler_init(NOTCompiler *self, NOTQuery *parent, Searcher *searcher, +NOTCompiler_init(NOTCompiler *self, NOTQuery *query, Searcher *searcher, float boost) { - PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)parent, searcher, + PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)query, searcher, boost); return self; } +bool +NOTCompiler_Equals_IMP(NOTCompiler *self, Obj *other) { + if ((NOTCompiler*)other == self) { return true; } + if (!Obj_is_a(other, NOTCOMPILER)) { return false; } + NOTCompiler_Equals_t super_equals + = (NOTCompiler_Equals_t)SUPER_METHOD_PTR(NOTCOMPILER, + LUCY_NOTCompiler_Equals); + return super_equals(self, other); +} + float NOTCompiler_Sum_Of_Squared_Weights_IMP(NOTCompiler *self) { UNUSED_VAR(self); @@ -119,7 +131,7 @@ NOTCompiler_Make_Matcher_IMP(NOTCompiler *self, SegReader *reader, UNUSED_VAR(need_score); if (negated_matcher == NULL) { - float weight = NOTCompiler_Get_Weight(self); + float weight = ivars->boost; int32_t doc_max = SegReader_Doc_Max(reader); return (Matcher*)MatchAllMatcher_new(weight, doc_max); } diff --git a/core/Lucy/Search/NOTQuery.cfh b/core/Lucy/Search/NOTQuery.cfh index 9ae65ac4a..1aff3db4a 100644 --- a/core/Lucy/Search/NOTQuery.cfh +++ b/core/Lucy/Search/NOTQuery.cfh @@ -65,10 +65,10 @@ class Lucy::Search::NOTCompiler inherits Lucy::Search::PolyCompiler { inert incremented NOTCompiler* - new(NOTQuery *parent, Searcher *searcher, float boost); + new(NOTQuery *query, Searcher *searcher, float boost); inert NOTCompiler* - init(NOTCompiler *self, NOTQuery *parent, Searcher *searcher, + init(NOTCompiler *self, NOTQuery *query, Searcher *searcher, float boost); public incremented nullable Matcher* @@ -80,6 +80,9 @@ class Lucy::Search::NOTCompiler incremented Vector* Highlight_Spans(NOTCompiler *self, Searcher *searcher, DocVector *doc_vec, String *field); + + public bool + Equals(NOTCompiler *self, Obj *other); } diff --git a/core/Lucy/Search/NoMatchQuery.c b/core/Lucy/Search/NoMatchQuery.c index 6a1924821..e08388526 100644 --- a/core/Lucy/Search/NoMatchQuery.c +++ b/core/Lucy/Search/NoMatchQuery.c @@ -62,7 +62,10 @@ NoMatchQuery_To_String_IMP(NoMatchQuery *self) { Compiler* NoMatchQuery_Make_Compiler_IMP(NoMatchQuery *self, Searcher *searcher, float boost) { - return (Compiler*)NoMatchCompiler_new(self, searcher, boost); + UNUSED_VAR(self); + UNUSED_VAR(searcher); + UNUSED_VAR(boost); + return (Compiler*)NoMatchCompiler_new(); } void @@ -114,18 +117,35 @@ NoMatchQuery_Deserialize_IMP(NoMatchQuery *self, InStream *instream) { /**********************************************************************/ NoMatchCompiler* -NoMatchCompiler_new(NoMatchQuery *parent, Searcher *searcher, - float boost) { +NoMatchCompiler_new() { NoMatchCompiler *self = (NoMatchCompiler*)Class_Make_Obj(NOMATCHCOMPILER); - return NoMatchCompiler_init(self, parent, searcher, boost); + return NoMatchCompiler_init(self); +} + +bool +NoMatchCompiler_Equals_IMP(NoMatchCompiler *self, Obj *other) { + if ((NoMatchCompiler*)other == self) { return true; } + if (!Obj_is_a(other, NOMATCHCOMPILER)) { return false; } + return true; +} + +// Perl's Storable doesn't cope with empty strings. +void +NoMatchCompiler_Serialize_IMP(NoMatchCompiler *self, OutStream *outstream) { + UNUSED_VAR(self); + OutStream_Write_I8(outstream, 'x'); +} + +NoMatchCompiler* +NoMatchCompiler_Deserialize_IMP(NoMatchCompiler *self, InStream *instream) { + InStream_Read_I8(instream); + return self; } NoMatchCompiler* -NoMatchCompiler_init(NoMatchCompiler *self, NoMatchQuery *parent, - Searcher *searcher, float boost) { - return (NoMatchCompiler*)Compiler_init((Compiler*)self, (Query*)parent, - searcher, NULL, boost); +NoMatchCompiler_init(NoMatchCompiler *self) { + return (NoMatchCompiler*)Compiler_init((Compiler*)self); } Matcher* diff --git a/core/Lucy/Search/NoMatchQuery.cfh b/core/Lucy/Search/NoMatchQuery.cfh index 53aff1fe4..2e6e03c99 100644 --- a/core/Lucy/Search/NoMatchQuery.cfh +++ b/core/Lucy/Search/NoMatchQuery.cfh @@ -69,14 +69,22 @@ class Lucy::Search::NoMatchCompiler inherits Lucy::Search::Compiler { inert incremented NoMatchCompiler* - new(NoMatchQuery *parent, Searcher *searcher, float boost); + new(); inert NoMatchCompiler* - init(NoMatchCompiler *self, NoMatchQuery *parent, - Searcher *searcher, float boost); + init(NoMatchCompiler *self); public incremented nullable Matcher* Make_Matcher(NoMatchCompiler *self, SegReader *reader, bool need_score); + + void + Serialize(NoMatchCompiler *self, OutStream *outstream); + + incremented NoMatchCompiler* + Deserialize(decremented NoMatchCompiler *self, InStream *instream); + + public bool + Equals(NoMatchCompiler *self, Obj *other); } diff --git a/core/Lucy/Search/ORQuery.c b/core/Lucy/Search/ORQuery.c index 7bcf39646..603aaaba6 100644 --- a/core/Lucy/Search/ORQuery.c +++ b/core/Lucy/Search/ORQuery.c @@ -23,6 +23,7 @@ #include "Clownfish/CharBuf.h" #include "Lucy/Index/SegReader.h" #include "Lucy/Index/Similarity.h" +#include "Lucy/Plan/Schema.h" #include "Lucy/Search/ORMatcher.h" #include "Lucy/Search/Searcher.h" #include "Lucy/Store/InStream.h" @@ -82,19 +83,28 @@ ORQuery_To_String_IMP(ORQuery *self) { /**********************************************************************/ ORCompiler* -ORCompiler_new(ORQuery *parent, Searcher *searcher, float boost) { +ORCompiler_new(ORQuery *query, Searcher *searcher, float boost) { ORCompiler *self = (ORCompiler*)Class_Make_Obj(ORCOMPILER); - return ORCompiler_init(self, parent, searcher, boost); + return ORCompiler_init(self, query, searcher, boost); } ORCompiler* -ORCompiler_init(ORCompiler *self, ORQuery *parent, Searcher *searcher, +ORCompiler_init(ORCompiler *self, ORQuery *query, Searcher *searcher, float boost) { - PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)parent, searcher, - boost); + PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)query, searcher, boost); return self; } +bool +ORCompiler_Equals_IMP(ORCompiler *self, Obj *other) { + if ((ORCompiler*)other == self) { return true; } + if (!Obj_is_a(other, ORCOMPILER)) { return false; } + ORCompiler_Equals_t super_equals + = (ORCompiler_Equals_t)SUPER_METHOD_PTR(ORCOMPILER, + LUCY_ORCompiler_Equals); + return super_equals(self, other); +} + Matcher* ORCompiler_Make_Matcher_IMP(ORCompiler *self, SegReader *reader, bool need_score) { @@ -127,10 +137,11 @@ ORCompiler_Make_Matcher_IMP(ORCompiler *self, SegReader *reader, return NULL; } else { - Similarity *sim = ORCompiler_Get_Similarity(self); - Matcher *retval = need_score - ? (Matcher*)ORScorer_new(submatchers, sim) - : (Matcher*)ORMatcher_new(submatchers); + Schema *schema = SegReader_Get_Schema(reader); + Similarity *sim = Schema_Get_Similarity(schema); + Matcher *retval = need_score + ? (Matcher*)ORScorer_new(submatchers, sim) + : (Matcher*)ORMatcher_new(submatchers); DECREF(submatchers); return retval; } diff --git a/core/Lucy/Search/ORQuery.cfh b/core/Lucy/Search/ORQuery.cfh index d9c12edb0..3eab674e3 100644 --- a/core/Lucy/Search/ORQuery.cfh +++ b/core/Lucy/Search/ORQuery.cfh @@ -54,14 +54,17 @@ class Lucy::Search::ORCompiler inherits Lucy::Search::PolyCompiler { inert incremented ORCompiler* - new(ORQuery *parent, Searcher *searcher, float boost); + new(ORQuery *query, Searcher *searcher, float boost); inert ORCompiler* - init(ORCompiler *self, ORQuery *parent, Searcher *searcher, + init(ORCompiler *self, ORQuery *query, Searcher *searcher, float boost); public incremented nullable Matcher* Make_Matcher(ORCompiler *self, SegReader *reader, bool need_score); + + public bool + Equals(ORCompiler *self, Obj *other); } diff --git a/core/Lucy/Search/PhraseMatcher.c b/core/Lucy/Search/PhraseMatcher.c index 740ed507f..206ca305e 100644 --- a/core/Lucy/Search/PhraseMatcher.c +++ b/core/Lucy/Search/PhraseMatcher.c @@ -26,15 +26,15 @@ #include "Lucy/Search/Compiler.h" PhraseMatcher* -PhraseMatcher_new(Similarity *sim, Vector *plists, Compiler *compiler) { +PhraseMatcher_new(Similarity *sim, Vector *plists, float weight) { PhraseMatcher *self = (PhraseMatcher*)Class_Make_Obj(PHRASEMATCHER); - return PhraseMatcher_init(self, sim, plists, compiler); + return PhraseMatcher_init(self, sim, plists, weight); } PhraseMatcher* PhraseMatcher_init(PhraseMatcher *self, Similarity *similarity, Vector *plists, - Compiler *compiler) { + float weight) { Matcher_init((Matcher*)self); PhraseMatcherIVARS *const ivars = PhraseMatcher_IVARS(self); @@ -59,9 +59,8 @@ PhraseMatcher_init(PhraseMatcher *self, Similarity *similarity, Vector *plists, } // Assign. - ivars->sim = (Similarity*)INCREF(similarity); - ivars->compiler = (Compiler*)INCREF(compiler); - ivars->weight = Compiler_Get_Weight(compiler); + ivars->sim = (Similarity*)INCREF(similarity); + ivars->weight = weight; return self; } @@ -77,7 +76,6 @@ PhraseMatcher_Destroy_IMP(PhraseMatcher *self) { } DECREF(ivars->sim); DECREF(ivars->anchor_set); - DECREF(ivars->compiler); SUPER_DESTROY(self, PHRASEMATCHER); } diff --git a/core/Lucy/Search/PhraseMatcher.cfh b/core/Lucy/Search/PhraseMatcher.cfh index e522a6017..d1f4562aa 100644 --- a/core/Lucy/Search/PhraseMatcher.cfh +++ b/core/Lucy/Search/PhraseMatcher.cfh @@ -28,17 +28,16 @@ class Lucy::Search::PhraseMatcher inherits Lucy::Search::Matcher { ByteBuf *anchor_set; float phrase_freq; float phrase_boost; - Compiler *compiler; float weight; bool first_time; bool more; inert incremented PhraseMatcher* - new(Similarity *similarity, Vector *posting_lists, Compiler *compiler); + new(Similarity *similarity, Vector *posting_lists, float weight); inert PhraseMatcher* init(PhraseMatcher *self, Similarity *similarity, Vector *posting_lists, - Compiler *compiler); + float weight); public void Destroy(PhraseMatcher *self); diff --git a/core/Lucy/Search/PhraseQuery.c b/core/Lucy/Search/PhraseQuery.c index 1c5363854..f7a669d85 100644 --- a/core/Lucy/Search/PhraseQuery.c +++ b/core/Lucy/Search/PhraseQuery.c @@ -191,48 +191,57 @@ PhraseQuery_Get_Terms_IMP(PhraseQuery *self) { /*********************************************************************/ PhraseCompiler* -PhraseCompiler_new(PhraseQuery *parent, Searcher *searcher, float boost) { +PhraseCompiler_new(PhraseQuery *query, Searcher *searcher, float boost) { PhraseCompiler *self = (PhraseCompiler*)Class_Make_Obj(PHRASECOMPILER); - return PhraseCompiler_init(self, parent, searcher, boost); + return PhraseCompiler_init(self, query, searcher, boost); } PhraseCompiler* -PhraseCompiler_init(PhraseCompiler *self, PhraseQuery *parent, +PhraseCompiler_init(PhraseCompiler *self, PhraseQuery *query, Searcher *searcher, float boost) { PhraseCompilerIVARS *const ivars = PhraseCompiler_IVARS(self); - PhraseQueryIVARS *const parent_ivars = PhraseQuery_IVARS(parent); + PhraseQueryIVARS *const query_ivars = PhraseQuery_IVARS(query); + String *field = query_ivars->field; + Vector *terms = query_ivars->terms; Schema *schema = Searcher_Get_Schema(searcher); - Similarity *sim = Schema_Fetch_Sim(schema, parent_ivars->field); - Vector *terms = parent_ivars->terms; + Similarity *sim = Schema_Fetch_Sim(schema, field); // Try harder to find a Similarity if necessary. if (!sim) { sim = Schema_Get_Similarity(schema); } // Init. - Compiler_init((Compiler*)self, (Query*)parent, searcher, sim, boost); + Compiler_init((Compiler*)self); + ivars->field = (String*)INCREF(field); + ivars->terms = (Vector*)INCREF(terms); // Store IDF for the phrase. ivars->idf = 0; for (size_t i = 0, max = Vec_Get_Size(terms); i < max; i++) { Obj *term = Vec_Fetch(terms, i); int32_t doc_max = Searcher_Doc_Max(searcher); - uint32_t doc_freq = Searcher_Doc_Freq(searcher, parent_ivars->field, term); + uint32_t doc_freq = Searcher_Doc_Freq(searcher, field, term); ivars->idf += Sim_IDF(sim, (int32_t)doc_freq, doc_max); } // Calculate raw weight. - ivars->raw_weight = ivars->idf * ivars->boost; + ivars->raw_weight = ivars->idf * boost; return self; } +void +PhraseCompiler_Destroy_IMP(PhraseCompiler *self) { + PhraseCompilerIVARS *const ivars = PhraseCompiler_IVARS(self); + DECREF(ivars->field); + DECREF(ivars->terms); + SUPER_DESTROY(self, PHRASECOMPILER); +} + void PhraseCompiler_Serialize_IMP(PhraseCompiler *self, OutStream *outstream) { PhraseCompilerIVARS *const ivars = PhraseCompiler_IVARS(self); - PhraseCompiler_Serialize_t super_serialize - = (PhraseCompiler_Serialize_t)SUPER_METHOD_PTR(PHRASECOMPILER, - LUCY_PhraseCompiler_Serialize); - super_serialize(self, outstream); + Freezer_serialize_string(ivars->field, outstream); + Freezer_serialize_varray(ivars->terms, outstream); OutStream_Write_F32(outstream, ivars->idf); OutStream_Write_F32(outstream, ivars->raw_weight); OutStream_Write_F32(outstream, ivars->query_norm_factor); @@ -241,27 +250,30 @@ PhraseCompiler_Serialize_IMP(PhraseCompiler *self, OutStream *outstream) { PhraseCompiler* PhraseCompiler_Deserialize_IMP(PhraseCompiler *self, InStream *instream) { - PhraseCompiler_Deserialize_t super_deserialize - = SUPER_METHOD_PTR(PHRASECOMPILER, LUCY_PhraseCompiler_Deserialize); - self = super_deserialize(self, instream); PhraseCompilerIVARS *const ivars = PhraseCompiler_IVARS(self); + + ivars->field = Freezer_read_string(instream); + ivars->terms = Freezer_read_varray(instream); ivars->idf = InStream_Read_F32(instream); ivars->raw_weight = InStream_Read_F32(instream); ivars->query_norm_factor = InStream_Read_F32(instream); ivars->normalized_weight = InStream_Read_F32(instream); + + for (size_t i = 0, max = Vec_Get_Size(ivars->terms); i < max; i++) { + CERTIFY(Vec_Fetch(ivars->terms, i), OBJ); + } + return self; } bool PhraseCompiler_Equals_IMP(PhraseCompiler *self, Obj *other) { if (!Obj_is_a(other, PHRASECOMPILER)) { return false; } - PhraseCompiler_Equals_t super_equals - = (PhraseCompiler_Equals_t)SUPER_METHOD_PTR(PHRASECOMPILER, - LUCY_PhraseCompiler_Equals); - if (!super_equals(self, other)) { return false; } PhraseCompilerIVARS *const ivars = PhraseCompiler_IVARS(self); PhraseCompilerIVARS *const ovars = PhraseCompiler_IVARS((PhraseCompiler*)other); + if (!Str_Equals(ivars->field, (Obj*)ovars->field)) { return false; } + if (!Vec_Equals(ivars->terms, (Obj*)ovars->terms)) { return false; } if (ivars->idf != ovars->idf) { return false; } if (ivars->raw_weight != ovars->raw_weight) { return false; } if (ivars->query_norm_factor != ovars->query_norm_factor) { return false; } @@ -269,11 +281,6 @@ PhraseCompiler_Equals_IMP(PhraseCompiler *self, Obj *other) { return true; } -float -PhraseCompiler_Get_Weight_IMP(PhraseCompiler *self) { - return PhraseCompiler_IVARS(self)->normalized_weight; -} - float PhraseCompiler_Sum_Of_Squared_Weights_IMP(PhraseCompiler *self) { PhraseCompilerIVARS *const ivars = PhraseCompiler_IVARS(self); @@ -292,35 +299,36 @@ PhraseCompiler_Make_Matcher_IMP(PhraseCompiler *self, SegReader *reader, bool need_score) { UNUSED_VAR(need_score); PhraseCompilerIVARS *const ivars = PhraseCompiler_IVARS(self); - PhraseQueryIVARS *const parent_ivars - = PhraseQuery_IVARS((PhraseQuery*)ivars->parent); - Vector *const terms = parent_ivars->terms; + Vector *const terms = ivars->terms; size_t num_terms = Vec_Get_Size(terms); // Bail if there are no terms. if (!num_terms) { return NULL; } + // Bail if there's no PostingListReader for this segment. + PostingListReader *const plist_reader + = (PostingListReader*)SegReader_Fetch( + reader, Class_Get_Name(POSTINGLISTREADER)); + if (!plist_reader) { return NULL; } + + Schema *schema = PListReader_Get_Schema(plist_reader); + Similarity *sim = Schema_Fetch_Sim(schema, ivars->field); + if (!sim) { sim = Schema_Get_Similarity(schema); } + // Bail unless field is valid and posting type supports positions. - Similarity *sim = PhraseCompiler_Get_Similarity(self); - Posting *posting = Sim_Make_Posting(sim); + Posting *posting = Sim_Make_Posting(sim); if (posting == NULL || !Obj_is_a((Obj*)posting, SCOREPOSTING)) { DECREF(posting); return NULL; } DECREF(posting); - // Bail if there's no PostingListReader for this segment. - PostingListReader *const plist_reader - = (PostingListReader*)SegReader_Fetch( - reader, Class_Get_Name(POSTINGLISTREADER)); - if (!plist_reader) { return NULL; } - // Look up each term. Vector *plists = Vec_new(num_terms); for (size_t i = 0; i < num_terms; i++) { Obj *term = Vec_Fetch(terms, i); PostingList *plist - = PListReader_Posting_List(plist_reader, parent_ivars->field, term); + = PListReader_Posting_List(plist_reader, ivars->field, term); // Bail if any one of the terms isn't in the index. if (!plist || !PList_Get_Doc_Freq(plist)) { @@ -331,8 +339,8 @@ PhraseCompiler_Make_Matcher_IMP(PhraseCompiler *self, SegReader *reader, Vec_Push(plists, (Obj*)plist); } - Matcher *retval - = (Matcher*)PhraseMatcher_new(sim, plists, (Compiler*)self); + float weight = ivars->normalized_weight; + Matcher *retval = (Matcher*)PhraseMatcher_new(sim, plists, weight); DECREF(plists); return retval; } @@ -341,16 +349,14 @@ Vector* PhraseCompiler_Highlight_Spans_IMP(PhraseCompiler *self, Searcher *searcher, DocVector *doc_vec, String *field) { PhraseCompilerIVARS *const ivars = PhraseCompiler_IVARS(self); - PhraseQueryIVARS *const parent_ivars - = PhraseQuery_IVARS((PhraseQuery*)ivars->parent); - Vector *const terms = parent_ivars->terms; + Vector *const terms = ivars->terms; Vector *const spans = Vec_new(0); const uint32_t num_terms = (uint32_t)Vec_Get_Size(terms); UNUSED_VAR(searcher); // Bail if no terms or field doesn't match. if (!num_terms) { return spans; } - if (!Str_Equals(field, (Obj*)parent_ivars->field)) { return spans; } + if (!Str_Equals(field, (Obj*)ivars->field)) { return spans; } Vector *term_vectors = Vec_new(num_terms); BitVector *posit_vec = BitVec_new(0); @@ -403,7 +409,7 @@ PhraseCompiler_Highlight_Spans_IMP(PhraseCompiler *self, Searcher *searcher, I32Array *valid_posits = BitVec_To_Array(posit_vec); size_t num_valid_posits = I32Arr_Get_Size(valid_posits); size_t j = 0; - float weight = PhraseCompiler_Get_Weight(self); + float weight = ivars->normalized_weight; size_t i = 0; // Add only those starts/ends that belong to a valid position. diff --git a/core/Lucy/Search/PhraseQuery.cfh b/core/Lucy/Search/PhraseQuery.cfh index df95e936d..a49721fd4 100644 --- a/core/Lucy/Search/PhraseQuery.cfh +++ b/core/Lucy/Search/PhraseQuery.cfh @@ -81,24 +81,23 @@ public class Lucy::Search::PhraseQuery inherits Lucy::Search::Query { class Lucy::Search::PhraseCompiler inherits Lucy::Search::Compiler { - float idf; - float raw_weight; - float query_norm_factor; - float normalized_weight; + String *field; + Vector *terms; + float idf; + float raw_weight; + float query_norm_factor; + float normalized_weight; inert incremented PhraseCompiler* - new(PhraseQuery *parent, Searcher *searcher, float boost); + new(PhraseQuery *query, Searcher *searcher, float boost); inert PhraseCompiler* - init(PhraseCompiler *self, PhraseQuery *parent, Searcher *searcher, + init(PhraseCompiler *self, PhraseQuery *query, Searcher *searcher, float boost); public incremented nullable Matcher* Make_Matcher(PhraseCompiler *self, SegReader *reader, bool need_score); - public float - Get_Weight(PhraseCompiler *self); - public float Sum_Of_Squared_Weights(PhraseCompiler *self); @@ -117,6 +116,9 @@ class Lucy::Search::PhraseCompiler incremented PhraseCompiler* Deserialize(decremented PhraseCompiler *self, InStream *instream); + + public void + Destroy(PhraseCompiler *self); } diff --git a/core/Lucy/Search/PolyQuery.c b/core/Lucy/Search/PolyQuery.c index 13de25eb9..4be303884 100644 --- a/core/Lucy/Search/PolyQuery.c +++ b/core/Lucy/Search/PolyQuery.c @@ -130,18 +130,19 @@ PolyQuery_Equals_IMP(PolyQuery *self, Obj *other) { PolyCompiler* -PolyCompiler_init(PolyCompiler *self, PolyQuery *parent, +PolyCompiler_init(PolyCompiler *self, PolyQuery *query, Searcher *searcher, float boost) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); - PolyQueryIVARS *const parent_ivars = PolyQuery_IVARS(parent); - const size_t num_kids = Vec_Get_Size(parent_ivars->children); + PolyQueryIVARS *const query_ivars = PolyQuery_IVARS(query); + const size_t num_kids = Vec_Get_Size(query_ivars->children); - Compiler_init((Compiler*)self, (Query*)parent, searcher, NULL, boost); + Compiler_init((Compiler*)self); ivars->children = Vec_new(num_kids); + ivars->boost = boost; // Iterate over the children, creating a Compiler for each one. for (size_t i = 0; i < num_kids; i++) { - Query *child_query = (Query*)Vec_Fetch(parent_ivars->children, i); + Query *child_query = (Query*)Vec_Fetch(query_ivars->children, i); float sub_boost = boost * Query_Get_Boost(child_query); Compiler *child_compiler = Query_Make_Compiler(child_query, searcher, sub_boost); @@ -162,7 +163,7 @@ float PolyCompiler_Sum_Of_Squared_Weights_IMP(PolyCompiler *self) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); float sum = 0; - float my_boost = PolyCompiler_Get_Boost(self); + float my_boost = ivars->boost; for (size_t i = 0, max = Vec_Get_Size(ivars->children); i < max; i++) { Compiler *child = (Compiler*)Vec_Fetch(ivars->children, i); @@ -201,24 +202,35 @@ PolyCompiler_Highlight_Spans_IMP(PolyCompiler *self, Searcher *searcher, return spans; } +bool +PolyCompiler_Equals_IMP(PolyCompiler *self, Obj *other) { + if ((PolyCompiler*)other == self) { return true; } + if (!Obj_is_a(other, POLYCOMPILER)) { return false; } + PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); + PolyCompilerIVARS *const ovars = PolyCompiler_IVARS((PolyCompiler*)other); + if (ivars->boost != ovars->boost) { return false; } + if (!Vec_Equals(ovars->children, (Obj*)ivars->children)) { return false; } + return true; +} + void PolyCompiler_Serialize_IMP(PolyCompiler *self, OutStream *outstream) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); - Freezer_serialize_string(PolyCompiler_get_class_name(self), outstream); Freezer_serialize_varray(ivars->children, outstream); - PolyCompiler_Serialize_t super_serialize - = SUPER_METHOD_PTR(POLYCOMPILER, LUCY_PolyCompiler_Serialize); - super_serialize(self, outstream); + OutStream_Write_F32(outstream, ivars->boost); } PolyCompiler* PolyCompiler_Deserialize_IMP(PolyCompiler *self, InStream *instream) { PolyCompilerIVARS *const ivars = PolyCompiler_IVARS(self); - String *class_name = Freezer_read_string(instream); - DECREF(class_name); // TODO Don't serialize class name. + ivars->children = Freezer_read_varray(instream); - PolyCompiler_Deserialize_t super_deserialize - = SUPER_METHOD_PTR(POLYCOMPILER, LUCY_PolyCompiler_Deserialize); - return super_deserialize(self, instream); + ivars->boost = InStream_Read_F32(instream); + + for (size_t i = 0, max = Vec_Get_Size(ivars->children); i < max; i++) { + CERTIFY(Vec_Fetch(ivars->children, i), COMPILER); + } + + return self; } diff --git a/core/Lucy/Search/PolyQuery.cfh b/core/Lucy/Search/PolyQuery.cfh index 69d026292..bbd12bd34 100644 --- a/core/Lucy/Search/PolyQuery.cfh +++ b/core/Lucy/Search/PolyQuery.cfh @@ -70,12 +70,13 @@ public abstract class Lucy::Search::PolyQuery inherits Lucy::Search::Query { abstract class Lucy::Search::PolyCompiler inherits Lucy::Search::Compiler { Vector *children; + float boost; /** Initialize the Compiler, creating a Compiler child for each child * Query. Normalization is left to the subclass. */ inert PolyCompiler* - init(PolyCompiler *self, PolyQuery *parent, Searcher *searcher, + init(PolyCompiler *self, PolyQuery *query, Searcher *searcher, float boost); public float @@ -88,6 +89,9 @@ abstract class Lucy::Search::PolyCompiler inherits Lucy::Search::Compiler { Highlight_Spans(PolyCompiler *self, Searcher *searcher, DocVector *doc_vec, String *field); + public bool + Equals(PolyCompiler *self, Obj *other); + public void Destroy(PolyCompiler *self); diff --git a/core/Lucy/Search/PolySearcher.c b/core/Lucy/Search/PolySearcher.c index 8ae818b32..8bca04807 100644 --- a/core/Lucy/Search/PolySearcher.c +++ b/core/Lucy/Search/PolySearcher.c @@ -136,8 +136,8 @@ S_modify_doc_ids(Vector *match_docs, int32_t base) { } TopDocs* -PolySearcher_Top_Docs_IMP(PolySearcher *self, Query *query, - uint32_t num_wanted, SortSpec *sort_spec) { +PolySearcher_Top_Docs_IMP(PolySearcher *self, Obj *query, uint32_t num_wanted, + SortSpec *sort_spec) { PolySearcherIVARS *const ivars = PolySearcher_IVARS(self); Schema *schema = PolySearcher_Get_Schema(self); Vector *searchers = ivars->searchers; @@ -146,14 +146,23 @@ PolySearcher_Top_Docs_IMP(PolySearcher *self, Query *query, ? HitQ_new(schema, sort_spec, num_wanted) : HitQ_new(NULL, NULL, num_wanted); uint32_t total_hits = 0; - Compiler *compiler = Query_is_a(query, COMPILER) - ? ((Compiler*)INCREF(query)) - : Query_Make_Root_Compiler(query, (Searcher*)self); + Compiler *compiler; + + if (Obj_is_a(query, QUERY)) { + compiler = Query_Make_Root_Compiler((Query*)query, (Searcher*)self); + } + else if (Obj_is_a(query, COMPILER)) { + compiler = (Compiler*)INCREF(query); + } + else { + THROW(ERR, "Invalid query type: %o", Obj_get_class_name(query)); + UNREACHABLE_RETURN(TopDocs*); + } for (size_t i = 0, max = Vec_Get_Size(searchers); i < max; i++) { Searcher *searcher = (Searcher*)Vec_Fetch(searchers, i); int32_t base = I32Arr_Get(starts, i); - TopDocs *top_docs = Searcher_Top_Docs(searcher, (Query*)compiler, + TopDocs *top_docs = Searcher_Top_Docs(searcher, (Obj*)compiler, num_wanted, sort_spec); Vector *sub_match_docs = TopDocs_Get_Match_Docs(top_docs); @@ -179,7 +188,7 @@ PolySearcher_Top_Docs_IMP(PolySearcher *self, Query *query, void -PolySearcher_Collect_IMP(PolySearcher *self, Query *query, +PolySearcher_Collect_IMP(PolySearcher *self, Obj *query, Collector *collector) { PolySearcherIVARS *const ivars = PolySearcher_IVARS(self); Vector *const searchers = ivars->searchers; diff --git a/core/Lucy/Search/PolySearcher.cfh b/core/Lucy/Search/PolySearcher.cfh index ad7065e1e..9fb421124 100644 --- a/core/Lucy/Search/PolySearcher.cfh +++ b/core/Lucy/Search/PolySearcher.cfh @@ -60,10 +60,10 @@ public class Lucy::Search::PolySearcher Doc_Freq(PolySearcher *self, String *field, Obj *term); public void - Collect(PolySearcher *self, Query *query, Collector *collector); + Collect(PolySearcher *self, Obj *query, Collector *collector); incremented TopDocs* - Top_Docs(PolySearcher *self, Query *query, uint32_t num_wanted, + Top_Docs(PolySearcher *self, Obj *query, uint32_t num_wanted, SortSpec *sort_spec = NULL); public incremented HitDoc* diff --git a/core/Lucy/Search/Query.c b/core/Lucy/Search/Query.c index 75b1258ab..656c5850e 100644 --- a/core/Lucy/Search/Query.c +++ b/core/Lucy/Search/Query.c @@ -18,6 +18,8 @@ #include "Lucy/Util/ToolSet.h" #include "Lucy/Search/Query.h" +#include "Lucy/Index/Similarity.h" +#include "Lucy/Plan/Schema.h" #include "Lucy/Search/Compiler.h" #include "Lucy/Search/Searcher.h" #include "Lucy/Store/InStream.h" @@ -35,7 +37,11 @@ Compiler* Query_Make_Root_Compiler_IMP(Query *self, Searcher *searcher) { Compiler *compiler = Query_Make_Compiler(self, searcher, Query_Get_Boost(self)); - Compiler_Normalize(compiler); + + Schema *schema = Searcher_Get_Schema(searcher); + Similarity *sim = Schema_Get_Similarity(schema); + Compiler_Normalize(compiler, sim); + return compiler; } diff --git a/core/Lucy/Search/RangeQuery.c b/core/Lucy/Search/RangeQuery.c index 4b61686de..7eb8f7b0a 100644 --- a/core/Lucy/Search/RangeQuery.c +++ b/core/Lucy/Search/RangeQuery.c @@ -36,11 +36,11 @@ // Determine the lowest ordinal that should match. static int32_t -S_find_lower_bound(RangeCompiler *self, SortCache *sort_cache); +S_find_lower_bound(RangeQueryIVARS *query_ivars, SortCache *sort_cache); // Determine the highest ordinal that should match. static int32_t -S_find_upper_bound(RangeCompiler *self, SortCache *sort_cache); +S_find_upper_bound(RangeQueryIVARS *query_ivars, SortCache *sort_cache); RangeQuery* RangeQuery_new(String *field, Obj *lower_term, Obj *upper_term, @@ -215,30 +215,66 @@ RangeQuery_Load_IMP(RangeQuery *self, Obj *dump) { Compiler* RangeQuery_Make_Compiler_IMP(RangeQuery *self, Searcher *searcher, float boost) { - return (Compiler*)RangeCompiler_new(self, searcher, boost); + UNUSED_VAR(searcher); + return (Compiler*)RangeCompiler_new(self, boost); } /**********************************************************************/ RangeCompiler* -RangeCompiler_new(RangeQuery *parent, Searcher *searcher, float boost) { +RangeCompiler_new(RangeQuery *query, float boost) { RangeCompiler *self = (RangeCompiler*)Class_Make_Obj(RANGECOMPILER); - return RangeCompiler_init(self, parent, searcher, boost); + return RangeCompiler_init(self, query, boost); } RangeCompiler* -RangeCompiler_init(RangeCompiler *self, RangeQuery *parent, - Searcher *searcher, float boost) { - return (RangeCompiler*)Compiler_init((Compiler*)self, (Query*)parent, - searcher, NULL, boost); +RangeCompiler_init(RangeCompiler *self, RangeQuery *query, float boost) { + RangeCompilerIVARS *const ivars = RangeCompiler_IVARS(self); + ivars->query = (RangeQuery*)INCREF(query); + ivars->boost = boost; + return (RangeCompiler*)Compiler_init((Compiler*)self); +} + +void +RangeCompiler_Destroy_IMP(RangeCompiler *self) { + DECREF(RangeCompiler_IVARS(self)->query); + SUPER_DESTROY(self, RANGECOMPILER); +} + +bool +RangeCompiler_Equals_IMP(RangeCompiler *self, Obj *other) { + if ((RangeCompiler*)other == self) { return true; } + if (!Obj_is_a(other, RANGECOMPILER)) { return false; } + RangeCompilerIVARS *const ivars = RangeCompiler_IVARS(self); + RangeCompilerIVARS *const ovars + = RangeCompiler_IVARS((RangeCompiler*)other); + if (ivars->boost != ovars->boost) { return false; } + if (!RangeQuery_Equals(ivars->query, (Obj*)ovars->query)) { return false; } + return true; +} + +void +RangeCompiler_Serialize_IMP(RangeCompiler *self, OutStream *outstream) { + RangeCompilerIVARS *const ivars = RangeCompiler_IVARS(self); + FREEZE(ivars->query, outstream); + OutStream_Write_F32(outstream, ivars->boost); +} + +RangeCompiler* +RangeCompiler_Deserialize_IMP(RangeCompiler *self, InStream *instream) { + RangeCompilerIVARS *const ivars = RangeCompiler_IVARS(self); + ivars->query = (RangeQuery*)CERTIFY(THAW(instream), RANGEQUERY); + ivars->boost = InStream_Read_F32(instream); + return self; } Matcher* RangeCompiler_Make_Matcher_IMP(RangeCompiler *self, SegReader *reader, bool need_score) { - RangeQuery *parent = (RangeQuery*)RangeCompiler_IVARS(self)->parent; - String *field = RangeQuery_IVARS(parent)->field; + RangeQuery *query = RangeCompiler_IVARS(self)->query; + RangeQueryIVARS *const query_ivars = RangeQuery_IVARS(query); + String *field = query_ivars->field; SortReader *sort_reader = (SortReader*)SegReader_Fetch(reader, Class_Get_Name(SORTREADER)); SortCache *sort_cache = sort_reader @@ -250,8 +286,8 @@ RangeCompiler_Make_Matcher_IMP(RangeCompiler *self, SegReader *reader, return NULL; } else { - int32_t lower = S_find_lower_bound(self, sort_cache); - int32_t upper = S_find_upper_bound(self, sort_cache); + int32_t lower = S_find_lower_bound(query_ivars, sort_cache); + int32_t upper = S_find_upper_bound(query_ivars, sort_cache); int32_t max_ord = SortCache_Get_Cardinality(sort_cache) + 1; if (lower > max_ord || upper < 0) { return NULL; @@ -265,9 +301,8 @@ RangeCompiler_Make_Matcher_IMP(RangeCompiler *self, SegReader *reader, } static int32_t -S_find_lower_bound(RangeCompiler *self, SortCache *sort_cache) { - RangeQuery *parent = (RangeQuery*)RangeCompiler_IVARS(self)->parent; - Obj *lower_term = RangeQuery_IVARS(parent)->lower_term; +S_find_lower_bound(RangeQueryIVARS *query_ivars, SortCache *sort_cache) { + Obj *lower_term = query_ivars->lower_term; int32_t lower_bound = 0; if (lower_term) { @@ -283,7 +318,7 @@ S_find_lower_bound(RangeCompiler *self, SortCache *sort_cache) { : Obj_Equals(lower_term, low_found); lower_bound = low_ord; - if (!exact_match || !RangeQuery_IVARS(parent)->include_lower) { + if (!exact_match || !query_ivars->include_lower) { lower_bound++; } DECREF(low_found); @@ -294,9 +329,8 @@ S_find_lower_bound(RangeCompiler *self, SortCache *sort_cache) { } static int32_t -S_find_upper_bound(RangeCompiler *self, SortCache *sort_cache) { - RangeQuery *parent = (RangeQuery*)RangeCompiler_IVARS(self)->parent; - Obj *upper_term = RangeQuery_IVARS(parent)->upper_term; +S_find_upper_bound(RangeQueryIVARS *query_ivars, SortCache *sort_cache) { + Obj *upper_term = query_ivars->upper_term; int32_t retval = INT32_MAX; if (upper_term) { @@ -312,7 +346,7 @@ S_find_upper_bound(RangeCompiler *self, SortCache *sort_cache) { : Obj_Equals(upper_term, (Obj*)hi_found); retval = hi_ord; - if (exact_match && !RangeQuery_IVARS(parent)->include_upper) { + if (exact_match && !query_ivars->include_upper) { retval--; } DECREF(hi_found); diff --git a/core/Lucy/Search/RangeQuery.cfh b/core/Lucy/Search/RangeQuery.cfh index ea8a1fdcf..06b837751 100644 --- a/core/Lucy/Search/RangeQuery.cfh +++ b/core/Lucy/Search/RangeQuery.cfh @@ -84,15 +84,29 @@ public class Lucy::Search::RangeQuery inherits Lucy::Search::Query { class Lucy::Search::RangeCompiler inherits Lucy::Search::Compiler { + RangeQuery *query; + float boost; + inert incremented RangeCompiler* - new(RangeQuery *parent, Searcher *searcher, float boost); + new(RangeQuery *query, float boost); inert RangeCompiler* - init(RangeCompiler *self, RangeQuery *parent, Searcher *searcher, - float boost); + init(RangeCompiler *self, RangeQuery *query, float boost); public incremented nullable Matcher* Make_Matcher(RangeCompiler *self, SegReader *reader, bool need_score); + + public bool + Equals(RangeCompiler *self, Obj *other); + + public void + Destroy(RangeCompiler *self); + + void + Serialize(RangeCompiler *self, OutStream *outstream); + + incremented RangeCompiler* + Deserialize(decremented RangeCompiler *self, InStream *instream); } diff --git a/core/Lucy/Search/RequiredOptionalQuery.c b/core/Lucy/Search/RequiredOptionalQuery.c index 901453509..741c11095 100644 --- a/core/Lucy/Search/RequiredOptionalQuery.c +++ b/core/Lucy/Search/RequiredOptionalQuery.c @@ -98,23 +98,31 @@ ReqOptQuery_Make_Compiler_IMP(RequiredOptionalQuery *self, Searcher *searcher, /**********************************************************************/ RequiredOptionalCompiler* -ReqOptCompiler_new(RequiredOptionalQuery *parent, Searcher *searcher, +ReqOptCompiler_new(RequiredOptionalQuery *query, Searcher *searcher, float boost) { RequiredOptionalCompiler *self = (RequiredOptionalCompiler*)Class_Make_Obj( REQUIREDOPTIONALCOMPILER); - return ReqOptCompiler_init(self, parent, searcher, boost); + return ReqOptCompiler_init(self, query, searcher, boost); } RequiredOptionalCompiler* ReqOptCompiler_init(RequiredOptionalCompiler *self, - RequiredOptionalQuery *parent, + RequiredOptionalQuery *query, Searcher *searcher, float boost) { - PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)parent, searcher, - boost); + PolyCompiler_init((PolyCompiler*)self, (PolyQuery*)query, searcher, boost); return self; } +bool +ReqOptCompiler_Equals_IMP(RequiredOptionalCompiler *self, Obj *other) { + if ((RequiredOptionalCompiler*)other == self) { return true; } + if (!Obj_is_a(other, REQUIREDOPTIONALCOMPILER)) { return false; } + ReqOptCompiler_Equals_t super_equals = (ReqOptCompiler_Equals_t) + SUPER_METHOD_PTR(REQUIREDOPTIONALCOMPILER, LUCY_ReqOptCompiler_Equals); + return super_equals(self, other); +} + Matcher* ReqOptCompiler_Make_Matcher_IMP(RequiredOptionalCompiler *self, SegReader *reader, bool need_score) { diff --git a/core/Lucy/Search/RequiredOptionalQuery.cfh b/core/Lucy/Search/RequiredOptionalQuery.cfh index bb09182a4..65b0a8190 100644 --- a/core/Lucy/Search/RequiredOptionalQuery.cfh +++ b/core/Lucy/Search/RequiredOptionalQuery.cfh @@ -74,15 +74,18 @@ class Lucy::Search::RequiredOptionalCompiler nickname ReqOptCompiler inherits Lucy::Search::PolyCompiler { inert incremented RequiredOptionalCompiler* - new(RequiredOptionalQuery *parent, Searcher *searcher, float boost); + new(RequiredOptionalQuery *query, Searcher *searcher, float boost); inert RequiredOptionalCompiler* - init(RequiredOptionalCompiler *self, RequiredOptionalQuery *parent, + init(RequiredOptionalCompiler *self, RequiredOptionalQuery *query, Searcher *searcher, float boost); public incremented nullable Matcher* Make_Matcher(RequiredOptionalCompiler *self, SegReader *reader, bool need_score); + + public bool + Equals(RequiredOptionalCompiler *self, Obj *other); } diff --git a/core/Lucy/Search/Searcher.c b/core/Lucy/Search/Searcher.c index e2d7a2190..4f6b0309d 100644 --- a/core/Lucy/Search/Searcher.c +++ b/core/Lucy/Search/Searcher.c @@ -55,7 +55,7 @@ Searcher_Hits_IMP(Searcher *self, Obj *query, uint32_t offset, uint32_t wanted = offset + num_wanted > doc_max ? doc_max : offset + num_wanted; - TopDocs *top_docs = Searcher_Top_Docs(self, real_query, wanted, + TopDocs *top_docs = Searcher_Top_Docs(self, (Obj*)real_query, wanted, sort_spec); Hits *hits = Hits_new(self, top_docs, offset); DECREF(top_docs); diff --git a/core/Lucy/Search/Searcher.cfh b/core/Lucy/Search/Searcher.cfh index 2eeba6db6..e1422205d 100644 --- a/core/Lucy/Search/Searcher.cfh +++ b/core/Lucy/Search/Searcher.cfh @@ -81,16 +81,16 @@ public class Lucy::Search::Searcher inherits Clownfish::Obj { /** Iterate over hits, feeding them into a * [](cfish:Collector). * - * @param query A Query. + * @param query A Query or a Compiler. * @param collector A Collector. */ public abstract void - Collect(Searcher *self, Query *query, Collector *collector); + Collect(Searcher *self, Obj *query, Collector *collector); /** Return a TopDocs object with up to num_wanted hits. */ abstract incremented TopDocs* - Top_Docs(Searcher *self, Query *query, uint32_t num_wanted, + Top_Docs(Searcher *self, Obj *query, uint32_t num_wanted, SortSpec *sort_spec = NULL); /** Retrieve a document. Throws an error if the doc id is out of range. diff --git a/core/Lucy/Search/TermQuery.c b/core/Lucy/Search/TermQuery.c index ddf609eda..54d78dad4 100644 --- a/core/Lucy/Search/TermQuery.c +++ b/core/Lucy/Search/TermQuery.c @@ -132,37 +132,40 @@ TermQuery_To_String_IMP(TermQuery *self) { Compiler* TermQuery_Make_Compiler_IMP(TermQuery *self, Searcher *searcher, float boost) { - return (Compiler*)TermCompiler_new((Query*)self, searcher, boost); + return (Compiler*)TermCompiler_new(self, searcher, boost); } /******************************************************************/ TermCompiler* -TermCompiler_new(Query *parent, Searcher *searcher, float boost) { +TermCompiler_new(TermQuery *query, Searcher *searcher, float boost) { TermCompiler *self = (TermCompiler*)Class_Make_Obj(TERMCOMPILER); - return TermCompiler_init(self, parent, searcher, boost); + return TermCompiler_init(self, query, searcher, boost); } TermCompiler* -TermCompiler_init(TermCompiler *self, Query *parent, Searcher *searcher, +TermCompiler_init(TermCompiler *self, TermQuery *query, Searcher *searcher, float boost) { TermCompilerIVARS *const ivars = TermCompiler_IVARS(self); - TermQueryIVARS *const parent_ivars = TermQuery_IVARS((TermQuery*)parent); + TermQueryIVARS *const query_ivars = TermQuery_IVARS(query); + String *field = query_ivars->field; + Obj *term = query_ivars->term; Schema *schema = Searcher_Get_Schema(searcher); - Similarity *sim = Schema_Fetch_Sim(schema, parent_ivars->field); + Similarity *sim = Schema_Fetch_Sim(schema, field); // Try harder to get a Similarity if necessary. if (!sim) { sim = Schema_Get_Similarity(schema); } // Init. - Compiler_init((Compiler*)self, parent, searcher, sim, boost); + Compiler_init((Compiler*)self); + ivars->field = (String*)INCREF(field); + ivars->term = INCREF(term); ivars->normalized_weight = 0.0f; ivars->query_norm_factor = 0.0f; // Derive. int32_t doc_max = Searcher_Doc_Max(searcher); - uint32_t doc_freq = Searcher_Doc_Freq(searcher, parent_ivars->field, - parent_ivars->term); + uint32_t doc_freq = Searcher_Doc_Freq(searcher, field, term); ivars->idf = Sim_IDF(sim, (int32_t)doc_freq, doc_max); /* The score of any document is approximately equal to: @@ -176,20 +179,26 @@ TermCompiler_init(TermCompiler *self, Query *parent, Searcher *searcher, * tf_d and norm_d can only be added by the Matcher, since they are * per-document. */ - ivars->raw_weight = ivars->idf * ivars->boost; + ivars->raw_weight = ivars->idf * boost; return self; } +void +TermCompiler_Destroy_IMP(TermCompiler *self) { + TermCompilerIVARS *const ivars = TermCompiler_IVARS(self); + DECREF(ivars->field); + DECREF(ivars->term); + SUPER_DESTROY(self, TERMCOMPILER); +} + bool TermCompiler_Equals_IMP(TermCompiler *self, Obj *other) { - TermCompiler_Equals_t super_equals - = (TermCompiler_Equals_t)SUPER_METHOD_PTR(TERMCOMPILER, - LUCY_TermCompiler_Equals); - if (!super_equals(self, other)) { return false; } if (!Obj_is_a(other, TERMCOMPILER)) { return false; } TermCompilerIVARS *const ivars = TermCompiler_IVARS(self); TermCompilerIVARS *const ovars = TermCompiler_IVARS((TermCompiler*)other); + if (!Str_Equals(ivars->field, (Obj*)ovars->field)) { return false; } + if (!Obj_Equals(ivars->term, ovars->term)) { return false; } if (ivars->idf != ovars->idf) { return false; } if (ivars->raw_weight != ovars->raw_weight) { return false; } if (ivars->query_norm_factor != ovars->query_norm_factor) { return false; } @@ -200,9 +209,8 @@ TermCompiler_Equals_IMP(TermCompiler *self, Obj *other) { void TermCompiler_Serialize_IMP(TermCompiler *self, OutStream *outstream) { TermCompilerIVARS *const ivars = TermCompiler_IVARS(self); - TermCompiler_Serialize_t super_serialize - = SUPER_METHOD_PTR(TERMCOMPILER, LUCY_TermCompiler_Serialize); - super_serialize(self, outstream); + Freezer_serialize_string(ivars->field, outstream); + Freezer_freeze(ivars->term, outstream); OutStream_Write_F32(outstream, ivars->idf); OutStream_Write_F32(outstream, ivars->raw_weight); OutStream_Write_F32(outstream, ivars->query_norm_factor); @@ -211,10 +219,9 @@ TermCompiler_Serialize_IMP(TermCompiler *self, OutStream *outstream) { TermCompiler* TermCompiler_Deserialize_IMP(TermCompiler *self, InStream *instream) { - TermCompiler_Deserialize_t super_deserialize - = SUPER_METHOD_PTR(TERMCOMPILER, LUCY_TermCompiler_Deserialize); - self = super_deserialize(self, instream); TermCompilerIVARS *const ivars = TermCompiler_IVARS(self); + ivars->field = Freezer_read_string(instream); + ivars->term = Freezer_thaw(instream); ivars->idf = InStream_Read_F32(instream); ivars->raw_weight = InStream_Read_F32(instream); ivars->query_norm_factor = InStream_Read_F32(instream); @@ -244,25 +251,17 @@ TermCompiler_Apply_Norm_Factor_IMP(TermCompiler *self, = ivars->raw_weight * ivars->idf * query_norm_factor; } -float -TermCompiler_Get_Weight_IMP(TermCompiler *self) { - return TermCompiler_IVARS(self)->normalized_weight; -} - Matcher* TermCompiler_Make_Matcher_IMP(TermCompiler *self, SegReader *reader, bool need_score) { UNUSED_VAR(need_score); TermCompilerIVARS *const ivars = TermCompiler_IVARS(self); - TermQueryIVARS *const parent_ivars - = TermQuery_IVARS((TermQuery*)ivars->parent); PostingListReader *plist_reader = (PostingListReader*)SegReader_Fetch( reader, Class_Get_Name(POSTINGLISTREADER)); PostingList *plist = plist_reader - ? PListReader_Posting_List(plist_reader, - parent_ivars->field, - parent_ivars->term) + ? PListReader_Posting_List(plist_reader, ivars->field, + ivars->term) : NULL; if (plist == NULL || PList_Get_Doc_Freq(plist) == 0) { @@ -282,18 +281,16 @@ TermCompiler_Highlight_Spans_IMP(TermCompiler *self, Searcher *searcher, DocVector *doc_vec, String *field) { TermCompilerIVARS *const ivars = TermCompiler_IVARS(self); - TermQueryIVARS *const parent_ivars - = TermQuery_IVARS((TermQuery*)ivars->parent); Vector *spans = Vec_new(0); TermVector *term_vector; I32Array *starts, *ends; UNUSED_VAR(searcher); - if (!Str_Equals(parent_ivars->field, (Obj*)field)) { return spans; } + if (!Str_Equals(ivars->field, (Obj*)field)) { return spans; } // Add all starts and ends. term_vector - = DocVec_Term_Vector(doc_vec, field, (String*)parent_ivars->term); + = DocVec_Term_Vector(doc_vec, field, (String*)ivars->term); if (!term_vector) { return spans; } starts = TV_Get_Start_Offsets(term_vector); @@ -302,7 +299,7 @@ TermCompiler_Highlight_Spans_IMP(TermCompiler *self, Searcher *searcher, int32_t start = I32Arr_Get(starts, i); int32_t length = I32Arr_Get(ends, i) - start; Vec_Push(spans, - (Obj*)Span_new(start, length, TermCompiler_Get_Weight(self))); + (Obj*)Span_new(start, length, ivars->normalized_weight)); } DECREF(term_vector); diff --git a/core/Lucy/Search/TermQuery.cfh b/core/Lucy/Search/TermQuery.cfh index d9ee6223c..268cdea6b 100644 --- a/core/Lucy/Search/TermQuery.cfh +++ b/core/Lucy/Search/TermQuery.cfh @@ -80,24 +80,23 @@ public class Lucy::Search::TermQuery inherits Lucy::Search::Query { } class Lucy::Search::TermCompiler inherits Lucy::Search::Compiler { - float idf; - float raw_weight; - float query_norm_factor; - float normalized_weight; + String *field; + Obj *term; + float idf; + float raw_weight; + float query_norm_factor; + float normalized_weight; inert incremented TermCompiler* - new(Query *parent, Searcher *searcher, float boost); + new(TermQuery *query, Searcher *searcher, float boost); inert TermCompiler* - init(TermCompiler *self, Query *parent, Searcher *searcher, + init(TermCompiler *self, TermQuery *query, Searcher *searcher, float boost); public incremented nullable Matcher* Make_Matcher(TermCompiler *self, SegReader *reader, bool need_score); - public float - Get_Weight(TermCompiler *self); - public float Sum_Of_Squared_Weights(TermCompiler *self); @@ -116,6 +115,9 @@ class Lucy::Search::TermCompiler inherits Lucy::Search::Compiler { incremented TermCompiler* Deserialize(decremented TermCompiler *self, InStream *instream); + + public void + Destroy(TermCompiler *self); } diff --git a/core/Lucy/Util/Freezer.c b/core/Lucy/Util/Freezer.c index 3aa2810f5..fae58855f 100644 --- a/core/Lucy/Util/Freezer.c +++ b/core/Lucy/Util/Freezer.c @@ -31,6 +31,7 @@ #include "Lucy/Index/TermVector.h" #include "Lucy/Plan/FieldType.h" #include "Lucy/Plan/Schema.h" +#include "Lucy/Search/Compiler.h" #include "Lucy/Search/Query.h" #include "Lucy/Search/SortRule.h" #include "Lucy/Search/SortSpec.h" @@ -94,6 +95,9 @@ Freezer_serialize(Obj *obj, OutStream *outstream) { else if (Obj_is_a(obj, QUERY)) { Query_Serialize((Query*)obj, outstream); } + else if (Obj_is_a(obj, COMPILER)) { + Compiler_Serialize((Compiler*)obj, outstream); + } else if (Obj_is_a(obj, DOC)) { Doc_Serialize((Doc*)obj, outstream); } @@ -149,6 +153,9 @@ Freezer_deserialize(Obj *obj, InStream *instream) { else if (Obj_is_a(obj, QUERY)) { obj = (Obj*)Query_Deserialize((Query*)obj, instream); } + else if (Obj_is_a(obj, COMPILER)) { + obj = (Obj*)Compiler_Deserialize((Compiler*)obj, instream); + } else if (Obj_is_a(obj, DOC)) { obj = (Obj*)Doc_Deserialize((Doc*)obj, instream); } diff --git a/core/LucyX/Search/ProximityMatcher.c b/core/LucyX/Search/ProximityMatcher.c index e72bdc285..cc82eef6a 100644 --- a/core/LucyX/Search/ProximityMatcher.c +++ b/core/LucyX/Search/ProximityMatcher.c @@ -27,17 +27,17 @@ ProximityMatcher* -ProximityMatcher_new(Similarity *sim, Vector *plists, Compiler *compiler, +ProximityMatcher_new(Similarity *sim, Vector *plists, float weight, uint32_t within) { ProximityMatcher *self = (ProximityMatcher*)Class_Make_Obj(PROXIMITYMATCHER); - return ProximityMatcher_init(self, sim, plists, compiler, within); + return ProximityMatcher_init(self, sim, plists, weight, within); } ProximityMatcher* ProximityMatcher_init(ProximityMatcher *self, Similarity *similarity, - Vector *plists, Compiler *compiler, uint32_t within) { + Vector *plists, float weight, uint32_t within) { Matcher_init((Matcher*)self); ProximityMatcherIVARS *const ivars = ProximityMatcher_IVARS(self); @@ -63,9 +63,8 @@ ProximityMatcher_init(ProximityMatcher *self, Similarity *similarity, } // Assign. - ivars->sim = (Similarity*)INCREF(similarity); - ivars->compiler = (Compiler*)INCREF(compiler); - ivars->weight = Compiler_Get_Weight(compiler); + ivars->sim = (Similarity*)INCREF(similarity); + ivars->weight = weight; return self; } @@ -81,7 +80,6 @@ ProximityMatcher_Destroy_IMP(ProximityMatcher *self) { } DECREF(ivars->sim); DECREF(ivars->anchor_set); - DECREF(ivars->compiler); SUPER_DESTROY(self, PROXIMITYMATCHER); } diff --git a/core/LucyX/Search/ProximityMatcher.cfh b/core/LucyX/Search/ProximityMatcher.cfh index 2ec796bc6..16d229e42 100644 --- a/core/LucyX/Search/ProximityMatcher.cfh +++ b/core/LucyX/Search/ProximityMatcher.cfh @@ -28,19 +28,18 @@ class LucyX::Search::ProximityMatcher inherits Lucy::Search::Matcher { ByteBuf *anchor_set; float proximity_freq; float proximity_boost; - Compiler *compiler; float weight; bool first_time; bool more; uint32_t within; inert incremented ProximityMatcher* - new(Similarity *similarity, Vector *posting_lists, Compiler *compiler, + new(Similarity *similarity, Vector *posting_lists, float weight, uint32_t within); inert ProximityMatcher* init(ProximityMatcher *self, Similarity *similarity, Vector *posting_lists, - Compiler *compiler, uint32_t within); + float weight, uint32_t within); public void Destroy(ProximityMatcher *self); diff --git a/core/LucyX/Search/ProximityQuery.c b/core/LucyX/Search/ProximityQuery.c index 29fdbfa55..df4b828d2 100644 --- a/core/LucyX/Search/ProximityQuery.c +++ b/core/LucyX/Search/ProximityQuery.c @@ -186,8 +186,7 @@ ProximityQuery_Make_Compiler_IMP(ProximityQuery *self, Searcher *searcher, return (Compiler*)term_compiler; } else { - return (Compiler*)ProximityCompiler_new(self, searcher, boost, - ivars->within); + return (Compiler*)ProximityCompiler_new(self, searcher, boost); } } @@ -209,53 +208,60 @@ ProximityQuery_Get_Within_IMP(ProximityQuery *self) { /*********************************************************************/ ProximityCompiler* -ProximityCompiler_new(ProximityQuery *parent, Searcher *searcher, float boost, - uint32_t within) { +ProximityCompiler_new(ProximityQuery *query, Searcher *searcher, float boost) { ProximityCompiler *self = (ProximityCompiler*)Class_Make_Obj(PROXIMITYCOMPILER); - return ProximityCompiler_init(self, parent, searcher, boost, within); + return ProximityCompiler_init(self, query, searcher, boost); } ProximityCompiler* -ProximityCompiler_init(ProximityCompiler *self, ProximityQuery *parent, - Searcher *searcher, float boost, uint32_t within) { +ProximityCompiler_init(ProximityCompiler *self, ProximityQuery *query, + Searcher *searcher, float boost) { ProximityCompilerIVARS *const ivars = ProximityCompiler_IVARS(self); - ProximityQueryIVARS *const parent_ivars = ProximityQuery_IVARS(parent); + ProximityQueryIVARS *const query_ivars = ProximityQuery_IVARS(query); + String *field = query_ivars->field; + Vector *terms = query_ivars->terms; Schema *schema = Searcher_Get_Schema(searcher); - Similarity *sim = Schema_Fetch_Sim(schema, parent_ivars->field); - Vector *terms = parent_ivars->terms; - - ivars->within = within; + Similarity *sim = Schema_Fetch_Sim(schema, ivars->field); // Try harder to find a Similarity if necessary. if (!sim) { sim = Schema_Get_Similarity(schema); } // Init. - Compiler_init((Compiler*)self, (Query*)parent, searcher, sim, boost); + Compiler_init((Compiler*)self); + ivars->field = (String*)INCREF(field); + ivars->terms = (Vector*)INCREF(terms); + ivars->within = query_ivars->within; // Store IDF for the phrase. ivars->idf = 0; for (size_t i = 0, max = Vec_Get_Size(terms); i < max; i++) { Obj *term = Vec_Fetch(terms, i); int32_t doc_max = Searcher_Doc_Max(searcher); - uint32_t doc_freq - = Searcher_Doc_Freq(searcher, parent_ivars->field,term); + uint32_t doc_freq = Searcher_Doc_Freq(searcher, field, term); ivars->idf += Sim_IDF(sim, (int32_t)doc_freq, doc_max); } // Calculate raw weight. - ivars->raw_weight = ivars->idf * ivars->boost; + ivars->raw_weight = ivars->idf * boost; return self; } +void +ProximityCompiler_Destroy_IMP(ProximityCompiler *self) { + ProximityCompilerIVARS *const ivars = ProximityCompiler_IVARS(self); + DECREF(ivars->field); + DECREF(ivars->terms); + SUPER_DESTROY(self, PROXIMITYCOMPILER); +} + void ProximityCompiler_Serialize_IMP(ProximityCompiler *self, OutStream *outstream) { - ProximityCompiler_Serialize_t super_serialize - = SUPER_METHOD_PTR(PROXIMITYCOMPILER, LUCY_ProximityCompiler_Serialize); - super_serialize(self, outstream); ProximityCompilerIVARS *const ivars = ProximityCompiler_IVARS(self); + Freezer_serialize_string(ivars->field, outstream); + Freezer_serialize_varray(ivars->terms, outstream); OutStream_Write_F32(outstream, ivars->idf); OutStream_Write_F32(outstream, ivars->raw_weight); OutStream_Write_F32(outstream, ivars->query_norm_factor); @@ -266,15 +272,20 @@ ProximityCompiler_Serialize_IMP(ProximityCompiler *self, ProximityCompiler* ProximityCompiler_Deserialize_IMP(ProximityCompiler *self, InStream *instream) { - ProximityCompiler_Deserialize_t super_deserialize - = SUPER_METHOD_PTR(PROXIMITYCOMPILER, LUCY_ProximityCompiler_Deserialize); - self = super_deserialize(self, instream); ProximityCompilerIVARS *const ivars = ProximityCompiler_IVARS(self); + + ivars->field = Freezer_read_string(instream); + ivars->terms = Freezer_read_varray(instream); ivars->idf = InStream_Read_F32(instream); ivars->raw_weight = InStream_Read_F32(instream); ivars->query_norm_factor = InStream_Read_F32(instream); ivars->normalized_weight = InStream_Read_F32(instream); ivars->within = InStream_Read_CU32(instream); + + for (size_t i = 0, max = Vec_Get_Size(ivars->terms); i < max; i++) { + CERTIFY(Vec_Fetch(ivars->terms, i), OBJ); + } + return self; } @@ -282,13 +293,11 @@ bool ProximityCompiler_Equals_IMP(ProximityCompiler *self, Obj *other) { if ((ProximityCompiler*)other == self) { return true; } if (!Obj_is_a(other, PROXIMITYCOMPILER)) { return false; } - ProximityCompiler_Equals_t super_equals - = (ProximityCompiler_Equals_t)SUPER_METHOD_PTR(PROXIMITYCOMPILER, - LUCY_ProximityCompiler_Equals); - if (!super_equals(self, other)) { return false; } ProximityCompilerIVARS *const ivars = ProximityCompiler_IVARS(self); ProximityCompilerIVARS *const ovars = ProximityCompiler_IVARS((ProximityCompiler*)other); + if (!Str_Equals(ivars->field, (Obj*)ovars->field)) { return false; } + if (!Vec_Equals(ivars->terms, (Obj*)ovars->terms)) { return false; } if (ivars->idf != ovars->idf) { return false; } if (ivars->raw_weight != ovars->raw_weight) { return false; } if (ivars->query_norm_factor != ovars->query_norm_factor) { return false; } @@ -297,11 +306,6 @@ ProximityCompiler_Equals_IMP(ProximityCompiler *self, Obj *other) { return true; } -float -ProximityCompiler_Get_Weight_IMP(ProximityCompiler *self) { - return ProximityCompiler_IVARS(self)->normalized_weight; -} - float ProximityCompiler_Sum_Of_Squared_Weights_IMP(ProximityCompiler *self) { ProximityCompilerIVARS *const ivars = ProximityCompiler_IVARS(self); @@ -321,16 +325,23 @@ ProximityCompiler_Make_Matcher_IMP(ProximityCompiler *self, SegReader *reader, bool need_score) { ProximityCompilerIVARS *const ivars = ProximityCompiler_IVARS(self); UNUSED_VAR(need_score); - ProximityQueryIVARS *const parent_ivars - = ProximityQuery_IVARS((ProximityQuery*)ivars->parent); - Vector *const terms = parent_ivars->terms; + Vector *const terms = ivars->terms; size_t num_terms = Vec_Get_Size(terms); // Bail if there are no terms. if (!num_terms) { return NULL; } + // Bail if there's no PostingListReader for this segment. + PostingListReader *const plist_reader + = (PostingListReader*)SegReader_Fetch( + reader, Class_Get_Name(POSTINGLISTREADER)); + if (!plist_reader) { return NULL; } + + Schema *schema = PListReader_Get_Schema(plist_reader); + Similarity *sim = Schema_Fetch_Sim(schema, ivars->field); + if (!sim) { sim = Schema_Get_Similarity(schema); } + // Bail unless field is valid and posting type supports positions. - Similarity *sim = ProximityCompiler_Get_Similarity(self); Posting *posting = Sim_Make_Posting(sim); if (posting == NULL || !Obj_is_a((Obj*)posting, SCOREPOSTING)) { DECREF(posting); @@ -338,18 +349,12 @@ ProximityCompiler_Make_Matcher_IMP(ProximityCompiler *self, SegReader *reader, } DECREF(posting); - // Bail if there's no PostingListReader for this segment. - PostingListReader *const plist_reader - = (PostingListReader*)SegReader_Fetch( - reader, Class_Get_Name(POSTINGLISTREADER)); - if (!plist_reader) { return NULL; } - // Look up each term. Vector *plists = Vec_new(num_terms); for (size_t i = 0; i < num_terms; i++) { Obj *term = Vec_Fetch(terms, i); PostingList *plist - = PListReader_Posting_List(plist_reader, parent_ivars->field, term); + = PListReader_Posting_List(plist_reader, ivars->field, term); // Bail if any one of the terms isn't in the index. if (!plist || !PList_Get_Doc_Freq(plist)) { @@ -360,8 +365,9 @@ ProximityCompiler_Make_Matcher_IMP(ProximityCompiler *self, SegReader *reader, Vec_Push(plists, (Obj*)plist); } + float weight = ivars->normalized_weight; Matcher *retval - = (Matcher*)ProximityMatcher_new(sim, plists, (Compiler*)self, ivars->within); + = (Matcher*)ProximityMatcher_new(sim, plists, weight, ivars->within); DECREF(plists); return retval; } @@ -371,16 +377,14 @@ ProximityCompiler_Highlight_Spans_IMP(ProximityCompiler *self, Searcher *searcher, DocVector *doc_vec, String *field) { ProximityCompilerIVARS *const ivars = ProximityCompiler_IVARS(self); - ProximityQueryIVARS *const parent_ivars - = ProximityQuery_IVARS((ProximityQuery*)ivars->parent); - Vector *const terms = parent_ivars->terms; + Vector *const terms = ivars->terms; Vector *const spans = Vec_new(0); const uint32_t num_terms = (uint32_t)Vec_Get_Size(terms); UNUSED_VAR(searcher); // Bail if no terms or field doesn't match. if (!num_terms) { return spans; } - if (!Str_Equals(field, (Obj*)parent_ivars->field)) { return spans; } + if (!Str_Equals(field, (Obj*)ivars->field)) { return spans; } Vector *term_vectors = Vec_new(num_terms); BitVector *posit_vec = BitVec_new(0); @@ -433,7 +437,7 @@ ProximityCompiler_Highlight_Spans_IMP(ProximityCompiler *self, I32Array *valid_posits = BitVec_To_Array(posit_vec); size_t num_valid_posits = I32Arr_Get_Size(valid_posits); size_t j = 0; - float weight = ProximityCompiler_Get_Weight(self); + float weight = ivars->normalized_weight; size_t i = 0; // Add only those starts/ends that belong to a valid position. diff --git a/core/LucyX/Search/ProximityQuery.cfh b/core/LucyX/Search/ProximityQuery.cfh index 106ebbc93..98689e00c 100644 --- a/core/LucyX/Search/ProximityQuery.cfh +++ b/core/LucyX/Search/ProximityQuery.cfh @@ -87,25 +87,24 @@ public class LucyX::Search::ProximityQuery inherits Lucy::Search::Query { class LucyX::Search::ProximityCompiler inherits Lucy::Search::Compiler { - float idf; - float raw_weight; - float query_norm_factor; - float normalized_weight; - uint32_t within; + String *field; + Vector *terms; + float idf; + float raw_weight; + float query_norm_factor; + float normalized_weight; + uint32_t within; inert incremented ProximityCompiler* - new(ProximityQuery *parent, Searcher *searcher, float boost, uint32_t within); + new(ProximityQuery *query, Searcher *searcher, float boost); inert ProximityCompiler* - init(ProximityCompiler *self, ProximityQuery *parent, Searcher *searcher, - float boost, uint32_t within); + init(ProximityCompiler *self, ProximityQuery *query, Searcher *searcher, + float boost); public incremented nullable Matcher* Make_Matcher(ProximityCompiler *self, SegReader *reader, bool need_score); - public float - Get_Weight(ProximityCompiler *self); - public float Sum_Of_Squared_Weights(ProximityCompiler *self); @@ -124,6 +123,9 @@ class LucyX::Search::ProximityCompiler incremented ProximityCompiler* Deserialize(decremented ProximityCompiler *self, InStream *instream); + + public void + Destroy(ProximityCompiler *self); } diff --git a/go/lucy/highlight_test.go b/go/lucy/highlight_test.go index 3b60a8ddb..774464c5a 100644 --- a/go/lucy/highlight_test.go +++ b/go/lucy/highlight_test.go @@ -73,10 +73,6 @@ func TestHighlighterAccessors(t *testing.T) { if _, ok := hl.GetSearcher().(Searcher); !ok { t.Errorf("GetSearcher") } - barQuery := NewTermQuery("content", "bar") - if got := hl.GetQuery(); !barQuery.Equals(got) { - t.Errorf("GetQuery: %T %v", got, got) - } if _, ok := hl.GetCompiler().(Compiler); !ok { t.Errorf("GetCompiler") } diff --git a/go/lucy/search.go b/go/lucy/search.go index 097905453..8d76a68a0 100644 --- a/go/lucy/search.go +++ b/go/lucy/search.go @@ -139,7 +139,7 @@ func (s *SearcherIMP) topDocs(query Query, numWanted uint32, err = clownfish.TrapErr(func() { self := (*C.lucy_Searcher)(clownfish.Unwrap(s, "s")) sortSpecC := (*C.lucy_SortSpec)(clownfish.UnwrapNullable(sortSpec)) - queryC := (*C.lucy_Query)(clownfish.Unwrap(query, "query")) + queryC := (*C.cfish_Obj)(clownfish.Unwrap(query, "query")) topDocsC := C.LUCY_Searcher_Top_Docs(self, queryC, C.uint32_t(numWanted), sortSpecC) topDocs = WRAPTopDocs(unsafe.Pointer(topDocsC)) diff --git a/go/lucy/search_test.go b/go/lucy/search_test.go index 25da159b6..15da0b4e2 100644 --- a/go/lucy/search_test.go +++ b/go/lucy/search_test.go @@ -34,6 +34,19 @@ func checkQuerySerialize(t *testing.T, query Query) { } } +func checkCompilerSerialize(t *testing.T, compiler Compiler) { + folder := NewRAMFolder("") + outStream, _ := folder.OpenOut("foo") + compiler.serialize(outStream) + outStream.Close() + inStream, _ := folder.OpenIn("foo") + dupe := clownfish.GetClass(compiler).MakeObj().(Compiler).deserialize(inStream) + if !compiler.Equals(dupe) { + t.Errorf("Unsuccessful serialization round trip -- expected '%v', got '%v'", + compiler.ToString(), dupe.ToString()) + } +} + func checkQueryDumpLoad(t *testing.T, query Query) { dupe := clownfish.GetClass(query).MakeObj().(Query) dupe = dupe.Load(query.Dump()).(Query) @@ -43,11 +56,11 @@ func checkQueryDumpLoad(t *testing.T, query Query) { } } -func checkQueryEquals(t *testing.T, query Query) { - if !query.Equals(query) { +func checkObjEquals(t *testing.T, obj clownfish.Obj) { + if !obj.Equals(obj) { t.Error("Equals self") } - if query.Equals("blah") { + if obj.Equals("blah") { t.Error("Equals against Go string") } } @@ -72,7 +85,7 @@ func TestTermQueryMisc(t *testing.T) { query := NewTermQuery("content", "foo") checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -92,9 +105,8 @@ func TestTermCompilerMisc(t *testing.T) { searcher, _ := OpenIndexSearcher(folder) query := NewTermQuery("content", "foo") compiler := NewTermCompiler(query, searcher, 1.0) - checkQuerySerialize(t, compiler) - checkQueryEquals(t, compiler) - checkQueryToStringHasFoo(t, compiler) + checkCompilerSerialize(t, compiler) + checkObjEquals(t, compiler) segReaders := searcher.GetReader().SegReaders() matcher, err := compiler.MakeMatcher(segReaders[0].(SegReader), false) if matcher == nil || err != nil { @@ -108,7 +120,6 @@ func TestTermCompilerWeighting(t *testing.T) { query := NewTermQuery("content", "foo") compiler := NewTermCompiler(query, searcher, 1.0) _ = compiler.SumOfSquaredWeights() - _ = compiler.GetWeight() compiler.ApplyNormFactor(10.0) } @@ -117,7 +128,7 @@ func TestPhraseQueryMisc(t *testing.T) { query := NewPhraseQuery("content", terms) checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -139,9 +150,8 @@ func TestPhraseCompilerMisc(t *testing.T) { terms := []interface{}{"foo", "bar"} query := NewPhraseQuery("content", terms) compiler := NewPhraseCompiler(query, searcher, 1.0) - checkQuerySerialize(t, compiler) - checkQueryEquals(t, compiler) - checkQueryToStringHasFoo(t, compiler) + checkCompilerSerialize(t, compiler) + checkObjEquals(t, compiler) } func TestPhraseCompilerWeighting(t *testing.T) { @@ -151,7 +161,6 @@ func TestPhraseCompilerWeighting(t *testing.T) { query := NewPhraseQuery("content", terms) compiler := NewPhraseCompiler(query, searcher, 1.0) _ = compiler.SumOfSquaredWeights() - _ = compiler.GetWeight() compiler.ApplyNormFactor(10.0) } @@ -163,7 +172,7 @@ func TestANDQueryBasics(t *testing.T) { query := NewANDQuery(children) checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -176,7 +185,7 @@ func TestORQueryBasics(t *testing.T) { query := NewORQuery(children) checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -187,7 +196,7 @@ func TestReqOptQueryBasics(t *testing.T) { query := NewRequiredOptionalQuery(req, opt) checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -209,7 +218,7 @@ func TestNOTQueryBasics(t *testing.T) { query := NewNOTQuery(negated) checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -226,7 +235,7 @@ func TestMatchAllQueryBasics(t *testing.T) { query := NewMatchAllQuery() checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) } @@ -234,7 +243,7 @@ func TestNOMatchQueryBasics(t *testing.T) { query := NewNoMatchQuery() checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) } @@ -242,7 +251,7 @@ func TestRangeQueryBasics(t *testing.T) { query := NewRangeQuery("content", "fab", "foo", true, true) checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryMakeRootCompiler(t, query) checkQueryToStringHasFoo(t, query) } @@ -251,7 +260,7 @@ func TestLeafQueryBasics(t *testing.T) { query := NewLeafQuery("content", "foo") checkQuerySerialize(t, query) checkQueryDumpLoad(t, query) - checkQueryEquals(t, query) + checkObjEquals(t, query) checkQueryToStringHasFoo(t, query) } diff --git a/perl/buildlib/Lucy/Build/Binding/Search.pm b/perl/buildlib/Lucy/Build/Binding/Search.pm index 6d3ddcb0e..4d07f98b5 100644 --- a/perl/buildlib/Lucy/Build/Binding/Search.pm +++ b/perl/buildlib/Lucy/Build/Binding/Search.pm @@ -184,12 +184,17 @@ the parent Query. END_CONSTRUCTOR_POD $pod_spec->set_synopsis($synopsis); $pod_spec->add_constructor( alias => 'new', pod => $constructor, ); + $pod_spec->add_method( + method => 'Normalize', + alias => 'normalize', + ); my $binding = Clownfish::CFC::Binding::Perl::Class->new( parcel => "Lucy", class_name => "Lucy::Search::Compiler", ); $binding->bind_constructor( alias => 'do_new' ); + $binding->bind_method( alias => '_normalize', method => 'Normalize' ); $binding->set_pod_spec($pod_spec); Clownfish::CFC::Binding::Perl::Class->register($binding); diff --git a/perl/lib/Lucy.pm b/perl/lib/Lucy.pm index 2a5b5ceb8..5bde92ae7 100644 --- a/perl/lib/Lucy.pm +++ b/perl/lib/Lucy.pm @@ -162,18 +162,67 @@ BEGIN { package Lucy::Search::Compiler; our $VERSION = '0.006000'; $VERSION = eval $VERSION; + use Lucy qw( STORABLE_freeze STORABLE_thaw ); + + # Backward compatibility. + use Carp; use Scalar::Util qw( blessed ); + my %warned; + sub new { my ( $either, %args ) = @_; - if ( !defined $args{boost} ) { - confess("'parent' is not a Query") - unless ( blessed( $args{parent} ) - and $args{parent}->isa("Lucy::Search::Query") ); - $args{boost} = $args{parent}->get_boost; + my $self = $either->do_new; + if (%args) { + my $class = ref($either) || $either; + if ( !exists $warned{$class} ) { + warn <<"EOF"; +Warning: $class uses the deprecated +Lucy::Search::Compiler API which will be removed in a +future release. Please adapt to the new API. +EOF + $warned{$class} = undef; + } + if ( !defined $args{boost} ) { + confess("'parent' is not a Query") + unless ( blessed( $args{parent} ) + and $args{parent}->isa("Lucy::Search::Query") ); + $args{boost} = $args{parent}->get_boost; + } + $self->{_cf_boost} = $args{boost}; + $self->{_cf_parent} = $args{parent}; + $self->{_cf_sim} = $args{similarity} + || $args{searcher}->get_schema + ->get_similarity; } - return $either->do_new(%args); + return $self; + } + + sub get_boost { + my $self = shift; + return $self->{_cf_boost}; + } + + sub get_weight { + my $self = shift; + return $self->{_cf_boost}; + } + + sub get_parent { + my $self = shift; + return $self->{_cf_parent}; + } + + sub get_similarity { + my $self = shift; + return $self->{_cf_sim}; + } + + sub normalize { + my ( $self, $sim ) = @_; + $sim ||= $self->{_cf_sim}; + $self->_normalize($sim); } } diff --git a/perl/t/binding/303-highlighter.t b/perl/t/binding/303-highlighter.t index bf905276d..f8f8fb6f5 100644 --- a/perl/t/binding/303-highlighter.t +++ b/perl/t/binding/303-highlighter.t @@ -55,7 +55,7 @@ sub highlight { package main; -use Test::More tests => 6; +use Test::More tests => 5; use Lucy::Test; binmode( STDOUT, ":utf8" ); @@ -115,8 +115,6 @@ $hl = Lucy::Highlight::Highlighter->new( query => $compiler, field => 'content', ); -is( $$compiler, ${ $hl->get_query }, - "Highlighter accepts Compiler as Query" ); is( $$compiler, ${ $hl->get_compiler }, "Highlighter uses supplied Compiler" ); diff --git a/test/Lucy/Test/Search/TestPolySearcher.c b/test/Lucy/Test/Search/TestPolySearcher.c index ed0082e6b..34e0c2566 100644 --- a/test/Lucy/Test/Search/TestPolySearcher.c +++ b/test/Lucy/Test/Search/TestPolySearcher.c @@ -111,7 +111,7 @@ test_poly_searcher(TestBatchRunner *runner) { Collector *collector = (Collector*)BitColl_new(bit_vec); Query *query = PolySearcher_Glean_Query(poly_searcher, (Obj*)SSTR_WRAP_C("b")); - PolySearcher_Collect(poly_searcher, query, collector); + PolySearcher_Collect(poly_searcher, (Obj*)query, collector); TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 0), 2, "Collect doc 1"); TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 3), 4, "Collect doc 2"); TEST_INT_EQ(runner, BitVec_Next_Hit(bit_vec, 5), -1, "Collect end"); From 6125e8312f73ed7016f4b90f770fc838ccb0bb3b Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Mon, 13 Feb 2017 18:03:29 +0100 Subject: [PATCH 6/8] Compiler serialization tests --- perl/t/core/613-proximity_query.t | 23 ++++++ test/Lucy/Test.c | 2 + test/Lucy/Test/Search/MockSearcher.c | 50 +++++++++++++ test/Lucy/Test/Search/MockSearcher.cfh | 34 +++++++++ test/Lucy/Test/Search/TestMatchAllQuery.c | 8 +- test/Lucy/Test/Search/TestNOTQuery.c | 16 +++- test/Lucy/Test/Search/TestNoMatchQuery.c | 8 +- test/Lucy/Test/Search/TestPhraseQuery.c | 15 +++- test/Lucy/Test/Search/TestPolyQuery.c | 22 +++++- test/Lucy/Test/Search/TestRangeQuery.c | 11 ++- test/Lucy/Test/Search/TestReqOptQuery.c | 21 +++++- test/Lucy/Test/Search/TestTermQuery.c | 14 +++- test/Lucy/Test/TestUtils.c | 17 +++++ test/Lucy/Test/TestUtils.cfh | 6 ++ test/LucyX/Test/Search/TestProximityQuery.c | 73 +++++++++++++++++++ test/LucyX/Test/Search/TestProximityQuery.cfh | 29 ++++++++ 16 files changed, 340 insertions(+), 9 deletions(-) create mode 100644 perl/t/core/613-proximity_query.t create mode 100644 test/Lucy/Test/Search/MockSearcher.c create mode 100644 test/Lucy/Test/Search/MockSearcher.cfh create mode 100644 test/LucyX/Test/Search/TestProximityQuery.c create mode 100644 test/LucyX/Test/Search/TestProximityQuery.cfh diff --git a/perl/t/core/613-proximity_query.t b/perl/t/core/613-proximity_query.t new file mode 100644 index 000000000..cb4026c9e --- /dev/null +++ b/perl/t/core/613-proximity_query.t @@ -0,0 +1,23 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +use strict; +use warnings; + +use Lucy::Test; +my $success = Lucy::Test::run_tests("LucyX::Test::Search::TestProximityQuery"); + +exit($success ? 0 : 1); + diff --git a/test/Lucy/Test.c b/test/Lucy/Test.c index 2a30a680e..fff556570 100644 --- a/test/Lucy/Test.c +++ b/test/Lucy/Test.c @@ -89,6 +89,7 @@ #include "Lucy/Test/Util/TestPriorityQueue.h" #include "Lucy/Test/Util/TestSortExternal.h" #include "Lucy/Test/Util/TestStringHelper.h" +#include "LucyX/Test/Search/TestProximityQuery.h" TestSuite* Test_create_test_suite() { @@ -160,6 +161,7 @@ Test_create_test_suite() { TestSuite_Add_Batch(suite, (TestBatch*)TestNoMatchQuery_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestSeriesMatcher_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestORQuery_new()); + TestSuite_Add_Batch(suite, (TestBatch*)TestProximityQuery_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestQPLogic_new()); TestSuite_Add_Batch(suite, (TestBatch*)TestQPSyntax_new()); diff --git a/test/Lucy/Test/Search/MockSearcher.c b/test/Lucy/Test/Search/MockSearcher.c new file mode 100644 index 000000000..3176d9625 --- /dev/null +++ b/test/Lucy/Test/Search/MockSearcher.c @@ -0,0 +1,50 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define TESTLUCY_USE_SHORT_NAMES +#include "Lucy/Util/ToolSet.h" + +#include "Lucy/Test/Search/MockSearcher.h" +#include "Lucy/Test/TestSchema.h" + +MockSearcher* +MockSearcher_new() { + MockSearcher *self = (MockSearcher*)Class_Make_Obj(MOCKSEARCHER); + return MockSearcher_init(self); +} + +MockSearcher* +MockSearcher_init(MockSearcher *self) { + Schema *schema = (Schema*)TestSchema_new(false); + Searcher_init((Searcher*)self, schema); + DECREF(schema); + return self; +} + +int32_t +MockSearcher_Doc_Max_IMP(MockSearcher *self) { + UNUSED_VAR(self); + return 2500; +} + +uint32_t +MockSearcher_Doc_Freq_IMP(MockSearcher *self, String *field, Obj *term) { + UNUSED_VAR(self); + UNUSED_VAR(field); + UNUSED_VAR(term); + return 10; +} + diff --git a/test/Lucy/Test/Search/MockSearcher.cfh b/test/Lucy/Test/Search/MockSearcher.cfh new file mode 100644 index 000000000..5bb240c06 --- /dev/null +++ b/test/Lucy/Test/Search/MockSearcher.cfh @@ -0,0 +1,34 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +parcel TestLucy; + +class Lucy::Test::Search::MockSearcher inherits Lucy::Search::Searcher { + + public inert incremented MockSearcher* + new(); + + public inert MockSearcher* + init(MockSearcher *self); + + public int32_t + Doc_Max(MockSearcher *self); + + public uint32_t + Doc_Freq(MockSearcher *self, String *field, Obj *term); +} + + diff --git a/test/Lucy/Test/Search/TestMatchAllQuery.c b/test/Lucy/Test/Search/TestMatchAllQuery.c index 524d25dfd..ded039216 100644 --- a/test/Lucy/Test/Search/TestMatchAllQuery.c +++ b/test/Lucy/Test/Search/TestMatchAllQuery.c @@ -47,11 +47,17 @@ test_Dump_Load_and_Equals(TestBatchRunner *runner) { DECREF(clone); } +static void +test_freeze_thaw_compiler(TestBatchRunner *runner) { + TestUtils_test_freeze_thaw(runner, (Obj*)MatchAllCompiler_new(38.0f), + "compiler"); +} void TestMatchAllQuery_Run_IMP(TestMatchAllQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 2); + TestBatchRunner_Plan(runner, (TestBatch*)self, 3); test_Dump_Load_and_Equals(runner); + test_freeze_thaw_compiler(runner); } diff --git a/test/Lucy/Test/Search/TestNOTQuery.c b/test/Lucy/Test/Search/TestNOTQuery.c index eee76575f..67c1bdd6e 100644 --- a/test/Lucy/Test/Search/TestNOTQuery.c +++ b/test/Lucy/Test/Search/TestNOTQuery.c @@ -22,9 +22,11 @@ #include "Clownfish/TestHarness/TestBatchRunner.h" #include "Lucy/Test.h" #include "Lucy/Test/TestUtils.h" +#include "Lucy/Test/Search/MockSearcher.h" #include "Lucy/Test/Search/TestNOTQuery.h" #include "Lucy/Search/NOTQuery.h" #include "Lucy/Search/LeafQuery.h" +#include "Lucy/Search/TermQuery.h" #include "Lucy/Util/Freezer.h" TestNOTQuery* @@ -61,10 +63,22 @@ test_Dump_Load_and_Equals(TestBatchRunner *runner) { DECREF(clone); } +static void +test_freeze_thaw_compiler(TestBatchRunner *runner) { + NOTQuery *query = TestUtils_make_not_query( + (Query*)TermQuery_new(SSTR_WRAP_C("content"), (Obj*)SSTR_WRAP_C("a"))); + Searcher *searcher = (Searcher*)MockSearcher_new(); + NOTCompiler *compiler = NOTCompiler_new(query, searcher, 921.0f); + TestUtils_test_freeze_thaw(runner, (Obj*)compiler, "compiler"); + DECREF(searcher); + DECREF(query); +} + void TestNOTQuery_Run_IMP(TestNOTQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 4); + TestBatchRunner_Plan(runner, (TestBatch*)self, 5); test_Dump_Load_and_Equals(runner); + test_freeze_thaw_compiler(runner); } diff --git a/test/Lucy/Test/Search/TestNoMatchQuery.c b/test/Lucy/Test/Search/TestNoMatchQuery.c index bac28b966..b23312c53 100644 --- a/test/Lucy/Test/Search/TestNoMatchQuery.c +++ b/test/Lucy/Test/Search/TestNoMatchQuery.c @@ -47,11 +47,17 @@ test_Dump_Load_and_Equals(TestBatchRunner *runner) { DECREF(clone); } +static void +test_freeze_thaw_compiler(TestBatchRunner *runner) { + TestUtils_test_freeze_thaw(runner, (Obj*)NoMatchCompiler_new(), + "compiler"); +} void TestNoMatchQuery_Run_IMP(TestNoMatchQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 2); + TestBatchRunner_Plan(runner, (TestBatch*)self, 3); test_Dump_Load_and_Equals(runner); + test_freeze_thaw_compiler(runner); } diff --git a/test/Lucy/Test/Search/TestPhraseQuery.c b/test/Lucy/Test/Search/TestPhraseQuery.c index c0ed6dab1..e3316e630 100644 --- a/test/Lucy/Test/Search/TestPhraseQuery.c +++ b/test/Lucy/Test/Search/TestPhraseQuery.c @@ -22,6 +22,7 @@ #include "Clownfish/TestHarness/TestBatchRunner.h" #include "Lucy/Test.h" #include "Lucy/Test/TestUtils.h" +#include "Lucy/Test/Search/MockSearcher.h" #include "Lucy/Test/Search/TestPhraseQuery.h" #include "Lucy/Search/PhraseQuery.h" #include "Lucy/Util/Freezer.h" @@ -44,10 +45,22 @@ test_Dump_And_Load(TestBatchRunner *runner) { DECREF(twin); } +static void +test_freeze_thaw_compiler(TestBatchRunner *runner) { + PhraseQuery *query + = TestUtils_make_phrase_query("content", "a", "b", "c", NULL); + Searcher *searcher = (Searcher*)MockSearcher_new(); + PhraseCompiler *compiler = PhraseCompiler_new(query, searcher, 433.0f); + TestUtils_test_freeze_thaw(runner, (Obj*)compiler, "compiler"); + DECREF(searcher); + DECREF(query); +} + void TestPhraseQuery_Run_IMP(TestPhraseQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 1); + TestBatchRunner_Plan(runner, (TestBatch*)self, 2); test_Dump_And_Load(runner); + test_freeze_thaw_compiler(runner); } diff --git a/test/Lucy/Test/Search/TestPolyQuery.c b/test/Lucy/Test/Search/TestPolyQuery.c index 67fe6fa78..ddc0cff8f 100644 --- a/test/Lucy/Test/Search/TestPolyQuery.c +++ b/test/Lucy/Test/Search/TestPolyQuery.c @@ -22,11 +22,13 @@ #include "Clownfish/TestHarness/TestBatchRunner.h" #include "Lucy/Test.h" #include "Lucy/Test/TestUtils.h" +#include "Lucy/Test/Search/MockSearcher.h" #include "Lucy/Test/Search/TestPolyQuery.h" #include "Lucy/Search/ANDQuery.h" #include "Lucy/Search/ORQuery.h" #include "Lucy/Search/PolyQuery.h" #include "Lucy/Search/LeafQuery.h" +#include "Lucy/Search/TermQuery.h" #include "Lucy/Util/Freezer.h" TestANDQuery* @@ -78,16 +80,32 @@ test_Dump_Load_and_Equals(TestBatchRunner *runner, uint32_t boolop) { DECREF(clone); } +static void +test_freeze_thaw_compiler(TestBatchRunner *runner, uint32_t boolop) { + String *field = SSTR_WRAP_C("content"); + PolyQuery *query = TestUtils_make_poly_query(boolop, + TermQuery_new(field, (Obj*)SSTR_WRAP_C("a")), + TermQuery_new(field, (Obj*)SSTR_WRAP_C("b")), + NULL); + Searcher *searcher = (Searcher*)MockSearcher_new(); + Compiler *compiler = PolyQuery_Make_Root_Compiler(query, searcher); + TestUtils_test_freeze_thaw(runner, (Obj*)compiler, "compiler"); + DECREF(searcher); + DECREF(query); +} + void TestANDQuery_Run_IMP(TestANDQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 4); + TestBatchRunner_Plan(runner, (TestBatch*)self, 5); test_Dump_Load_and_Equals(runner, BOOLOP_AND); + test_freeze_thaw_compiler(runner, BOOLOP_AND); } void TestORQuery_Run_IMP(TestORQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 4); + TestBatchRunner_Plan(runner, (TestBatch*)self, 5); test_Dump_Load_and_Equals(runner, BOOLOP_OR); + test_freeze_thaw_compiler(runner, BOOLOP_OR); } diff --git a/test/Lucy/Test/Search/TestRangeQuery.c b/test/Lucy/Test/Search/TestRangeQuery.c index ab8a9cacd..965126e35 100644 --- a/test/Lucy/Test/Search/TestRangeQuery.c +++ b/test/Lucy/Test/Search/TestRangeQuery.c @@ -65,11 +65,20 @@ test_Dump_Load_and_Equals(TestBatchRunner *runner) { DECREF(clone); } +static void +test_freeze_thaw_compiler(TestBatchRunner *runner) { + RangeQuery *query + = TestUtils_make_range_query("content", "a", "b", true, true); + RangeCompiler *compiler = RangeCompiler_new(query, 672.0f); + TestUtils_test_freeze_thaw(runner, (Obj*)compiler, "compiler"); + DECREF(query); +} void TestRangeQuery_Run_IMP(TestRangeQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 5); + TestBatchRunner_Plan(runner, (TestBatch*)self, 6); test_Dump_Load_and_Equals(runner); + test_freeze_thaw_compiler(runner); } diff --git a/test/Lucy/Test/Search/TestReqOptQuery.c b/test/Lucy/Test/Search/TestReqOptQuery.c index 404e9877e..5bfcf0332 100644 --- a/test/Lucy/Test/Search/TestReqOptQuery.c +++ b/test/Lucy/Test/Search/TestReqOptQuery.c @@ -22,9 +22,11 @@ #include "Clownfish/TestHarness/TestBatchRunner.h" #include "Lucy/Test.h" #include "Lucy/Test/TestUtils.h" +#include "Lucy/Test/Search/MockSearcher.h" #include "Lucy/Test/Search/TestReqOptQuery.h" #include "Lucy/Search/RequiredOptionalQuery.h" #include "Lucy/Search/LeafQuery.h" +#include "Lucy/Search/TermQuery.h" #include "Lucy/Util/Freezer.h" TestReqOptQuery* @@ -64,10 +66,27 @@ test_Dump_Load_and_Equals(TestBatchRunner *runner) { DECREF(clone); } +static void +test_freeze_thaw_compiler(TestBatchRunner *runner) { + String *field = SSTR_WRAP_C("content"); + TermQuery *req = TermQuery_new(field, (Obj*)SSTR_WRAP_C("a")); + TermQuery *opt = TermQuery_new(field, (Obj*)SSTR_WRAP_C("b")); + RequiredOptionalQuery *query = ReqOptQuery_new((Query*)req, (Query*)opt); + Searcher *searcher = (Searcher*)MockSearcher_new(); + RequiredOptionalCompiler *compiler + = ReqOptCompiler_new(query, searcher, 921.0f); + TestUtils_test_freeze_thaw(runner, (Obj*)compiler, "compiler"); + DECREF(searcher); + DECREF(query); + DECREF(opt); + DECREF(req); +} + void TestReqOptQuery_Run_IMP(TestReqOptQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 4); + TestBatchRunner_Plan(runner, (TestBatch*)self, 5); test_Dump_Load_and_Equals(runner); + test_freeze_thaw_compiler(runner); } diff --git a/test/Lucy/Test/Search/TestTermQuery.c b/test/Lucy/Test/Search/TestTermQuery.c index a3309136c..16a60301e 100644 --- a/test/Lucy/Test/Search/TestTermQuery.c +++ b/test/Lucy/Test/Search/TestTermQuery.c @@ -21,6 +21,7 @@ #include "Clownfish/TestHarness/TestBatchRunner.h" #include "Lucy/Test.h" +#include "Lucy/Test/Search/MockSearcher.h" #include "Lucy/Test/Search/TestTermQuery.h" #include "Lucy/Test/TestUtils.h" #include "Lucy/Search/TermQuery.h" @@ -57,10 +58,21 @@ test_Dump_Load_and_Equals(TestBatchRunner *runner) { DECREF(clone); } +static void +test_freeze_thaw_compiler(TestBatchRunner *runner) { + TermQuery *query = TestUtils_make_term_query("content", "foo"); + Searcher *searcher = (Searcher*)MockSearcher_new(); + TermCompiler *compiler = TermCompiler_new(query, searcher, 433.0f); + TestUtils_test_freeze_thaw(runner, (Obj*)compiler, "compiler"); + DECREF(searcher); + DECREF(query); +} + void TestTermQuery_Run_IMP(TestTermQuery *self, TestBatchRunner *runner) { - TestBatchRunner_Plan(runner, (TestBatch*)self, 4); + TestBatchRunner_Plan(runner, (TestBatch*)self, 5); test_Dump_Load_and_Equals(runner); + test_freeze_thaw_compiler(runner); } diff --git a/test/Lucy/Test/TestUtils.c b/test/Lucy/Test/TestUtils.c index 614e84c01..7e64367fc 100644 --- a/test/Lucy/Test/TestUtils.c +++ b/test/Lucy/Test/TestUtils.c @@ -229,3 +229,20 @@ TestUtils_modules_folder() { return NULL; } +void +TestUtils_test_freeze_thaw(TestBatchRunner *runner, Obj *obj, + const char *msg) { + RAMFile *file = RAMFile_new(NULL, false); + OutStream *outstream = OutStream_open((Obj*)file); + Freezer_freeze(obj, outstream); + OutStream_Close(outstream); + InStream *instream = InStream_open((Obj*)file); + Obj *thawed = Freezer_thaw(instream); + TEST_TRUE(runner, Obj_Equals(obj, thawed), "freeze/thaw %s", msg); + DECREF(thawed); + DECREF(instream); + DECREF(outstream); + DECREF(file); + DECREF(obj); +} + diff --git a/test/Lucy/Test/TestUtils.cfh b/test/Lucy/Test/TestUtils.cfh index 00d50c4a1..d11ed89fd 100644 --- a/test/Lucy/Test/TestUtils.cfh +++ b/test/Lucy/Test/TestUtils.cfh @@ -82,6 +82,12 @@ inert class Lucy::Test::TestUtils { */ inert incremented nullable FSFolder* modules_folder(); + + /** Test whether a freeze/thaw round trip yields an equal object. + */ + inert void + test_freeze_thaw(TestBatchRunner *runner, decremented Obj *obj, + const char *msg); } __C__ diff --git a/test/LucyX/Test/Search/TestProximityQuery.c b/test/LucyX/Test/Search/TestProximityQuery.c new file mode 100644 index 000000000..8095372d2 --- /dev/null +++ b/test/LucyX/Test/Search/TestProximityQuery.c @@ -0,0 +1,73 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define TESTLUCY_USE_SHORT_NAMES +#include "Lucy/Util/ToolSet.h" + +#include "Clownfish/TestHarness/TestBatchRunner.h" +#include "Lucy/Test/Search/MockSearcher.h" +#include "Lucy/Test/TestUtils.h" +#include "Lucy/Util/Freezer.h" +#include "LucyX/Search/ProximityQuery.h" +#include "LucyX/Test/Search/TestProximityQuery.h" + +TestProximityQuery* +TestProximityQuery_new() { + return (TestProximityQuery*)Class_Make_Obj(TESTPROXIMITYQUERY); +} + +static ProximityQuery* +S_make_proximity_query() { + Vector *terms = Vec_new(2); + Vec_Push(terms, (Obj*)Str_newf("a")); + Vec_Push(terms, (Obj*)Str_newf("b")); + ProximityQuery *query + = ProximityQuery_new(SSTR_WRAP_C("content"), terms, 4); + DECREF(terms); + return query; +} + +static void +test_Dump_And_Load(TestBatchRunner *runner) { + ProximityQuery *query = S_make_proximity_query(); + Obj *dump = (Obj*)ProximityQuery_Dump(query); + ProximityQuery *twin = (ProximityQuery*)Freezer_load(dump); + TEST_TRUE(runner, ProximityQuery_Equals(query, (Obj*)twin), + "Dump => Load round trip"); + DECREF(query); + DECREF(dump); + DECREF(twin); +} + +static void +test_freeze_thaw_compiler(TestBatchRunner *runner) { + ProximityQuery *query = S_make_proximity_query(); + Searcher *searcher = (Searcher*)MockSearcher_new(); + ProximityCompiler *compiler + = ProximityCompiler_new(query, searcher, 880.0f); + TestUtils_test_freeze_thaw(runner, (Obj*)compiler, "compiler"); + DECREF(searcher); + DECREF(query); +} + +void +TestProximityQuery_Run_IMP(TestProximityQuery *self, TestBatchRunner *runner) { + TestBatchRunner_Plan(runner, (TestBatch*)self, 2); + test_Dump_And_Load(runner); + test_freeze_thaw_compiler(runner); +} + + diff --git a/test/LucyX/Test/Search/TestProximityQuery.cfh b/test/LucyX/Test/Search/TestProximityQuery.cfh new file mode 100644 index 000000000..422e0a25b --- /dev/null +++ b/test/LucyX/Test/Search/TestProximityQuery.cfh @@ -0,0 +1,29 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +parcel TestLucy; + +class LucyX::Test::Search::TestProximityQuery + inherits Clownfish::TestHarness::TestBatch { + + inert incremented TestProximityQuery* + new(); + + void + Run(TestProximityQuery *self, TestBatchRunner *runner); +} + + From 7e7972804f8a6610d25bee7a523eb60720be20de Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Tue, 21 Mar 2017 12:42:55 +0100 Subject: [PATCH 7/8] Port Filter and 800-stack.t to new Compiler API --- perl/lib/LucyX/Search/Filter.pm | 9 +++++---- perl/t/binding/800-stack.t | 3 +-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/perl/lib/LucyX/Search/Filter.pm b/perl/lib/LucyX/Search/Filter.pm index 84248db0f..26efe342e 100644 --- a/perl/lib/LucyX/Search/Filter.pm +++ b/perl/lib/LucyX/Search/Filter.pm @@ -52,7 +52,7 @@ sub DESTROY { sub make_compiler { my ( $self, %args ) = @_; - return LucyX::Search::FilterCompiler->new( %args, parent => $self ); + return LucyX::Search::FilterCompiler->new( query => $self ); } sub serialize { @@ -169,14 +169,15 @@ BEGIN { our @ISA = qw( Lucy::Search::Compiler ) } sub new { my ( $class, %args ) = @_; - $args{similarity} ||= $args{searcher}->get_schema->get_similarity; - return $class->SUPER::new(%args); + my $self = $class->SUPER::new; + $self->{query} = $args{query}; + return $self; } sub make_matcher { my ( $self, %args ) = @_; my $seg_reader = $args{reader}; - my $bits = $self->get_parent->_bits($seg_reader); + my $bits = $self->{query}->_bits($seg_reader); return LucyX::Search::FilterMatcher->new( bits => $bits, doc_max => $seg_reader->doc_max, diff --git a/perl/t/binding/800-stack.t b/perl/t/binding/800-stack.t index 3bda4f41c..a23364a32 100644 --- a/perl/t/binding/800-stack.t +++ b/perl/t/binding/800-stack.t @@ -23,8 +23,7 @@ package MyQuery; use base qw( Lucy::Search::Query ); sub make_compiler { - my ( $self, %args ) = @_; - return MyCompiler->new( %args, parent => $self ); + return MyCompiler->new; } package MyCompiler; From b0aad8cbb45c965f701bbe0a7cb1b13f974d1853 Mon Sep 17 00:00:00 2001 From: Nick Wellnhofer Date: Sun, 16 Apr 2017 13:54:52 +0200 Subject: [PATCH 8/8] Add test for old query/compiler API --- core/Lucy/Search/TermQuery.c | 5 ++ core/Lucy/Search/TermQuery.cfh | 5 ++ perl/t/binding/802-old_query_api.t | 90 ++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 perl/t/binding/802-old_query_api.t diff --git a/core/Lucy/Search/TermQuery.c b/core/Lucy/Search/TermQuery.c index 54d78dad4..b19afcf1a 100644 --- a/core/Lucy/Search/TermQuery.c +++ b/core/Lucy/Search/TermQuery.c @@ -235,6 +235,11 @@ TermCompiler_Sum_Of_Squared_Weights_IMP(TermCompiler *self) { return ivars->raw_weight * ivars->raw_weight; } +float +TermCompiler_Get_Weight_IMP(TermCompiler *self) { + return TermCompiler_IVARS(self)->normalized_weight; +} + void TermCompiler_Apply_Norm_Factor_IMP(TermCompiler *self, float query_norm_factor) { diff --git a/core/Lucy/Search/TermQuery.cfh b/core/Lucy/Search/TermQuery.cfh index 268cdea6b..2674e5bed 100644 --- a/core/Lucy/Search/TermQuery.cfh +++ b/core/Lucy/Search/TermQuery.cfh @@ -100,6 +100,11 @@ class Lucy::Search::TermCompiler inherits Lucy::Search::Compiler { public float Sum_Of_Squared_Weights(TermCompiler *self); + /** Test-only. + */ + float + Get_Weight(TermCompiler *self); + public void Apply_Norm_Factor(TermCompiler *self, float factor); diff --git a/perl/t/binding/802-old_query_api.t b/perl/t/binding/802-old_query_api.t new file mode 100644 index 000000000..523c360c2 --- /dev/null +++ b/perl/t/binding/802-old_query_api.t @@ -0,0 +1,90 @@ +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +use strict; +use warnings; + +package MockSearcher; +use base qw( Lucy::Search::Searcher ); + +sub doc_max { 100 } +sub doc_freq { 1 } + +package MyQuery; +use base qw( Lucy::Search::Query ); + +our $subordinate_arg; + +sub make_compiler { + my ( $self, %args ) = @_; + $subordinate_arg = delete($args{subordinate}); + return MyCompiler->new( %args, parent => $self ); +} + +package MyCompiler; +use base qw( Lucy::Search::Compiler ); + +our $similarity_arg; + +sub new { + my ( $self, %args ) = @_; + return $self->SUPER::new(%args); +} + +sub _normalize { + my ( $self, $sim ) = @_; + $similarity_arg = $sim; +} + +package QueryWithoutMakeCompiler; +use base qw( Lucy::Search::Query ); + +package main; +use Test::More tests => 8; + +my $schema = Lucy::Plan::Schema->new; +my $sim = $schema->get_similarity; +my $searcher = MockSearcher->new( schema => $schema ); +my $query; +my $compiler; + +$query = MyQuery->new; +$query->set_boost(123.0); +$compiler = $query->make_root_compiler($searcher); +ok( $MyQuery::subordinate_arg, "make_compiler receives true subordinate arg" ); + +is( $compiler->get_boost, 123.0, "get_boost" ); +is( $compiler->get_weight, 123.0, "get_weight" ); +is( ${ $compiler->get_parent }, $$query, "get_parent" ); +is( ${ $compiler->get_similarity }, $$sim, "get_similarity" ); + +$MyCompiler::similarity_arg = undef; +$compiler->normalize; +is( $$MyCompiler::similarity_arg, $$sim, "normalize without sim" ); + +eval { + QueryWithoutMakeCompiler->new->make_root_compiler($searcher); +}; +like( $@, qr('Make_Compiler' not defined by QueryWithoutMakeCompiler), + "Subclassing Query without overriding make_compiler throws" ); + +$query = Lucy::Search::TermQuery->new( field => 'content', term => 'foo' ); +$compiler = $query->make_compiler( + searcher => $searcher, + boost => 64.0, +); +# normalized_weight == idf == 1 + log(100 / (1 + 1)) +ok( $compiler->get_weight > 1, "make_compiler normalizes Compiler" ); +