‏הצגת רשומות עם תוויות MS SQL. הצג את כל הרשומות
‏הצגת רשומות עם תוויות MS SQL. הצג את כל הרשומות

יום חמישי, מאי 18, 2017

SQL 2016 for linux

בשקט בשקט , בסיס הנתונים שאני מחבב (לפעמים) הקרויי Microsoft SQL Server מתחיל להיות מותאם למספר הפצות :

אובנטו , סוזה ,rhel sles ונראה שאפילו משהוא חושב על דביאן

אממה , מי שארז לא ארז בצורה שווה לכולם (למשל בדביאן חסרים חבילות שיש באובנטו) , אז אם יש בקהל מי שמנהל או עובד על התיקיות האלה אנה ממך תמלא גם את החבילות של דביאן בבקשה, עשיתה עבודה מדהימה שהתאמת למספר הפצות ונראה שהתחלת עבור דביאן אבל עצרת.

עכשיו למה אנחנו צריכים MSSQL על הפצות לינוקס ? פשוט הרבה עסקים עובדים מול MSSQL והמרה של הקוד בייס שלהם לא משתלמת כלכלית. ברגע שבסיס הנתונים עובר לעבוד תחת לינוקס כולם (גם לקוחות mssql שרצים על לינוקס וגם לקוחות שרצים תחת על וינדוס ).

תוכן החבילה העיקרית הוא :

drwxr-xr-x root/root         0 2017-05-15 23:25 ./
drwxr-xr-x root/root         0 2017-05-15 23:25 ./lib/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./lib/systemd/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./lib/systemd/system/
-rw-r--r-- root/root       655 2017-05-15 23:25 ./lib/systemd/system/mssql-server.service
drwxr-xr-x root/root         0 2017-05-15 23:25 ./usr/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./usr/share/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./usr/share/man/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./usr/share/man/man1/
-rw-r--r-- root/root       778 2017-05-15 23:25 ./usr/share/man/man1/mssql-conf.1.gz
-rw-r--r-- root/root       411 2017-05-15 23:25 ./usr/share/man/man1/sqlservr.1.gz
-rw-r--r-- root/root      6731 2017-05-15 23:25 ./usr/share/man/man1/sqlpackage.1.gz
drwxr-xr-x root/root         0 2017-05-15 23:25 ./usr/share/doc/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./usr/share/doc/mssql-server/
-rw-r--r-- root/root      6231 2017-05-15 23:25 ./usr/share/doc/mssql-server/THIRDPARTYNOTICES.TXT.gz
-rw-r--r-- root/root       161 2017-05-15 23:25 ./usr/share/doc/mssql-server/changelog.Debian.gz
-rw-r--r-- root/root      4429 2017-05-15 23:25 ./usr/share/doc/mssql-server/LICENSE.TXT.gz
-rw-r--r-- root/root        37 2017-05-15 23:25 ./usr/share/doc/mssql-server/copyright
drwxr-xr-x root/root         0 2017-05-15 23:25 ./opt/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./opt/mssql/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./opt/mssql/lib/
-rw-r--r-- root/root 394530816 2017-05-15 23:25 ./opt/mssql/lib/sqlservr.sfp
-rw-r--r-- root/root    369760 2017-05-15 23:24 ./opt/mssql/lib/libunwind.so.8
drwxr-xr-x root/root         0 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/
-rwxr-xr-x root/root     92765 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/collations.txt
drwxr-xr-x root/root         0 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/
drwxr-xr-x root/root         0 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/
-rw-r--r-- root/root     15588 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-fr_FR.mo
-rw-r--r-- root/root     18933 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-ru_RU.mo
-rw-r--r-- root/root     13327 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-zh_TW.mo
-rw-r--r-- root/root       396 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-en_US.mo
-rw-r--r-- root/root     15434 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-es_ES.mo
-rw-r--r-- root/root     15378 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-ko_KR.mo
-rw-r--r-- root/root     15333 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-de_DE.mo
-rw-r--r-- root/root     13288 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-zh_CN.mo
-rw-r--r-- root/root     16272 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-ja_JP.mo
-rw-r--r-- root/root     14840 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-pt_BR.mo
-rw-r--r-- root/root     15132 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/loc/mo/mssql-conf-it_IT.mo
-rwxr-xr-x root/root      9157 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/mssql-conf.py
-rwxr-xr-x root/root       313 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/invokesqlservr.sh
-rw-r--r-- root/root     24281 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/mssqlconfhelper.py
-rwxr-xr-x root/root       459 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/set-collation.sh
-rwxr-xr-x root/root       740 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/checkinstall.sh
-rwxr-xr-x root/root     10215 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/mssqlsettings.py
-rwxr-xr-x root/root     10763 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/mssqlsettingsmanager.py
-rwxr-xr-x root/root       115 2017-05-15 23:25 ./opt/mssql/lib/mssql-conf/checkrunninginstance.sh
-rw-r--r-- root/root 115310592 2017-05-15 23:24 ./opt/mssql/lib/system.common.sfp
-rw-r--r-- root/root     73728 2017-05-15 23:24 ./opt/mssql/lib/system.certificates.sfp
-rw-r--r-- root/root     49152 2017-05-15 23:25 ./opt/mssql/lib/secforwarderxplat.sfp
-rw-r--r-- root/root   8568832 2017-05-15 23:24 ./opt/mssql/lib/system.sfp
-rw-r--r-- root/root  19398656 2017-05-15 23:25 ./opt/mssql/lib/sqlpackage.sfp
-rw-r--r-- root/root    343296 2017-05-15 23:24 ./opt/mssql/lib/libsqlvdi.so
-rw-r--r-- root/root 318115840 2017-05-15 23:24 ./opt/mssql/lib/system.netfx.sfp
drwxr-xr-x root/root         0 2017-05-15 23:25 ./opt/mssql/bin/
-rwxr-xr-x root/root       983 2017-05-15 23:25 ./opt/mssql/bin/mssql-conf
-rwxr-xr-x root/root  21406504 2017-05-15 23:25 ./opt/mssql/bin/paldumper
-rwxr-xr-x root/root     12922 2017-05-15 23:25 ./opt/mssql/bin/crash-support-functions.sh
-rwxr-xr-x root/root      1652 2017-05-15 23:25 ./opt/mssql/bin/handle-crash.sh
-rwxr-xr-x root/root    873344 2017-05-15 23:25 ./opt/mssql/bin/sqlpackage
-rwxr-xr-x root/root    877440 2017-05-15 23:25 ./opt/mssql/bin/sqlservr
-rwxr-xr-x root/root       409 2017-05-15 23:25 ./opt/mssql/bin/compress-dump.sh


