mORMot and Open Source friends
Check-in [9a04825171]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:{3304} SynDB's ColumnScale contains -1 if the SQL metadata request returns NULL - is the case e.g. for plain NUMBER for Oracle, which should be handled as ftDouble, not ftInt64 - see http://synopse.info/forum/viewtopic.php?id=3723
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 9a048251710fdefdbe8e5f74224810d2961fe971
User & Date: ab 2016-12-29 08:21:42
Context
2017-01-01
15:05
{3305} we reached 2017 ! HAPPY MORMOT YEAR FOR EVERYONE! check-in: 8f71b8aaf0 user: ab tags: trunk
2016-12-29
08:21
{3304} SynDB's ColumnScale contains -1 if the SQL metadata request returns NULL - is the case e.g. for plain NUMBER for Oracle, which should be handled as ftDouble, not ftInt64 - see http://synopse.info/forum/viewtopic.php?id=3723 check-in: 9a04825171 user: ab tags: trunk
2016-12-28
18:31
{3303} new OPT4AMD conditional - to use "set of byte" to generate BT[mem] opcode which is actually slower under Intel than cascaded SUB, and may be faster under check-in: ded4e331e7 user: ab tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SynCommons.pas.

20043
20044
20045
20046
20047
20048
20049
20050
20051
20052
20053
20054
20055
20056
20057
20058
20059
20060
20061
.....
20068
20069
20070
20071
20072
20073
20074
20075
20076
20077
20078
20079
20080
20081
20082
.....
20132
20133
20134
20135
20136
20137
20138
20139
20140
20141
20142
20143
20144
20145
20146
.....
31921
31922
31923
31924
31925
31926
31927
31928
31929
31930
31931
31932
31933
31934
31935
31936
31937
31938
31939
31940
31941
31942
31943
31944
31945
.....
61360
61361
61362
61363
61364
61365
61366
61367
61368
61369
61370
61371
61372
61373
61374
61375
61376
61377
61378
  end else
    P := StrUInt64(P,val);
  result := P;
end;

const
  // see https://en.wikipedia.org/wiki/Baudot_code
  B2A: array[0..63] of AnsiChar =
   #0'e'#10'a siu'#13'drjnfcktzlwhypqobg'#254'mxv'#255+
   #0'3'#10'- ''87'#13#0'4'#0',!:(5+)2$6019?@'#254'./;'#255;
var
  A2B: array[AnsiChar] of byte;

function AsciiToBaudot(const Text: RawUTF8): RawByteString;
begin
  result := AsciiToBaudot(pointer(Text),length(Text));
end;

function AsciiToBaudot(P: PAnsiChar; len: integer): RawByteString; overload;
................................................................................
  if (P=nil) or (len=0) then
    exit;
  shift := false;
  dest := tmp.Init((len*10)shr 3);
  d := 0;
  bits := 0;
  for i := 0 to len-1 do begin
    c := A2B[P[i]];
    if c>32 then begin
      if not shift then begin
        d := (d shl 5) or 27;
        inc(bits,5);
        shift := true;
      end;
      d := (d shl 5) or (c-32);
................................................................................
      27: if shift<>0 then
            exit else
            shift := 32;
      31: if shift<>0 then
            shift := 0 else
            exit;
      else begin
        c := ord(B2A[c+shift]);
        if c=0 then
          if Baudot[i+1]=0 then // allow triming of last 5 bits
            break else
            exit;
        dest^ := AnsiChar(c);
        inc(dest);
      end;
................................................................................
  h.i7 := h1;
end;

function IsZero(const dig: THash256): boolean;
var a: TPtrIntArray absolute dig;
begin
  result := (a[0]=0) and (a[1]=0) and (a[2]=0) and (a[3]=0)
    {$ifndef CPU64} and (a[4]=0) and (a[5]=0)
                    and (a[6]=0) and (a[7]=0){$endif};
end;

function IsEqual(const A,B: THash256): boolean;
var a_: TPtrIntArray absolute A;
    b_: TPtrIntArray absolute B;
begin
  result := (a_[0]=b_[0]) and (a_[1]=b_[1]) and (a_[2]=b_[2]) and (a_[3]=b_[3])
    {$ifndef CPU64} and (a_[4]=b_[4]) and (a_[5]=b_[5])
                    and (a_[6]=b_[6]) and (a_[7]=b_[7]){$endif};
end;

procedure FillZero(out dig: THash256);
begin
  PInt64Array(@dig)^[0] := 0;
  PInt64Array(@dig)^[1] := 0;
  PInt64Array(@dig)^[2] := 0;
