स्थानीय कैलेंडर के साथ काम करने के लिए SQLite सीखें।
भाग 1 - अंग्रेजी संस्करण ,
भाग 2

हाल ही में, मैंने iOS के लिए साइट ट्रैफ़िक का विश्लेषण करने के लिए एक iOS एप्लिकेशन को पोर्ट (अधिक सटीक रूप से, फिर से लिखना) किया। चूंकि डेटा रिलेशनल मॉडल में फिट होता है, इसलिए हमने SQLite का उपयोग करने का निर्णय लिया। जहां तक मुझे पता है, आईओएस के लिए बस कोई अन्य रिलेशनल डीबीएमएस नहीं हैं।
कितना लंबा, कितना छोटा ... यह एक निश्चित तिथि सीमा के लिए साप्ताहिक दक्षता की गणना करने का समय है।
तो, हमारे पास एक तालिका है जिसमें उपयोगी और खर्च किए गए कार्यों के मूल्य हैं, साथ ही साथ इस काम के पूरा होने की तारीख भी है। तालिका की संरचना एसक्यूएल में निम्नानुसार वर्णित है:
CREATE TABLE [ Usage ]
(
[FacetId] VARCHAR , -- ""
[ Value ] INTEGER , -- ""
[Visits ] INTEGER , -- ""
[ Date ] DATETIME --
);
* This source code was highlighted with Source Code Highlighter .
प्रत्येक सप्ताह की दक्षता की गणना करने के लिए कुछ तिथि सीमा के लिए यह आवश्यक है। ठीक है, एक अनुरोध लिखा है
SELECT SUM ( Value ) / SUM ( Visits ),
strftime( '%Y-%W' , Date ) AS week
FROM Usage
WHERE Date BETWEEN @startDate AND @endDate
GROUP BY week
ORDER BY week;
* This source code was highlighted with Source Code Highlighter .
हालांकि, किसी कारण से, परिणाम संदर्भ कार्यान्वयन से सहमत नहीं थे। यह निम्नलिखित निकला। SQLite का मानना है कि सप्ताह सोमवार से शुरू होता है। जबकि संदर्भ कार्यान्वयन रविवार को सप्ताह की शुरुआत के रूप में मानता है जैसा कि यूएसए में प्रथागत है।
sqlite> SELECT strftime( '%Y-%W' , '2011-01-02' );
2011-01 ## 2011-02
sqlite> SELECT strftime( '%Y-%W' , '2011-01-01' );
2011-01
* This source code was highlighted with Source Code Highlighter .
मुझे DBMS लोकेल को निर्दिष्ट करने के लिए बाध्य करने का कोई तरीका नहीं मिला। मैं वास्तव में कई में एक सुंदर अनुरोध को तोड़ना नहीं चाहता था। इसके अलावा, मैंने SQLite को sqlite3_create_function का उपयोग करके फ़ंक्शन को जोड़ने की क्षमता की खोज की।
हां, मैंने वरीयता और शिष्टाचार के साथ तारीखों को प्रारूपित करने के लिए अपना खुद का विकल्प लिखने का फैसला किया। यह अनुरोध से पास किए गए लोकेल को ध्यान में रखने की क्षमता से अलग होगा।
इस समाधान के लाभ स्पष्ट हैं:
- हम SQL के भीतर रहते हैं
- ऑब्जेक्टिव-सी में अतिरिक्त लूप लिखने की आवश्यकता नहीं है
- हमें संभावित रूप से तेज क्वेरी निष्पादन मिलता है
- और सबसे महत्वपूर्ण बात - यह समाधान पुन: उपयोग के लिए डिज़ाइन किया गया है
तो चलिए शुरू करते हैं। हम खुद को ग्रेगोरियन कैलेंडर तक सीमित करके समस्या के बयान को सरल बनाते हैं।
SQLite एक्सटेंशन फ़ंक्शन में मुख्य () फ़ंक्शन के समान एक हस्ताक्षर है।
void ObjcFormatAnsiDateUsingLocale( sqlite3_context* ctx_, int argc_,sqlite3_value** argv_ );
* This source code was highlighted with Source Code Highlighter .
अंतर यह है कि इसमें रिटर्न फ्लैग नहीं है। इसके बजाय, डेटाबेस संदर्भ जिसमें से इसे बुलाया गया था, इसे पास कर दिया गया है। इस संदर्भ का उपयोग परिणाम या त्रुटि को वापस करने के लिए किया जाता है।
एक SQL क्वेरी में, फ़ंक्शन एक उद्देश्य-सी-शैली तिथि प्रारूप लेगा, वास्तव में, दिनांक और स्थान। यह अनुरोध सही रूप से 2011-01-02 को 2011 के दूसरे सप्ताह तक विशेषता देगा क्योंकि यह अमेरिकी क्षेत्रों में होना चाहिए।
sqlite> SELECT ObjcFormatAnsiDateUsingLocale( 'YYYY-ww' , '2011-01-02' , 'en_US' );
2011-02
* This source code was highlighted with Source Code Highlighter .
इस प्रकार, हमें 4 चीजें करने की आवश्यकता है:
- SQLite में एक फ़ंक्शन रजिस्टर करें ताकि इसे प्रश्नों में उपयोग किया जा सके।
- मापदंडों को argv_ से फाउंडेशन के प्रकारों में परिवर्तित करें। हमारे मामले में, यह क्रमशः [NSString, NSDate, NSString] होगा।
- NSDateFormatter का उपयोग करके प्रारूप तिथि
- वापसी का परिणाम
==============
0. SQLite फ़ंक्शन पंजीकृत करें
यह sqlite3_create_function का उपयोग करके किया जाता है।
www.sqlite.org/c3ref/create_function.htmlsqlite3_create_function
(
db_, // HANDLE , sqlite3_open
"ObjcFormatAnsiDateUsingLocale" , //
3, // . SQLite
SQLITE_UTF8, // iOS
NULL,
&ObjcFormatAnsiDateUsingLocale, //
NULL, NULL // . .
);
* This source code was highlighted with Source Code Highlighter .
-
1. मापदंडों का रूपांतरण
SQLite स्वतंत्र रूप से जांचता है कि मापदंडों की संख्या मेल खाती है या नहीं। हालाँकि, मेरा सुझाव है कि आप केवल मामले में argc को चेक छोड़ दें।
चूंकि SQLite स्वयं पैरामीटर संसाधनों को मुक्त करेगा, इसलिए NSString-> initWithBytesNoCopy: लंबाई: एन्कोडिंग: freeWhenDone कंस्ट्रक्टर का उपयोग करना बेहतर है:
-
2. दिनांक स्वरूपण
पहली नज़र में, सब कुछ सरल है।
inputFormatter_.dateFormat = @"yyyy-MM-dd" ;
NSDate* date_ = [ inputFormatter_ dateFromString: strDate_ ];
targetFormatter_.dateFormat = format_;
return [ targetFormatter_ stringFromDate: date_ ];
* This source code was highlighted with Source Code Highlighter .
हालांकि, कुछ बारीकियां हैं।
- जैसा कि आप जानते हैं, NSLocale क्लास का एक उदाहरण NSCalendar ऑब्जेक्ट और NSDateFormatter दोनों में समाहित है।
यह बहुत महत्वपूर्ण है कि हालत "NSDateFormatter.calendar.locale == NSDateFormatter.locale" से मिलती है।

- inputFormatter_ का स्थान "en_US_POSIX" होना चाहिए
- SQLite स्टोर ANSI प्रारूप @ "yyyy-MM-dd" में हैं। इसे inputFormatter_ के लिए सेट किया जाना चाहिए
- NSDateFormatter बनाना एक बहुत महंगा ऑपरेशन है। उसे फिर से न बुलाने की कोशिश करें
-
3. परिणाम लौटना
इन उद्देश्यों के लिए, sqlite3_result_text फ़ंक्शन का उपयोग किया जाता है। SQLITE_TRANSIENT विकल्प का उपयोग करना महत्वपूर्ण है ताकि SQLite फाउंडेशन फ्रेमवर्क में आवंटित संसाधनों की एक प्रति बना सके।
==============
वह, वास्तव में, सब है। गणना में जुटे।
स्रोत कोड
github प्रोजेक्ट पेज पर उपलब्ध है
- dodikk / ESLocaleकोड समीक्षा और पुल अनुरोध का स्वागत है।
मुझे आशा है कि मेरा कार्य किसी के लिए उपयोगी है।
फिर मैं अपनी छुट्टी ले लेता हूं।