משום מה האורזים הלכו על opt ולא על תיקיות אחרות ,
תלויות :
 Version: 14.0.600.250-2
 Architecture: amd64
 Installed-Size: 859668
 Depends: libunwind8, libnuma1, libc6, adduser, libjemalloc1, libc++1, gdb, debconf, libcurl3, hostname, openssl (>= 1.0.1), openssl (<= 1.1.0), python (>= 2.7.0), libgssapi-krb5-2, libsss-nss-idmap0, gawk, sed
 Section: misc
 Priority: extra
 Description: Microsoft(R) SQL Server(R) Relational Database Engine
  The mssql-server package contains the Microsoft(R) SQL Server(R) Relational Database Engine.


 רישיון השימוש של גירסת האובנטו מכיל הערה כי התוכנה משדרת נתונים לשרתי מייקרוספט ומכילה פצצה עם שעון עצר (טוב נו time bomb) , מבצעת זיהוי של המחשבים ע"י אמצעים קריפטוגרפיים ומחתימה את המפתחים על NDAשאוסר פירסום של כל הממשקים - ומכיוון שאני לא יכול להסכים לדבר הזה כרגע לא אתקין ואנסה את המוצר על אובנטו .

יום שישי, אפריל 22, 2016

תקלות קידוד שפה בבסיס נתונים PostgreSql.

תקלות קידוד שפה בבסיס נתונים  PostgreSql .

על מנת להקל על הקורא דבר ראשון אם אתה רוצה להמנע מחיים קשים בהקשר של קידוד (ואתה לא על  SQL Server ) המנע מהתקנת השרת על וינדוס. אם אתה לא יכול לפחות המנע ממה שהוא לא SQL_ASCII והשתמש רק בשפה האנגלית.

אם אתה בוחר להתקין שרת בסיס נתונים על וינדוס או שאתה בוחר להשתמש בשפה שאינה אנגלית (אמריקאית) צפה לפגיעה.

הקורא הממוצע ישאל מה יש לכותב כנגד שפות שהן לא אנגלית אמריקאית ?

אתם מבינים בעולם התוכנה, יש מספר יצרנים לצערי מרמת מערכת ההפעלה ועד שמירת המידע בבסיס הנתונים הנחת הבסיס היא שיש שימוש באנגלית אמריקאית  (אפילו התקן של בסיס הנתונים מתייחס ל ANSI).

מדוע אני בתור איש וינדוס אומר להמנע משימוש בוינדוס כמערכת עבור בסיס נתונים במקרה הזה ?
התמיכה בקידודים ו locale שאינם en_us לדעתי לוקה בחסר, כברירת מחדל אין תמיכה ביוניקוד (צריך להריץ chcp 65001 בשביל להפעיל תמיכה למשל ביניקוד).

כאשר אנו מעבירים מידע  בין תוכנת לקוח לשרת  -  אנו  כפופים  לסוג הקידוד של מערכת הפעלה (מה שידוע כ code page) למאפייני השפה הנוכחים (locale) אופי קידוד המידע שיועבר ממערכת ההפעלה של הלקוח , אופי קידוד המידע בצד שרת ברמת הצד המקבל, אוקי קידוד המידע ברמת מערכת ההפעלה בצד המקבל , אוקי קידוד המידע בתוך בסיס הנתונים עצמו.

