你好,
因此,我有一段相當複雜的 JMP 腳本,它以一種看起來很奇怪的方式失敗,我想了解原因。在開始討論之前,我對這裡的複雜性表示歉意。
我寫了一個名為 sql_lib.jsl 的函式庫,它定義了命名空間「sql_lib」。在該命名空間中,我定義了一個名為「sql_lib:QueryBatchService」的類別 clsQueryBatch。這個類別的目的是使多個 SQL 查詢能夠輕鬆地批次以同時在後台運行。這個想法是,當實例化一個 sql_lib:QueryBatchService 類型的物件時,可以向該物件新增查詢,然後呼叫類別方法 run_queries() 來啟動所有查詢,最後使用類別方法 get_results 取得所有查詢的結果()。此類別的完整實作並不真正相關,但我的方法如下:該類別的 _ init _() 方法根據傳遞的參數設定一些成員變量,例如要使用的資料庫會話和所需的可見性結果表的級別,重要的是,它還創建了一個匿名命名空間this:m_ns ,我在其中儲存和檢索查詢結果以及已完成/錯誤查詢的數量。 _ init _ 方法如下所示(注意,我還為資料庫連接建立了一個包裝類,名為sql_lib:DBSession,其目的是為每個資料庫連接提供一個名稱,以便我可以輕鬆追蹤和重複使用同一連線進行多個查詢,出現錯誤時重新連線):
_init_ = Method({
db_session,
visibility = 1
},
If(! (db_session<<GETNAME></GETNAME>
Once the object is instantiated, I add queries to the queue with add_query():
<CODE class=" language-jsl">add_query = Method({query_str,query_name},
If(!IsString(query_str),
Write("clsQueryBatch:add_query requires an SQL query string as a parameter.\!N");
Throw();
);
query = NewSQLQuery(Connection(m_dbc), CustomSQL(query_str));
query << Query Name(query_name);
m_queries[query_name]=query;
m_ns:total++;
);
And I can then launch all queued queries with run_queries(). This is where the weirdness happens. You’ll notice that I’ve created an Associative Array variable in the anonymous m_ns namespace called results. This should be available as m_ns:results, and I take advantage of this by wrapping the code that runs the queries in Eval(EvalExpr()) and injecting the m_ns_name member variable as an expression into the OnRunComplete method of the RunBackground message sent to each query. I recently changed m_ns:results from a List to an Associative Array because I needed to be able to ensure that I could track down multiple differently named result tables. When I was using a list to track the results, this code worked fine, but when I try to assign a value into the Associative Array, I get the error “Not subscriptable value in access or evaluation of 'Assign' , ns:results[key] = /*###*/queryResult/*###*/“. Preamble completed, here’s the code for run_queries():
<CODE class=" language-jsl">run_queries = Method({},
If(m_visibility==1,
ForEach({{query_name,query},idx}, m_queries,
Eval(
EvalExpr(
query << RunBackground(
OnRunComplete(
Write("Query complete.\!N");
ns = Namespace(Expr(m_ns_name));
key = Eval(Expr(query_name));
Show(ns:results,Type(ns:results),key,queryResult);
ns:results[key] = queryResult;
ns:complete++;
),
OnRunCanceled(
Write("Query cancelled.\!N");
ns = Namespace(Expr(m_ns_name));
ns:error++;
),
OnError(
Write("Query failed!\!N");
ns = Namespace(Expr(m_ns_name));
ns:error++;
)
)
)
)
)
, //else
ForEach({{query_name,query},idx}, m_queries,
Eval(
EvalExpr(
query << RunBackground(
OnRunComplete(
ns = Namespace(Expr(m_ns_name));
key = Eval(Expr(query_name));
Show(ns:results,Type(ns:results),key,queryResult);
ns:results[key] = queryResult;
ns:complete++;
),
Invisible,
OnRunCanceled(
Write("Query cancelled.\!N");
ns = Namespace(Expr(m_ns_name));
ns:error++;
),
OnError(
ns = Namespace(Expr(m_ns_name));
Write("Query failed!\!N");
ns:error++;
)
)
)
)
)
)
);
As you can see, I’ve put a few Show() statements in here to try to understand what’s happening. The results of those are what prompts my question. Please also note that the query runs and generates a data table as expected, the problem arises when I try to store a reference to that data table for later use.
<CODE class=" language-jsl">Show(ns:results,Type(ns:results),key,queryResult);
puts this in the log:
<CODE class=" language-jsl">ns:results = [=>];
Type(ns:results) = "Associative Array";
key = "subid_temp_table_data";
queryResult = DataTable("subid_temp_table_data");so clearly the namespace is resolving correctly, and the type of ns:results is Associative array, and key is a string, queryResult is a datatable, but for some reason I am unable to create a new key=>value pair in the ns:results AA. Remember, this worked when ns:results was a list and I used Insert Into(ns:results, queryResult). Is there a difference in the memory context for lists and associative arrays that I’m violating in some way here? Usually in the past when calling RunBackground and using the OnRunComplete context, I’ve used a global variable to hold the results of the query, is this an issue with my nested namespace:class:namespace structure? Any insight you can provide would be greatly appreciated.
感謝 JMP 支援的 Jasean,事實證明發生此錯誤是因為當我初始化結果關聯數組時,我使用了 AssociativeArray() 函數。將其更改為使用 [=>] 符號反而解決了我的問題。
當您呼叫 AssociativeArray() 時,它顯然會返回建構函數對象,因此每當我實例化一個新物件時,關聯數組就會被覆寫。透過靜態地將成員變數分配為 [=>] 對象,它不會被覆蓋,至少這是我從@Jasean的電子郵件中得到的啟示,也許他可以提供更多的啟示。