................................................................................
    TwoDigitsHex[i][1] := HexChars[i shr 4];
    TwoDigitsHex[i][2] := HexChars[i and $f];
  end;
  FillcharFast(ConvertBase64ToBin,256,255); // invalid value set to -1
  for i := 0 to high(b64enc) do
    ConvertBase64ToBin[b64enc[i]] := i;
  ConvertBase64ToBin['='] := -2; // special value for '='
  for i := high(B2A) downto 0 do
    if B2A[i]<#128 then
      A2B[B2A[i]] := i;
  for i := ord('a') to ord('z') do
    A2B[AnsiChar(i-32)] := A2B[AnsiChar(i)]; // A-Z -> a-z
  // initialize our internaly used TSynAnsiConvert engines
  TSynAnsiConvert.Engine(0);
  // initialize tables for crc32cfast() and SymmetricEncrypt/FillRandom
  for i := 0 to 255 do begin
    crc := i;
    for n := 1 to 8 do
      if (crc and 1)<>0 then // polynom is not the same as with zlib's crc32()






|



|







 







|







 







|







 







|
|







|
|







 







|
|
|

|







20043
20044
20045
20046
20047
20048
20049
20050
20051
20052
20053
20054
20055
20056
20057
20058
20059
20060
20061
.....
20068
20069
20070
20071
20072
20073
20074
20075
20076
20077
20078
20079
20080
20081
20082
.....
20132
20133
20134
20135
20136
20137
20138
20139
20140
20141
20142
20143
20144
20145
20146
.....
31921
31922
31923
31924
31925
31926
31927
31928
31929
31930
31931
31932
31933
31934
31935
31936
31937
31938
31939
31940
31941
31942
31943
31944
31945
.....
61360
61361
61362
61363
61364
61365
61366
61367
61368
61369
61370
61371
61372
61373
61374
61375
61376
61377
61378
  end else
    P := StrUInt64(P,val);
  result := P;
end;

const
  // see https://en.wikipedia.org/wiki/Baudot_code
  Baudot2Char: array[0..63] of AnsiChar =
   #0'e'#10'a siu'#13'drjnfcktzlwhypqobg'#254'mxv'#255+
   #0'3'#10'- ''87'#13#0'4'#0',!:(5+)2$6019?@'#254'./;'#255;
var
  Char2Baudot: array[AnsiChar] of byte;

function AsciiToBaudot(const Text: RawUTF8): RawByteString;
begin
  result := AsciiToBaudot(pointer(Text),length(Text));
end;

function AsciiToBaudot(P: PAnsiChar; len: integer): RawByteString; overload;
................................................................................
  if (P=nil) or (len=0) then
    exit;
  shift := false;
  dest := tmp.Init((len*10)shr 3);
  d := 0;
  bits := 0;
  for i := 0 to len-1 do begin
    c := Char2Baudot[P[i]];
    if c>32 then begin
      if not shift then begin
        d := (d shl 5) or 27;
        inc(bits,5);
        shift := true;
      end;
      d := (d shl 5) or (c-32);
................................................................................
      27: if shift<>0 then
            exit else
            shift := 32;
      31: if shift<>0 then
            shift := 0 else
            exit;
      else begin
        c := ord(Baudot2Char[c+shift]);
        if c=0 then
          if Baudot[i+1]=0 then // allow triming of last 5 bits
            break else
            exit;
        dest^ := AnsiChar(c);
        inc(dest);
      end;
................................................................................
  h.i7 := h1;
end;

function IsZero(const dig: THash256): boolean;
var a: TPtrIntArray absolute dig;
begin
  result := (a[0]=0) and (a[1]=0) and (a[2]=0) and (a[3]=0)
     {$ifndef CPU64} and (a[4]=0) and (a[5]=0)
                     and (a[6]=0) and (a[7]=0){$endif};
end;

function IsEqual(const A,B: THash256): boolean;
var a_: TPtrIntArray absolute A;
    b_: TPtrIntArray absolute B;
begin
  result := (a_[0]=b_[0]) and (a_[1]=b_[1]) and (a_[2]=b_[2]) and (a_[3]=b_[3])
          {$ifndef CPU64} and (a_[4]=b_[4]) and (a_[5]=b_[5])
                          and (a_[6]=b_[6]) and (a_[7]=b_[7]){$endif};
end;

procedure FillZero(out dig: THash256);
begin
  PInt64Array(@dig)^[0] := 0;
  PInt64Array(@dig)^[1] := 0;
  PInt64Array(@dig)^[2] := 0;