בעייה קלאסית כשמתקינים בסיס נתונים היא שימוש בשפה שאינה אנגלית ו Collate ברירת מחדל.

הבעיה היא שבדר"כ יש יותר מדרך אחת להציג מידע ובחירת השפה "עברית" בצד שרת ובחירת שפה "עברית" בצד לקוח לא באמת מחייב שהמידע יעבור תקין.

סיבה קלאסית היא הסתמכות על הקידוד מערכת ההפעלה ושימוש בקידוד ברירת מחדל, כשאנו למשל מדברים על עברית זה יכול להיות : UTF16* , ISO-8859-8, UTF8, CP1255,CP 862 ,ISO646.

ממה שאני ראיתי לרוב באפליקציות מהעשור האחרון דובר על CP122 ו iso8859-8 (לא נתקלתי במצב הגיוני של UTF16 או 8 כברירת מחדל עד היום).

בעולם הוינדוס בשביל לגלות במה משתמשים נשתמש בפקודה CHCP בשביל לגלות על איזה קידוד נמצא המשתמש בחיבור הנוכחי (session).

במידה ונבחרו ברירות מחדל נאלץ לגלות מהו קידוד השרת בsession הנוכחי  (המידע בתוך בסיס הנתונים ומערכת ההפעלה בבסיס הנתונים עצמו) ולנסות לכוון את האפליקציה להשתמש באותו הקידוד (להגדיר chcp זהה) .


אם יש לנו גישה לקוד המקור נוכל להגדיר את הקידוד ברמת ה session (במקרה של ODBC) -
לדוגמה עבור PG ניתן להגדיר את הקידוד בצורה הבאה :

"SET client_encoding= 'UTF8'"

ואז לשלוח את המידע כשהוא עבר קידוד ל UTF8 (כל מחרוזת שנשלח צריכה לעבור קידוד ישירות ל UTF8 לפני ההגעה לקו)

פתרון נוסף הוא בחירת הקידוד ברמת החיבור בהנחה שהדריבר שאנו עובדים איתו תומך בunicode :

std::string url = "odbc:postgresql://url:ip/databse&client_encoding=UTF8"

חשוב לציין שאם מחרוזת החיבור נובעת מ DSN אז אפשר לבצע את ההחלפה גם בתוך ה DSN עצמו.

במידה ומשתמשים ב DSN תחת FreeTDS שם הפרמטר הוא ClientCharset והקידוד הוא לפי iconv ובגרסה הקניינית שם הפרמטר הוא Charset.
אצל אורקל שם הארגומנט הוא DatabaseCharacterSet


במידה במידה ואנו עובדים עם קידוד פנימי של שני בתים (wchar_t/UCS2)  ולא יכולים לשנות את מחרוזת החיבור הוא להחליף את הדריבר הרגיל לדוגמה psqlodbc.so ל psqlodbcw.so) ולהתבסס על המרת ברירת מחדל (בגרסאות ישנות של posgresql הפתרון היה פשוט להשתמש ב UCS2 ל UCS2 אם גם השרת וגם הלקוח הם עובדים על וינדוס).

לפעמים נתפתה פשוט תמיד להשתמש ב UTF8 תמיד ולצפות לטוב, הבעיה (אהם פרל אהם פרל) שלא כל השפות והדריברים תומכים בהמרה בין יוניקוד לשפה הנדרשת (EUC_JP לדוגמה) ואז נצטרך לבצע את ההמרה או באפליקציה שלנו או ברמת הדריבר או לבקש מבסיס הנתונים שלנו לבצע המרה.

המרה  ברמת הפעולה בבסיס הנתונים תראה בערך כך :

convert ( text , 'sourceencoding' , 'destencoding')

הממרה ברמת השפה איתה אנו משתמשים תראה בערך כך :

Perl:
$internalEncoding = decode( 'iso-8859-8', $var );
$result = encode( 'utf-8', $internalEncoding );
Java:
Charset utf8 = Charset.forName("UTF-8");
Charset iso8859_8 = Charset.forName("ISO-8859-8");
CharBuffer data = iso8859_8.decode(inputBuffer);
ByteBuffer output = utf8.encode(data);


iconv - C:

iconv_t cnv = iconv_open("UTF-8", "ISO_8859-8"); if (-1 == cnv) { return ; }
int ret = iconv(cnv, &text_in_8859_8, &length_of_text_in_8859_8, &text_in_utf8, &length_of_text_in_utf8);


יום שני, נובמבר 28, 2011

Inserting LONGVARBINARY into MS SQL Server

נתקעתי בבעיה קטנה של המרת קוד ישן שעובד עם freetds + unixodbc בשביל להכניס מידע לבסיס נתונים של MS SQL.
כזכור הסוג IMAGE יורד בהקדם אז צריך לעשות המרה של הקוד שמטפל בזה לאחרים.
אז הנה דוגמה לשימוש ב כfreetds ע"ג odbc בשביל לשלוח מידע שיכול לאחסן קבצים.


