2017-09-21 14 views
6

में बाइटा को डबल परिशुद्धता में कनवर्ट करें मेरे पास एक डेटाबेस है जहां एक तालिका में से किसी अन्य सिस्टम से एकत्र किए गए सभी प्रकार के सामान्य डेटा का ब्लॉब (bytea) संग्रहीत करता है। bytea फ़ील्ड में कुछ भी हो सकता है। डेटा को समझने के तरीके के बारे में जानने के लिए, तालिका में एक प्रारूप फ़ील्ड भी है। मैं एक byte[] के रूप में डेटाबेस से bytea क्षेत्र को पढ़ने के लिए और उसके बाद मैं आसानी से ByteBuffer का उपयोग कर और विभिन्न दृश्य (DoubleBuffer, IntBuffer, आदि) द्वारा double[] या int[] या जो कुछ भी प्रारूप क्षेत्र कहते हैं करने के लिए इसे परिवर्तित कर सकते हैं एक जावा आवेदन में लिखा था।PostgreSQL

अब मेरे पास ऐसी स्थिति है जहां मुझे किसी अन्य तालिका के साथ ईमानदारी बनाए रखने के लिए डेटाबेस पर डेटा के कुछ हेरफेर करने की आवश्यकता है। मैं कल्पना के बारे में किसी भी प्रकार के डेटा के लिए रूपांतरण पा सकता हूं, लेकिन मुझे bytea (या यहां तक ​​कि bit) से double precision और वापस जाने के लिए कुछ भी नहीं मिल रहा है। bytea टूटा जा सकता है, बिट्स में परिवर्तित किया जा सकता है, और उसके बाद int या bigint में परिवर्तित किया जा सकता है, लेकिन double precision नहीं। उदाहरण के लिए, x'deadbeefdeadbeef'::bit(64)::bigint कोई समस्या नहीं होने पर -2401053088876216593 में परिवर्तित हो जाएगा, लेकिन x'deadbeefdeadbeef'::bit(64)::double precision-1.1885959257070704E148 के आईईईई 754 उत्तर देने के बजाय "ERROR: टाइप बिट को डबल परिशुद्धता में नहीं डाला जा सकता" के साथ विफल रहता है।

मुझे यह उत्तर https://stackoverflow.com/a/11661849/5274457 मिला, जो मूल रूप से बिट्स को दोबारा बदलने के लिए आईईईई मानक लागू करता है, लेकिन क्या ऐसा करने के लिए पोस्टग्रेएसक्यूएल में वास्तव में बुनियादी रूपांतरण फ़ंक्शन नहीं है? इसके अलावा, मुझे double precision से bytea पर पीछे की तरफ जाने की आवश्यकता है जब मैं डेटा में हेरफेर कर रहा हूं और टेबल को अपडेट करने की आवश्यकता है, जो यह उत्तर प्रदान नहीं करता है।

कोई विचार?

+0

आपको आवश्यक कलाकार जोड़ने के लिए शायद एक साधारण सी एक्सटेंशन की आवश्यकता होगी। पीजी वास्तव में कच्चे बाइनरी रूपों से/कुछ रूपांतरण कार्यों का उपयोग कर सकता है। –

+0

मैं विस्तार विचार को देखूंगा। जो मैं बता सकता हूं, यह सिर्फ एक PostgreSQL समस्या नहीं है। एचएसक्यूएल और एसक्यूएल सर्वर, जो मैं बता सकता हूं, वही समस्या है। मेरे द्वारा उपयोग की जाने वाली प्रत्येक प्रोग्रामिंग भाषा में कच्चे बाइट्स को युगल में बदलने के तरीके हैं, लेकिन SQL डेटाबेस में ऐसा प्रतीत नहीं होता है। – Keith

+0

वे आम तौर पर उच्च स्तर के अमूर्तता पर परिचालन कर रहे हैं। PostgreSQL के साथ, एक व्यावहारिक विकल्प शायद ऐसा करने के लिए एक साधारण plperlu या plpythonu प्रक्रिया का उपयोग करने के लिए है, इस तरह आप एक सी एक्सटेंशन लिखने की जरूरत नहीं है। –

