मेरे पास एक परिदृश्य है जहां मुझे इनपुट के रूप में एक SQL क्वेरी और SQL तर्क (SQL इंजेक्शन से बचने के लिए) मिल रहा है।

और मैं नीचे दिए गए कोड का उपयोग करके वोल्टडीबी की AdHoc संग्रहीत प्रक्रिया का उपयोग कर एसक्यूएल चला रहा हूं।

private static final String voltdbServer = "localhost";
private static final int voltdbPort = 21212;

public ClientResponse runAdHoc(String sql, Object... sqlArgs) throws IOException, ProcCallException
{
    ClientConfig clientConfig = new ClientConfig();
    Client voltdbClient = ClientFactory.createClient(clientConfig);
    voltdbClient.createConnection(voltdbServer, voltdbPort);

    return  voltdbClient.callProcedure("@AdHoc", sql, sqlArgs);
}

लेकिन मुझे एक त्रुटि मिलती है org.voltdb.client.ProcCallException: SQL error while compiling query: Incorrect number of parameters passed: expected 2, passed 1

runAdHoc("select * from table where column1 = ? and column2 = ?", "column1", "column2") के लिए, जब दो या अधिक पैरामीटर हों।

और मुझे त्रुटि मिलती है org.voltdb.client.ProcCallException: Unable to execute adhoc sql statement(s): Array / Scalar parameter mismatch ([Ljava.lang.String; to java.lang.String)

runAdHoc("select * from table where column1 = ?", "column1"); के लिए, जब केवल एक पैरामीटर हो।

लेकिन जब मैं सीधे voltdbClient.callProcedure("@AdHoc", "select * from table where column1 = ? and column2 = ?", "column1", "column2") को कॉल करता हूं तो मुझे इस समस्या का सामना नहीं करना पड़ता है

मुझे लगता है कि वोल्टडीबी sqlArgs को अलग पैरामीटर के रूप में मानने में सक्षम नहीं है, यह उन्हें एक सरणी के रूप में मान रहा है।

इस समस्या को हल करने का एक तरीका स्वयं SQL स्ट्रिंग को पार्स करना और फिर उसे पास करना है, लेकिन मैं इस समस्या को हल करने के प्रभावी तरीके को जानने के लिए इसे पोस्ट कर रहा हूं।

नोट:- प्रयुक्त SQL केवल एक परीक्षण SQL है

0
Naresh Joshi 9 जुलाई 2019, 14:02

2 जवाब

सबसे बढ़िया उत्तर

मैंने वही प्रश्न वोल्टडीबी पब्लिक स्लैक चैनल पर पोस्ट किया और एक प्रतिक्रिया मिली जिसने समस्या को हल किया जो इस प्रकार है:

संक्षिप्त व्याख्या यह है कि आपके पैरामीटर @Adhoc को [sql, sqlArgs] में बदल दिया जा रहा है, जब उन्हें [sql, sqlArg1, sqlArg2, …] होना चाहिए। आपको एक नई सरणी बनानी होगी जो sqlArgs.length + 1 है, sql को स्थिति 0 पर रखें, और sqlArgs को स्थिति 1 से शुरू होने वाले नए सरणी में कॉपी करें। फिर उस नवनिर्मित सरणी को पास करें client.callProcedure("@AdHoc", newArray) को कॉल करें

इसलिए मैंने अपनी runAdHoc विधि को नीचे की तरह संशोधित किया और इसने इस समस्या को हल कर दिया

public ClientResponse runAdHoc(String sql, Object... sqlArgs) throws IOException, ProcCallException
{
    ClientConfig clientConfig = new ClientConfig();
    Client voltdbClient = ClientFactory.createClient(clientConfig);
    voltdbClient.createConnection(voltdbServer, voltdbPort);

    Object[] procArgs;
    if (sqlArgs == null || sqlArgs.length == 0)
    {
        procArgs = new Object[1];
    } else
    {
        procArgs = new Object[sqlArgs.length + 1];
        System.arraycopy(sqlArgs, 0, procArgs, 1, sqlArgs.length);
    }

    procArgs[0] = sql;

    return  voltdbClient.callProcedure("@AdHoc", procArgs);
}
0
Naresh Joshi 10 जुलाई 2019, 11:40

@Adhoc सिस्टम प्रक्रिया सरणी को एक पैरामीटर के रूप में पहचान रही है। इस तरह की बात @Adhoc के साथ होती है क्योंकि प्रक्रिया की कोई योजना नहीं है जहां कोई स्पष्ट रूप से बता सके कि प्रत्येक पैरामीटर क्या है।

आपके पास sqlArgs सरणी को अलग-अलग पास करने के लिए वास्तविक पैरामीटर में पार्स करने के बारे में सही विचार है। आप इन अलग-अलग मापदंडों को SQL स्टेटमेंट में ही जोड़ सकते हैं। इस तरह, आपका तदर्थ कथन बस होगा:

voltdbClient.callProcedure("@AdHoc", sql)

पूर्ण प्रकटीकरण: मैं वोल्टडीबी में काम करता हूं।

1
Andrew 9 जुलाई 2019, 17:59