/*

    Copyright 2011  Boris Shtrasman boris sh 1983 at gmail dot com

    Permission to use, copy, modify, and distribute this software
    and its documentation for any purpose and without fee is hereby
    granted, provided that the above copyright notice appear in all
    copies and that both that the copyright notice and this
    permission notice and warranty disclaimer appear in supporting
    documentation, and that the name of the author not be used in
    advertising or publicity pertaining to distribution of the
    software without specific, written prior permission.

    The author disclaim all warranties with regard to this
    software, including all implied warranties of merchantability
    and fitness.  In no event shall the author be liable for any
    special, indirect or consequential damages or any damages
    whatsoever resulting from loss of use, data or profits, whether
    in an action of contract, negligence or other tortious action,
    arising out of or in connection with the use or performance of
    this software.

*/
#include <stdio.h>
#include <sql.h>
#include <sqlext.h>

#define TABLE_NAME "binary_v3"

static void extract_error(
    char *fn,
    SQLHANDLE handle,
    SQLSMALLINT type);



int main()
{
   #undef UNICODE /* for the Win ppl */
   SQLHENV henv;
   SQLHDBC dbc;
   SQLHSTMT stmt;

   RETCODE retcode;

   SQLLEN cbTextSize, lbytes;
   PTR pParmID;
   char binary_data[8024]="";

   memset(binary_data,0,sizeof(binary_data));
   binary_data[1] = 5;

   //lets define some strage number for batch  
   SDWORD batch_size = sizeof(binary_data) - 1024;

   // Allocate the ODBC environment and save handle.
   retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) 
   {
      printf("SQLAllocHandle(Env) Failed\n\n");
      goto cleanup;
   }

   // Notify ODBC that this is an ODBC 3.0 app.
   retcode = SQLSetEnvAttr(henv, 
        SQL_ATTR_ODBC_VERSION,
           (SQLPOINTER) SQL_OV_ODBC3,
                SQL_IS_INTEGER);

   if ( 
       (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) 
   {
      printf("SQLSetEnvAttr(ODBC version) Failed\n\n");
      goto cleanup;
   }

   // Allocate ODBC connection handle and connect.
   retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &dbc);
   if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS))
   {
      printf("SQLAllocHandle(dbc) Failed\n\n");
      goto cleanup;
   }
     
   SQLCHAR odbc_dsn_string_dump[255];
   SQLSMALLINT odbc_dsn_string_dumpLen;

   retcode = SQLDriverConnect(
           dbc,
           NULL,
           (SQLCHAR *)"Driver=FreeTds;"
                "SERVER=192.168.1.2\\SQLEXPRESS;UID=sa;"
                "PWD=pwd;DATABASE=db",
           SQL_NTS,
           odbc_dsn_string_dump,
           sizeof(odbc_dsn_string_dump),
           &odbc_dsn_string_dumpLen,
           SQL_DRIVER_COMPLETE);
   
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) 
   {
      extract_error("Describe param",dbc, SQL_HANDLE_DBC);  
       
      goto cleanup;
   }

   // Allocate statement handle.
   retcode = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) 
   {
      extract_error("Allocation ... ",stmt, SQL_HANDLE_STMT);  
       
      goto cleanup;
   }

   //tell the driver to work only in sync mode !
   SQLSetStmtOption(dbc, SQL_ASYNC_ENABLE, SQL_ASYNC_ENABLE_OFF);

   if (SQL_SUCCESS !=  SQLExecDirect(stmt,  (SQLCHAR *)
            "IF EXISTS "
            "(SELECT * FROM sysobjects WHERE id = "
            "object_id(N'[dbo].[" TABLE_NAME "]') "
            "AND OBJECTPROPERTY(id, N'IsUserTable') = 1) "
            "DROP TABLE [dbo].[" TABLE_NAME "]; " 
            "CREATE TABLE [dbo].[" TABLE_NAME "] "
            "( name varchar(256), content varbinary(max) NOT NULL ); ",    
            SQL_NTS))
   {
      extract_error("drop + create table ... ",stmt, SQL_HANDLE_STMT);  
       
      goto cleanup;
 
   }
   
   lbytes = (SDWORD) sizeof(binary_data);
   //we are setting the length to be calculated on run time.
   cbTextSize = SQL_LEN_DATA_AT_EXEC(lbytes);

   // Bind the parameter marker.
   
   SQLSMALLINT    binded_column_type,
                  persicion_in_binded_column,
                  is_binded_type_nullable;
   
   SQLUINTEGER   binded_column_size_from_driver = 0;
   
   retcode = SQLPrepare( stmt,
                         (SQLCHAR*)"INSERT INTO " 
                                    TABLE_NAME 
                        " (name, content) VALUES ('file', ?)",SQL_NTS);

#if 0