................................................................................
    TwoDigitsHex[i][1] := HexChars[i shr 4];
    TwoDigitsHex[i][2] := HexChars[i and $f];
  end;
  FillcharFast(ConvertBase64ToBin,256,255); // invalid value set to -1
  for i := 0 to high(b64enc) do
    ConvertBase64ToBin[b64enc[i]] := i;
  ConvertBase64ToBin['='] := -2; // special value for '='
  for i := high(Baudot2Char) downto 0 do
    if Baudot2Char[i]<#128 then
      Char2Baudot[Baudot2Char[i]] := i;
  for i := ord('a') to ord('z') do
    Char2Baudot[AnsiChar(i-32)] := Char2Baudot[AnsiChar(i)]; // A-Z -> a-z
  // initialize our internaly used TSynAnsiConvert engines
  TSynAnsiConvert.Engine(0);
  // initialize tables for crc32cfast() and SymmetricEncrypt/FillRandom
  for i := 0 to 255 do begin
    crc := i;
    for n := 1 to 8 do
      if (crc and 1)<>0 then // polynom is not the same as with zlib's crc32()

Changes to SynDB.pas.

382
383
384
385
386
387
388

389
390
391
392
393
394
395
...
445
446
447
448
449
450
451

452
453
454
455
456
457
458
...
625
626
627
628
629
630
631


632
633
634
635
636
637
638
....
5174
5175
5176
5177
5178
5179
5180


5181
5182
5183
5184
5185
5186
5187
5188
....
5248
5249
5250
5251
5252
5253
5254


5255
5256
5257
5258
5259
5260
5261
5262
    // a value without any maximal length
    ColumnLength: PtrInt;
    /// the Column data precision
    // - used e.g. for numerical values
    ColumnPrecision: PtrInt;
    /// the Column data scale
    // - used e.g. for numerical values

    ColumnScale: PtrInt;
    /// the Column type, as recognized by our SynDB classes
    // - should not be ftUnknown nor ftNull
    ColumnType: TSQLDBFieldType;
    /// specify if column is indexed
    ColumnIndexed: boolean;
  end;
................................................................................
    // a value without any maximal length
    ColumnLength: PtrInt;
    /// the Column data precision
    // - used e.g. for numerical values
    ColumnPrecision: PtrInt;
    /// the Column data scale
    // - used e.g. for numerical values

    ColumnScale: PtrInt;
    /// the Column type, as recognized by our SynDB classes
    // - should not be ftUnknown nor ftNull
    ColumnType: TSQLDBFieldType;
    /// defines the procedure column as a parameter or a result set column
    ColumnParamType: TSQLDBParamInOutType;
  end;
................................................................................
    // - Columns numeration (i.e. Col value) starts with 0
    // - returns -1 if the Column name is not found (via case insensitive search)
    function ColumnIndex(const aColumnName: RawUTF8): integer;
    /// the Column type of the current Row
    // - FieldSize can be set to store the size in chars of a ftUTF8 column
    // (0 means BLOB kind of TEXT column)
    function ColumnType(Col: integer; FieldSize: PInteger=nil): TSQLDBFieldType;


    /// return a Column integer value of the current Row, first Col is 0
    function ColumnInt(Col: integer): Int64; overload;
    /// return a Column floating point value of the current Row, first Col is 0
    function ColumnDouble(Col: integer): double; overload;
    /// return a Column floating point value of the current Row, first Col is 0
    function ColumnDateTime(Col: integer): TDateTime; overload;
    /// return a column date and time value of the current Row, first Col is 0
................................................................................
      exit;
    with Execute(SQL,[]) do
      while Step do begin
        F.ColumnName := trim(ColumnUTF8(0));
        F.ColumnTypeNative := trim(ColumnUTF8(1));
        F.ColumnLength := ColumnInt(2);
        F.ColumnPrecision := ColumnInt(3);


        F.ColumnScale := ColumnInt(4);
        F.ColumnType := ColumnTypeNativeToDB(F.ColumnTypeNative,F.ColumnScale);
        if ColumnInt(5)>0 then
          F.ColumnIndexed := true;
        FA.Add(F);
      end;
  end;
  SetLength(Fields,n);