उत्तर

1

ठीक है, मुझे एक जवाब मिला। PostgreSQL में, आप पायथन का उपयोग करके फ़ंक्शन लिख सकते हैं। पायथन के उपयोग को सक्षम करने के लिए, आपको PostgreSQL की स्थापना द्वारा आवश्यक पायथन के विशिष्ट संस्करण को स्थापित करना होगा और इसे पाथ पर्यावरण चर में उपलब्ध होना होगा। इंस्टॉलेशन नोट्स को देखकर आप पाइथन का कौन सा संस्करण पोस्टग्रेएसक्यूएल की स्थापना की आवश्यकता को पा सकते हैं। मैं वर्तमान में विंडोज पर PostgreSQL 9.6.5 का उपयोग कर रहा हूं और यह पायथन 3.3 के लिए कॉल करता है। मैंने शुरुआत में नवीनतम पायथन 3.6 की कोशिश की, लेकिन यह काम नहीं करेगा। मैं विंडोज के लिए नवीनतम पायथन 3.3 के साथ बस गया, जो 3.3.5 है।

पायथन स्थापित करने के बाद, आप इसे पर दस्तावेज़ के रूप में अपने डेटाबेस पर CREATE EXTENSION plpython3u; निष्पादित करके PostgreSQL में सक्षम करते हैं। वहां से, आप पाइथन निकायों के साथ कोई भी फ़ंक्शन लिख सकते हैं।

मेरी विशेष मामले bytea से double precision[] करने के लिए और वापस, मैंने लिखा निम्नलिखित कार्यों में परिवर्तित करने के लिए:

CREATE FUNCTION bytea_to_double_array(b bytea) 
    RETURNS double precision[] 
    LANGUAGE 'plpython3u' 
AS $BODY$ 
    if 'struct' in GD: 
    struct = GD['struct'] 
    else: 
    import struct 
    GD['struct'] = struct 

    return struct.unpack('<' + str(int(len(b)/8)) + 'd', b) 
$BODY$; 

CREATE FUNCTION double_array_to_bytea(dblarray double precision[]) 
    RETURNS bytea 
    LANGUAGE 'plpython3u' 
AS $BODY$ 
    if 'struct' in GD: 
    struct = GD['struct'] 
    else: 
    import struct 
    GD['struct'] = struct 

    # dblarray here is really a list. 
    # PostgreSQL passes SQL arrays as Python lists 
    return struct.pack('<' + str(int(len(dblarray))) + 'd', *dblarray) 
$BODY$; 

मेरे मामले में, सभी युगल थोड़ा endian में जमा हो जाती है, इसलिए मैं < का उपयोग करें। मैं https://stackoverflow.com/a/15025425/5274457 में वर्णित वैश्विक शब्दकोश में struct मॉड्यूल के आयात को भी कैश करता हूं। मैंने एसडी के बजाय जीडी का इस्तेमाल किया क्योंकि मैं चाहता हूं कि आयात अन्य कार्यों में उपलब्ध हो जो मैं लिख सकता हूं। जीडी और एसडी के बारे में जानकारी के लिए, https://www.postgresql.org/docs/current/static/plpython-sharing.html देखें।

कार्रवाई में यह देखने के लिए मेरी डेटाबेस में धब्बे जानते हुए भी थोड़ा endian के रूप में जमा हो जाती है,

SELECT bytea_to_double_array(decode('efbeaddeefbeadde', 'hex')), encode(double_array_to_bytea(array[-1.1885959257070704E148]), 'hex'); 

और जवाब मैं

bytea_to_double_array | encode 
double precision[]  | text 
-------------------------+------------------ 
{-1.18859592570707e+148} | efbeaddeefbeadde 

जहां 'efbeaddeefbeadde' थोड़ा endian में 'deadbeefdeadbeef' है।

+0

अच्छी तरह से किया, धन्यवाद :) –