//for now freetds does not support describe param 
// but on the second it does I must use describe
//      param inorder to get the correct sizes and column types
   retcode = SQLDescribeParam(stmt,
         1,
         &binded_column_type,
         &binded_column_size_from_driver,
         &persicion_in_binded_column,
         &is_binded_type_nullable);

   printf ("Desc info (%d) %d %d %d %d\n",retcode , binded_column_type , 
binded_column_size_from_driver, persicion_in_binded_column, is_binded_type_nullable);

   if (binded_column_type != SQL_LONGVARBINARY) 
   {
        printf("This is strange got %d instead of %d\n" , 
binded_column_type, SQL_LONGVARBINARY);
   }

   if (SQL_SUCCESS != retcode ) 
   {
     extract_error("Describe param",stmt, SQL_HANDLE_STMT);  
         goto cleanup;
   }
#else
    binded_column_size_from_driver = 0;//Don't ask me why freetds\
 fails to work with the 2G size 
#endif

   retcode = SQLBindParameter(stmt, 
                              1, 
                              SQL_PARAM_INPUT,
                              SQL_C_BINARY,
                              SQL_LONGVARBINARY,
                              binded_column_size_from_driver
                                        /*2147483647 vs 32K*/,
                              0,
                              (VOID *) 1/* any value other then null*/,
                              0,
                              &cbTextSize);
    
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
      extract_error("Bind param param",stmt, SQL_HANDLE_STMT);  
      goto cleanup;
   }

   // Execute the command.
   retcode = SQLExecDirectA(
                stmt, 
                (SQLCHAR *)"INSERT INTO " 
                            TABLE_NAME 
                           " (name, content) VALUES ('file', ?)", SQL_NTS);
   
   if ( 
        (retcode != SQL_SUCCESS) 
           &&
        (retcode != SQL_NEED_DATA)
           && 
        (retcode != SQL_SUCCESS_WITH_INFO) )
   {
      extract_error("Insert",stmt, SQL_HANDLE_STMT);  
      goto cleanup;
   }

   // We set up the data len to be computed on executing therefor we must \
         actually send the data.
   // prior to calling put data you must first call to SQLParamData .. \
         why, only the odbc masters know 
   retcode = SQLParamData(stmt, &pParmID);
   printf("SQLParam Data = %d \n",retcode);

   if (SQL_NEED_DATA != retcode)
   {
      extract_error("grrr ... ",stmt , SQL_HANDLE_STMT);
      goto cleanup;
   }

   char * pt_data_be_inserted_into_db = binary_data;
   //we defined that data len will be calculated on executing \
        this is the reason why we got this value
  
   if (retcode == SQL_NEED_DATA) 
   {
      
      while (lbytes > batch_size)
      {

         retcode = SQLPutData(stmt,
                   (SQLCHAR*) pt_data_be_inserted_into_db, batch_size);
         lbytes -= batch_size;
         pt_data_be_inserted_into_db += batch_size;
      }
      // Put final batch.
      retcode = SQLPutData(stmt, pt_data_be_inserted_into_db, lbytes); 
      printf("last put data with %d bytes and exited with %d\n", lbytes,retcode);
   
      if ( 
           (retcode != SQL_SUCCESS)
              && 
           (retcode != SQL_SUCCESS_WITH_INFO) )
      {
         extract_error("Put data for stmt",stmt, SQL_HANDLE_STMT);  
         goto cleanup;
      }
     
   }
  
   // send the data to the db.
   retcode = SQLParamData(stmt, &pParmID);
   if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) 
   {
      extract_error("Final Param data",stmt, SQL_HANDLE_STMT);  
      goto cleanup;
   }
   
cleanup:
   // Clean up.
   SQLFreeHandle(SQL_HANDLE_STMT, stmt);
   SQLDisconnect(dbc);
   SQLFreeHandle(SQL_HANDLE_DBC, dbc);
   SQLFreeHandle(SQL_HANDLE_ENV, henv);
   return 0;
}

void extract_error(
    char *fn,
    SQLHANDLE handle,
    SQLSMALLINT type)
{
    SQLINTEGER     i = 0;
    SQLINTEGER     native;
    SQLCHAR     state[ 7 ];
    SQLCHAR     text[256];
    SQLSMALLINT     len;
    SQLRETURN     ret;

    fprintf(stderr,
            "\n"
            "The driver reported the following diagnostics whilst running "
            "%s\n\n",
            fn);

    perror("Last os error :");
    do
    {
        ret = SQLGetDiagRec(type, handle, ++i, state, &native, text,
                            sizeof(text), &len );
        if (SQL_SUCCEEDED(ret))
            printf("%s:%ld:%ld:%s\n", state, i, native, text);
    }
    while( ret != SQL_NO_DATA );
    fprintf(stderr, "found %d elements of information\n",(i>0)?i - 1:0);
}

יום שני, נובמבר 21, 2011

Denali is a great feture ...

 טוב קיבלתי לידי התקנת SQL Denali , מה אני יכול לספר אם זה ייציב בשביל מפתחים אז מישהוא אימץ את  שיטת שהמשתמשים יעשו QA.