................................................................................
    exit;
  with Execute(SQL,[]) do
    while Step do begin
      F.ColumnName := trim(ColumnUTF8(0));
      F.ColumnTypeNative := trim(ColumnUTF8(1));
      F.ColumnLength := ColumnInt(2);
      F.ColumnPrecision := ColumnInt(3);


      F.ColumnScale := ColumnInt(4);
      F.ColumnType := ColumnTypeNativeToDB(F.ColumnTypeNative,F.ColumnScale);
      case FindCSVIndex('IN,OUT,INOUT',ColumnUTF8(5),',',false) of
        0: F.ColumnParamType := paramIn;
        2: F.ColumnParamType := paramInOut;
      else // any other is assumed as out
        F.ColumnParamType := paramOut;
      end;






>







 







>







 







>
>







 







>
>
|







 







>
>
|







382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
...
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
....
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
....
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
    // a value without any maximal length
    ColumnLength: PtrInt;
    /// the Column data precision
    // - used e.g. for numerical values
    ColumnPrecision: PtrInt;
    /// the Column data scale
    // - used e.g. for numerical values
    // - may be -1 if the metadata SQL statement returned NULL 
    ColumnScale: PtrInt;
    /// the Column type, as recognized by our SynDB classes
    // - should not be ftUnknown nor ftNull
    ColumnType: TSQLDBFieldType;
    /// specify if column is indexed
    ColumnIndexed: boolean;
  end;
................................................................................
    // a value without any maximal length
    ColumnLength: PtrInt;
    /// the Column data precision
    // - used e.g. for numerical values
    ColumnPrecision: PtrInt;
    /// the Column data scale
    // - used e.g. for numerical values
    // - may be -1 if the metadata SQL statement returned NULL 
    ColumnScale: PtrInt;
    /// the Column type, as recognized by our SynDB classes
    // - should not be ftUnknown nor ftNull
    ColumnType: TSQLDBFieldType;
    /// defines the procedure column as a parameter or a result set column
    ColumnParamType: TSQLDBParamInOutType;
  end;
................................................................................
    // - Columns numeration (i.e. Col value) starts with 0
    // - returns -1 if the Column name is not found (via case insensitive search)
    function ColumnIndex(const aColumnName: RawUTF8): integer;
    /// the Column type of the current Row
    // - FieldSize can be set to store the size in chars of a ftUTF8 column
    // (0 means BLOB kind of TEXT column)
    function ColumnType(Col: integer; FieldSize: PInteger=nil): TSQLDBFieldType;
    /// returns TRUE if the column contains NULL
    function ColumnNull(Col: integer): boolean; 
    /// return a Column integer value of the current Row, first Col is 0
    function ColumnInt(Col: integer): Int64; overload;
    /// return a Column floating point value of the current Row, first Col is 0
    function ColumnDouble(Col: integer): double; overload;
    /// return a Column floating point value of the current Row, first Col is 0
    function ColumnDateTime(Col: integer): TDateTime; overload;
    /// return a column date and time value of the current Row, first Col is 0
................................................................................
      exit;
    with Execute(SQL,[]) do
      while Step do begin
        F.ColumnName := trim(ColumnUTF8(0));
        F.ColumnTypeNative := trim(ColumnUTF8(1));
        F.ColumnLength := ColumnInt(2);
        F.ColumnPrecision := ColumnInt(3);
        if ColumnNull(4) then // e.g. for plain NUMERIC in Oracle
          F.ColumnScale := -1 else
          F.ColumnScale := ColumnInt(4);
        F.ColumnType := ColumnTypeNativeToDB(F.ColumnTypeNative,F.ColumnScale);
        if ColumnInt(5)>0 then
          F.ColumnIndexed := true;
        FA.Add(F);
      end;
  end;
  SetLength(Fields,n);
................................................................................
    exit;
  with Execute(SQL,[]) do
    while Step do begin
      F.ColumnName := trim(ColumnUTF8(0));
      F.ColumnTypeNative := trim(ColumnUTF8(1));
      F.ColumnLength := ColumnInt(2);
      F.ColumnPrecision := ColumnInt(3);
      if ColumnNull(4) then // e.g. for plain NUMERIC in Oracle
        F.ColumnScale := -1 else
        F.ColumnScale := ColumnInt(4);
      F.ColumnType := ColumnTypeNativeToDB(F.ColumnTypeNative,F.ColumnScale);
      case FindCSVIndex('IN,OUT,INOUT',ColumnUTF8(5),',',false) of
        0: F.ColumnParamType := paramIn;
        2: F.ColumnParamType := paramInOut;
      else // any other is assumed as out
        F.ColumnParamType := paramOut;
      end;

Changes to SynopseCommit.inc.

1
'1.18.3303'
|
1
'1.18.3304'