2016-10-03 60 views
0

我試圖實現一個表值函數(作爲一個SQLite虛擬表)。xBestIndex故障(將非文字參數傳遞給表值函數)

這是一個函數,它會接受一個字符串並返回一個包含字符串中所有單詞的表。

如果我用下面的文字值調用它,它可以正常工作。

SELECT word FROM splitstring("abc def ghi") 

但是,如果我與另一個表中的列調用它,它不工作:

SELECT a.Name, word FROM article a, splitstring(a.Text) 

的xBestIndex方法被調用的所有權利,但權之後,我得到一個異常從ExecuteReader方法。異常消息是「xBestIndex故障」。由於例外,xFilter方法不會被調用。

我xBestIndex實現簡單,它只是標誌着參數,以便我可以看到它在xFilter:

public override SQLiteErrorCode BestIndex(SQLiteVirtualTable table, SQLiteIndex index) 
{ 
    index.Outputs.ConstraintUsages.ElementAt(0).argvIndex = 1; 
    index.Outputs.ConstraintUsages.ElementAt(0).omit = 1; 

    return SQLiteErrorCode.Ok; 
} 

難道我做錯了或者是它不可能通過非字面參數表值功能?

+0

表值函數在表連接之前執行,所以此查詢沒有意義。 –

+0

它讓我覺得可能是這樣,但事實並非如此。它爲table1的每一行執行一次。該表值函數語法只是語法suggar,這是寫這個查詢(這將導致相同的異常)的另一種方式: 選擇 \t a.Name,s.word FROM \t文章一 \t內在s.phrase = a.Text上加入splitstring – anakic

回答

0

發現問題!我使用的約束有usable=0。 SQLite會多次調用BestIndex方法,第二次使用不可用的約束。

這是BestIndex方法的固定主體。

public override SQLiteErrorCode BestIndex(SQLiteVirtualTable table, SQLiteIndex index) 
{ 
    if (index.Inputs.Constraints.Count() != 2) 
     throw new ArgumentException("The generate_series function requires two integer (long) parameters!"); 

    if (index.Inputs.Constraints.All(c=>c.usable == 1)) 
    { 
     index.Outputs.ConstraintUsages.ElementAt(0).argvIndex = 1; 
     index.Outputs.ConstraintUsages.ElementAt(0).omit = 1; 
     index.Outputs.ConstraintUsages.ElementAt(1).argvIndex = 2; 
     index.Outputs.ConstraintUsages.ElementAt(1).omit = 1; 
    } 
    else 
    { 
     index.Outputs.IndexNumber = -1; 
     index.Outputs.EstimatedCost = double.MaxValue; 
    } 

    return SQLiteErrorCode.Ok; 
} 

現在我檢查可用的標誌。當BestIndex被帶有約束的usable=0調用時,我會跳過它,即返回該索引的高估計成本,所以它不會被使用。