רק לספר לכם על התהליך שהמכונה הזאת עברה (משידרוג של sql server 2008 R2) - כמה שגיאות מדהימות בשביל התענוג :
הכל התחיל מexceptions מבסיס נתונים

אז אמרתי טוב בשביל מה יש בסיס התקנה לידך :



בשביל לתקן את זה צריך לייצר חשבון משתמש שונה מnetbios name (שם מחשב), טוב אמרתי יאללה אולי שווה לי לעבוד עם denali ?






אהה מה עושים במצב כזה תשאלו ?
מקללים ומסירים כל דבר שקשור ל SQL Server (כולל compat) - לפני זה תכינו את הדיסק של VS2010 כי ההתקנה שלכם הולכת פיפאן.
מקללים עוד קצת כי אז מקבלים :


זה בסדר תרגישו טוב אתם רק בודקי תוכנה בחינם :-)

יופי הצלחת לעדכן את בסיס הנתונים ואתם מקבלים שגיעה שאי אפשר לפתוח VS 2010 כי חלק מהאלמנטים השתדרגו , לפי פורמים כל מה שצריך לעשות זה לבצע תיקון של ההתקנה :
זה בסדר , זו רק שגיאה שמצריכה להפעיל מחדש את המחשב ולנסות לעשות תיקון נוסף ...


משהוא חשוב בשביל לספר לכם תחזיקו שני instances של סביבת העבודה שלכם אחת ל SQL ואחת ל C הסיבה היא פשוטה: ביום אחד קרוב ל12 נפילות של הclient , אם חשבתם ש VS 2010 הוא איטי (על מחשב עם 4 ג"ב זכרון וכונן 7200) אז תתכונו לסיוט.
משהוא קטן אני עובד עם win7 מעודכן ללא שום תוכנות חיצוניות פרט לנדרשות (אני מהאנשים שאסרו עליהם להתקין vim).

זהוא סיימנו עם סיפורי הגבורה עם שירותי ה SQL :-) ונעבור לקצת קוד פתוח..

לאחר הערה של ארתיום על אי התמיכה ביוניקוד ב freetds החלטתי לבדוק מה עוד יהיה חסר (עדיף לדעת על צרות לפני זה).

לפתע אני לא מצליח להתחבר מ freetds עם שגיעה קריפטית:



UNICODE Using encoding ASCII 'ISO8859-1' and UNICODE 'UCS-2LE' 
DIAG [08S01] [FreeTDS][SQL Server]Unable to connect: Adaptive Server is unavailable or does not exist   

DIAG [S1000] [FreeTDS][SQL Server]Unable to connect to data source 
אם אתם יודעים על מה מדובר על הכבוד לכם , זו דוגמה מצויינת להודעת שגיעה (כי היא משגעת ).
מדובר למעשה על בעיית חיבור שלא מתורגמת כמו שצריך.

טוב קופצים למכונה רואים שהפורט נכון שהכל כביכול עובד אבל אין חיבור.
חיפוש נוסף מגלה שלמרות שהגדרתי פורט להאזנה בשדה ipall פיספסתי שאני חייב לעבור שדה שדה ולמחוק תוכן מ dynamic ports, בסיום ההגדרה אצלי זה נראה כך :


בסדר נגמר יש אפילו חיבור :

#include <stdio.h>
#include <sql.h>
#include <sqlext.h>


static void extract_error(
    char *fn,
    SQLHANDLE handle,
    SQLSMALLINT type);

main() {
  SQLHENV env;
  SQLHDBC dbc;
  SQLHSTMT stmt;
  SQLRETURN ret; /* ODBC API return status */
  SQLCHAR outstr[1024];
  SQLSMALLINT outstrlen;

  /* Allocate an environment handle */
  SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
  /* We want ODBC 3 support */
  SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
  /* Allocate a connection handle */
  SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
  /* Connect to the DSN mydsn */
  ret = SQLDriverConnect(dbc, NULL, "Driver=FreeTds;SERVER=192.168.1.2\\SQLEXPRESS;UID=username;PWD=pwd;DATABASE=master", SQL_NTS,
                         outstr, sizeof(outstr), &outstrlen,
                         SQL_DRIVER_COMPLETE);
  if (SQL_SUCCEEDED(ret)) {
    printf("Connected\n");
    printf("Returned connection string was:\n\t%s\n", outstr);
    if (ret == SQL_SUCCESS_WITH_INFO) {
      printf("Driver reported the following diagnostics\n");
      extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
    }
    SQLDisconnect(dbc);         /* disconnect from driver */
  } else {
    fprintf(stderr, "Failed to connect\n");
    extract_error("SQLDriverConnect", dbc, SQL_HANDLE_DBC);
  }
  /* free up allocated handles */
  SQLFreeHandle(SQL_HANDLE_DBC, dbc);
  SQLFreeHandle(SQL_HANDLE_ENV, env);
}

void extract_error(
    char *fn,
    SQLHANDLE handle,
    SQLSMALLINT type)
{
    SQLINTEGER   i = 0;
    SQLINTEGER   native;
    SQLCHAR      state[ 7 ];
    SQLCHAR      text[256];
    SQLSMALLINT  len;
    SQLRETURN    ret;

    fprintf(stderr,
            "\n"
            "The driver reported the following diagnostics whilst running "
            "%s\n\n",
            fn);

    do
    {
        ret = SQLGetDiagRec(type, handle, ++i, state, &native, text,
                            sizeof(text), &len );
        if (SQL_SUCCEEDED(ret))
            printf("%s:%ld:%ld:%s\n", state, i, native, text);
    }
    while( ret == SQL_SUCCESS );
}

יום שישי, נובמבר 18, 2011

freetds vs kde

איזה כיף שיש מלחמות בין מפתחים נכון ?!
אני באמת אוהב להשתמש ב kde אבל בגלל סיבות כאלה ואחרות אני מפתח וצריך גישה לשרתי MS SQL.
בעולם האידאלי של פעם הייתי פשוט משתמש ב freetds.

אבל לא ..  עכשיו שני מתכנתים רבים והתוצאה או שתשתמש ב freetds או שתשתמש ב kde.
שברתי את הראש די הרבה והגעתי לשני פתרונות :
  • לחזור להשתמש ב squeeze.
  • לבנות מקומית את הספרייה ולחכות שהאנשים יפסיקו לריב בינהם.
לגבי האופציה השנייה :
apt-get source freetds
cd freetds-*
dpkg-buildpackage
לאחר מכאן פשוט להשתמש ב so שנוצר בהקנת ה freetds:

boris@midgard:/usr/share/doc/libct4$ cat /etc/odbcinst.ini
[ODBC]
Trace        = Yes
TraceFile    = /tmp/sql.log
ForceTrace   = Yes

[FreeTDS]
Driver=/opt/wasteoftime/freetds-0.82/debian/tmp/usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so
Setup = Driver=/usr/lib/x86_64-linux-gnu/odbc/libtdsS.so

UsageCount=1
FileUsage=1
tds version=8.0
 
כן אני יודע שיכלתי לבנות ולהתקין את freetds ל usr אבל יכלתי להתקע עם גירסאות שונות של אותה האפליקציה (אכשיו רק נשאר לחכות שיתקנו את kde).

יום רביעי, מרץ 31, 2010

לילה טוב MySQL

האם זה סופו של עידן ?
אוקרל עושה צרות לאחרונה בפיתוח של MySQL שזה כאב ראש קטן, אבל האם זה אומר שאני הולך למצוא את עצמי עובד עם בסיסי נתונים אחרים? האם נראה עלייה של שימוש בבסיסי נתונים מבוססי אובייקטים (כי זה מה שאני רואה בפועל כיום).

והנה הודעה בslashdot שאורקל מפסיקה את הפיתוח של OpenSolaris מה הלאה ? האם כל מוצרי sun ימותו לאט לאט ?
ולחשוב שקיבלתי מטלה בקורס אקדמי של לשער מה יהיה העתיד הקרוב (זה היה אחרי הרכישה של SUN) של בסיס הנתונים. מזל שלא לקחתי את המטלה הזאת. למרות שלדעתי MySQL הוא אחד מבסיסי הנתונים הטבלאיים הנוחים יותר (לעבודתי) אני נאלץ לומר שאני מתחיל ללמוד לעבוד עם בסיסי נתונים אחרים (ושל אורקל הוא אחד מהם). הבעיה ? הם לא חופשיים. לעזזעל לפחות תכניסו את עצמך לעץ non-free שיהיה אפשר לעבוד ולהתקין בצורה חלקה. אבל לא הסכם המשתמש אוסר הפצת חבילות (ככה אני הבנתי לפחות). נכון שזה תמריץ טוב לגרום למתכנתים לעבור לpostrege או לכל בסיס נתונים מבוסס SQL אחר (כי מה לעשות SQL הוא מספיק נפוץ). אני לא רואה מרצים עוברים ללמד MySQL אם הם לא בטוחים במוצר (ואני לא מדבר על לימודי בטיחות / בניית אתרים אלה כאשר מלמדים בסיסי נתונים). בסיס נתונים צריך להיות פשוט וקל להתקנה. בלי יותר מדי סלטות באוויר בשביל לגרום לו לעבוד על המכונה שלך.

ויאמר לזכותו של MSSQL שבהתחלה אותו קל להתקין, זה שהוא לא מספק עבורי את העבודה , זה שחסר לו אפשרויות ניהול חינימיות ,כן אני יודע שאני יכול להשתמש בתוכנה חופשית לנהל Ms SQL 20XY אבל עדיין אני מצפה שיצא מוצר מאותו הבית לניהול.

יום חמישי, אוגוסט 27, 2009

הגיע הזמן ללמוד את המפתח הפרטי שלי

לפני מספר ימים קראתי את הפוסט של יהונתן קלינגר בנושא של הצפנה. הפוסט העלה נקודה שלא חייבים לתת גישה לנתונים המאוכסנים במוחו של אדם. אבל מה קורא כאשר יש גישה לנתונים הקרים? לדוגמה שימוש בgnupg :

מרבית האנשים שאני מכיר שעובדים עם מידע חשוב (כספים , פרטים אישים , שיחות מעניינות ... ) מעדיפים להשתמש באחת מהפתרונות שנותנת חבילות ההצפנה (בנושא של הצפנת הRTP זה מקום לפוסט אחר).

אולם נניח ובצורה כל שהיא אחת המכונות שלכם הגיע לידי פקיד דרג ז' במדינה שבוחר לבדוק אותו. אמנם יש רבים וטובים בשירות המדינה (שמעתי מספיק על כל מני מבחנים ומערכות כדי להאמין שיש אנשים מאוד טובים שם). אבל יש גם גרועים - אני זוכר היטב איך אדם שהתרעיין טען כי הם פורצים מערכות מוצפנות בפרוטוקול RSA באורך של 4K על תקן יומי. אכשיו בניגוד למדינות אחרות אין פה חוקה , וגם התקשורת האהובה לא ממש חופשית או פתוחה (ראה ערך צנזורה). ובדרך נתונה לחסדי פוליטקאי זה או אחר (ראה ערך כתבת החליצה). אותו פקיד ישתמש בעוד חוק נחמד שלא נועד במקור ויקבל העתק של כל הכונן. מעניין שאין פה שום צורה של EFF אבל יכול להיות שאני טועה.

היום התפרסם בWired מאמר על זה שרשויות מדינה לא יקבלו את כל הכונן אלה רק חלקים ממנו (חברה צד ג' תסרוק את הכונן) אולם נשאלת השאלה מה זה עוזר ? אם מלתחילה רציתי שהשיחות שלי עם בת זוגתי או מעסיק פוטנציאלי יוצפנו אם פחות עין אחת תעבור עליו.

בדרך מחיצת הבית (או למעשה כל הכונן) מוצפן באמצעות שימוש בLUKS + dm_crypt . מהנקודה הזאת מתחילה בעייה : פעמים רבות המפתחות הפרטיים מאוכסנים פיזית על הכונן (לפעמים על tmpfs ) אבל עדיין יש גישה למפתח הפרטי (שזה מחצית מההצפנה). ומכאן נשאלת השאלה האם לא הכול אובד ברגע זה ? כלומר נניח ובדרך לא דרך אותו פקיד דרג ז' קיבל גישה למערכת הקבצים המוצפנת ויש לו כבר גישה למפתחות הפרטיים האם הכול אבוד ? האם ברגע זה למעשה כל ההצפנה החזקה (אורך) והתקווה הגדולה לפרטיות נופלת ?

לבסוף אני מבין שיש בעייה בשמירת המפתח הפרטי על מדיה כל שהיא אלה הגיע הזמן למצוא שיטה לזכור את המפתח הפרטי בע"פ.

עוד נקודה חשובה שיהונתן העלה היא נושא סריקת הפורטים , לאחר שקראתי את הסעיף אני מבין למעשה שאולי עצם הסריקה הוא לא בעייתי:

לדוגמה:
כנס גדול הולך להתארגן וחלק מהמארגנים מעוניינים להשתמש בחברת סליקה מסויימת. כמו כל גיק מצויי משתתפי הכנס סורקים את השרת בשביל לוודא שהשרת לא משתמש בטנולוגיות פריצות (למשל RDP פתוח לכל העולם) או ששירות בסיס הנתונים מאזין לכל העולם (לא מדובר פה על הכנס האחרון !). כן אני יודע ששרת SQL server 2005 זה שרת "מאובטח" וזה מצויין שהוא מאפשר לאנשי הIT שלכם להתחבר עם משתמש SA אבל אני לא רוצה לעשות איתכם עסק במצב כזה.

הדבר דומה לבדיקה שאתם מבצעים בכניסה ל"בנק": האם הייתם מפקידים את כספכם בבנק חדש שמחזיק את הכספת בחצר האחורית של בעל הבנק ? לא , נכון ?!. מאותה הסיבה אני לא מעוניין לבצע עיסקה עם חברה שלא שומרת על חוקי אבטחת מידע - תארו לכם שמשרד הרישוי היה שולח את המידע שלכם בצורה לא מוצפנת כששם המשתמש והסיסמה מודבקים על המחשב , נכון שלא הייתם ששים להצטלם ?!

כן כן תקראו לי פרנואיד .. אבל לאחר הבנה איך מספר מוסדות עובדים , אני לא מאמין לשום חברה , ולשום גוף. פשוט מספיק להזכר איך חדרו לעירייה מסויימת לא מזמן (הנדסה חברתית) ואיך חברת גבייה מסויימת משתמש בשם משתמש וסיסמה אחד לכל העובדים "כי אין זמן לפתוח משתמש לכל אחד כי העובדים מתחלפים / העובדת בדיוק בחופשת מחלה וצריך להכנס בשמה לעשות דברים".