myservicesuni.pas

来自「CrLab UniDAC 1.0 include sources」· PAS 代码 · 共 1,295 行 · 第 1/3 页

PAS
1,295
字号
        if Byte(Def[1]) = Byte('-') then
          Res := - IntAt(1, i - 1) / HoursPerDay - Res
        else
          Res :=   IntAt(0, i)     / HoursPerDay + Res;
      end;
      FIELD_TYPE_DATETIME: // YYYY-MM-DD HH:MM:SS
      begin
        Result := TryEncodeDate(IntAt(0, 4), IntAt(5, 2), IntAt(8, 2), Res);
        if Result then begin
          Result := TryEncodeTime(IntAt(11, 2), IntAt(14, 2), IntAt(17, 2), 0, t);
          if Res > 0 then
            Res := Res + t
          else
            Res := Res - t;
        end;
      end;
    end;
  end;

var
  MetaData: TDAMetaData;
  TableName, Schema: string;
  p: integer;
  NameField, DefField: TField;
  Field: TField;
  FieldDesc: TMySQLFieldDesc;
  Def: string;
  dt: TDateTime;
begin
  if not FDataSet.Options.DefaultValues or (FDataSet.Fields.Count = 0) or (FUpdatingTableInfoIdx = - 1) then
    Exit;

  TableName := GetTablesInfo[FUpdatingTableInfoIdx].TableNameFull;
  p := Pos('.', TableName);
  if p > 0 then begin
    Schema := Copy(TableName, 1, p - 1);
    TableName := Copy(TableName, p + 1, Length(TableName));
  end
  else
    Schema := '';

  MetaData := UsedConnection.CreateMetaData;
  try
    MetaData.MetaDataKind := 'Columns';
    MetaData.Restrictions.Text := 'table_schema=' + Schema +
      #13#10'table_name=' + TableName;

    MetaData.Open;
    NameField := MetaData.FieldByName('COLUMN_NAME');
    DefField := MetaData.FieldByName('DEFAULT_VALUE');
    while not MetaData.Eof do begin
      Field := FDataSet.FindField(NameField.AsString);
      if (Field <> nil) and not DefField.IsNull then begin
        Def := DefField.AsString;
        if DefaultExpressionOldBehavior then begin
          FieldDesc := FDataSet.GetFieldDesc(Field) as TMySQLFieldDesc;
          case Field.DataType of
            ftBoolean:
              Field.DefaultExpression := BoolToStr(Def <> '0', True);
            ftFloat, ftBCD{$IFDEF VER6P}, ftFMTBCD{$ENDIF}:
              Field.DefaultExpression := StringReplace(Def, '.', DecimalSeparator, [rfReplaceAll]);
            ftDateTime:
              if (Def <> '') and DateTimeFromStr(Def, FieldDesc, dt) then
                Field.DefaultExpression := DateTimeToStr(dt);
            ftDate:
              if (Def <> '') and DateTimeFromStr(Def, FieldDesc, dt) then
                Field.DefaultExpression := DateToStr(dt);
            ftTime:
              if (Def <> '') and DateTimeFromStr(Def, FieldDesc, dt) then
                Field.DefaultExpression := TimeToStr(dt);
            else
              Field.DefaultExpression := Def;
          end;
        end
        else begin
          if Def <> 'CURRENT_TIMESTAMP' then
            Def := AnsiQuotedStr(Def, '''');
          Field.DefaultExpression := Def;
        end;
      end;
      MetaData.Next;
    end;
  finally
    MetaData.Free;
  end;
end;

function TCustomMyDataSetService.GetRecCount: integer;
  function GetCount(const s: string): longint;
  var
    UQ: TCustomDADataSet;
    i: integer;
    MonitorClass: TDASQLMonitorClass;
    MessageID: cardinal;
  begin
    FUpdater.CheckUpdateQuery(stCustom);
    UQ := FUpdater.UpdateQuery as TCustomDADataSet;
    UQ.SQL.Text := s;

    UQ.Macros.Assign(FDataSet.Macros);
    for i := 0 to FDataSet.Params.Count - 1 do
      UQ.Params[i].Assign(FDataSet.Params[i]);

    MonitorClass := TDASQLMonitorClass(TDBAccessUtils.SQLMonitorClass(UsedConnection));
    if not TDBAccessUtils.GetLockDebug(FDataSet) and (MonitorClass.HasMonitor or FDataSet.Debug) then
      MonitorClass.SQLExecute(FDataSet, s, UQ.Params, 'Get RecCount', MessageID, True);

    UQ.Execute;
    Result := UQ.Fields[0].AsInteger;

    if not TDBAccessUtils.GetLockDebug(FDataSet) and (MonitorClass.HasMonitor or FDataSet.Debug) then
      MonitorClass.SQLExecute(FDataSet, s, UQ.Params, 'Get RecCount', MessageID, False);
  end;

var
  Parser: TMyParser;
  SelectPos: integer;
  FromPos: integer;
  s: string;
  Lexem: integer;
  DelimiterPos: integer;
  HaveDistinct: boolean;

begin
  Result := 0;
  if (not IsFetchAll and FDataSet.Options.QueryRecCount) // DefaultResultSet with FetchAll = False
    and not ((FDataSet.Params.Count > 0) and (FDataSet.Params[0].ParamType = ptResult)) then begin // Current SQL does not have RETURN parameter
    s := FDataSet.FinalSQL;
    s := {$IFDEF CLR}CoreLab.Dac.{$ENDIF}DBAccess._SetOrderBy(s, '', TMyParser);
    Parser := TMyParser.Create(s);
    Parser.OmitBlank := True;
    Parser.OmitComment := True;
    try
      if Parser.ToLexem(lxSELECT) <> lcEnd then begin
        SelectPos := Parser.CurrPos;
        Lexem := Parser.GetNextCode;
        HaveDistinct := (Lexem = lxDISTINCT) or (Lexem = lxDISTINCTROW);

        if Parser.ToLexem(lxFROM) <> lcEnd then begin
          FromPos := Parser.CurrPos;

          if Parser.ToLexem(lxLIMIT) <> lcEnd then begin
            if Parser.ToLexem(7) <> lcEnd then // ';'
              DelimiterPos := Parser.CurrPos
            else
              DelimiterPos := MaxInt;
            s := Copy(s, 1, SelectPos) + ' COUNT(*) FROM (SELECT ' + Copy(s, SelectPos + 1, DelimiterPos - 1 - SelectPos) + ') q' + Copy(s, DelimiterPos, MaxInt);
          end
          else
          if HaveDistinct then
            s := Copy(s, 1, SelectPos) + ' COUNT(' + Copy(s, SelectPos + 1, FromPos - 4 - SelectPos) + ')' + Copy(s, FromPos - 4 {length('FROM')}, MaxInt)
          else
            s := Copy(s, 1, SelectPos) + ' COUNT(*)' + Copy(s, FromPos - 4 {length('FROM')}, MaxInt);

          Result := GetCount(s);
        end;
      end;
    finally
      Parser.Free;
    end;
  end
  else
    Result := inherited GetRecCount;
end;

procedure TCustomMyDataSetService.SetNumberRange(FieldDef: TFieldDef);
var
  Field: TField;
  FieldDesc: TMySQLFieldDesc;
{$IFDEF VER6P}
  e: Extended;
{$ENDIF}

begin
  Field := FDataSet.FindField(FieldDef.Name);
  if (Field <> nil)
    and (Field is TNumericField) then begin
    FieldDesc := TMySQLFieldDesc(FDataSet.GetFieldDesc(Field));
    case FieldDesc.MySQLType of // Must be sync with ConvertMySQLTypeToInternalFormat
      // Integer fields
      FIELD_TYPE_DECIMAL, FIELD_TYPE_NEWDECIMAL: begin // DECIMAL
        if Field is TFloatField then begin
          TFloatField(Field).MaxValue :=
            IntPower(10, FieldDesc.Length - FieldDesc.Scale) -
            IntPower(10, - Integer(FieldDesc.Scale));
          TFloatField(Field).MinValue := - TFloatField(Field).MaxValue;
        end
        else
        if Field is TBCDField then begin
          TBCDField(Field).MaxValue :=
            IntPower(10, FieldDesc.Length - FieldDesc.Scale) -
            IntPower(10, - Integer(FieldDesc.Scale));
          TBCDField(Field).MinValue := - TBCDField(Field).MaxValue;
        end
        else
      {$IFDEF VER6P}
        if Field is TFMTBCDField then begin
          e :=
            IntPower(10, FieldDesc.Length - FieldDesc.Scale) -
            IntPower(10, - Integer(FieldDesc.Scale));
          TFMTBCDField(Field).MaxValue := FloatToStr(e);
          TFMTBCDField(Field).MinValue := FloatToStr(- e);
        end
        else
      {$ENDIF}
          Assert(False, Field.ClassName);
      end;
      FIELD_TYPE_TINY: // TINYINT
        if FieldDesc.IsUnsigned then
        begin
          TIntegerField(Field).MinValue := 0;
          TIntegerField(Field).MaxValue := 255;
        end
        else
        begin
          TIntegerField(Field).MinValue := -128;
          TIntegerField(Field).MaxValue := 127;
        end;

      FIELD_TYPE_SHORT: // SMALLINT
        if FieldDesc.IsUnsigned then
        begin
          TIntegerField(Field).MinValue := 0;
          TIntegerField(Field).MaxValue := 65535;
        end
        else
        begin
          TIntegerField(Field).MinValue := -32768;
          TIntegerField(Field).MaxValue := 32767;
        end;

      FIELD_TYPE_LONG, FIELD_TYPE_LONGLONG: // INT
        if Field is TIntegerField then
          if FieldDesc.IsUnsigned then
          begin
            TIntegerField(Field).MinValue := 0;
            TIntegerField(Field).MaxValue := 0; // 4294967295; - not supported by Delphi
          end
          else
          begin
            TIntegerField(Field).MinValue := -2147483647;
            TIntegerField(Field).MaxValue := 2147483647;
          end;

      // FIELD_TYPE_LONGLONG:; // BIGINT - does not need to set bounds

      FIELD_TYPE_INT24: begin// MEDIUMINT
        // ??? Error in Delphi? Does not set range value
        // May be d5/d6?

        Assert(Field is TIntegerField);
        if FieldDesc.IsUnsigned then
        begin
          TIntegerField(Field).MinValue := 0;
          TIntegerField(Field).MaxValue := 16777215;
        end
        else
        begin
          TIntegerField(Field).MinValue := -8388608;
          TIntegerField(Field).MaxValue := 8388607;
        end;
      end;

      // Float fields
      FIELD_TYPE_FLOAT: // FLOAT
      begin
        TFloatField(Field).Precision := FieldDesc.Length;
        TFloatField(Field).MinValue := -3.402823466E+38;
        TFloatField(Field).MaxValue :=  3.402823466E+38;
      end;
      FIELD_TYPE_DOUBLE: // DOUBLE
      begin
        TFloatField(Field).Precision := FieldDesc.Length;
        TFloatField(Field).MinValue := -1.7976931348623157E+308;
        TFloatField(Field).MaxValue :=  1.7976931348623157E+308;
      end;

      FIELD_TYPE_YEAR:
      begin
        Assert(Field is TIntegerField);
        case FieldDesc.Length of
          2: begin
            TIntegerField(Field).MinValue := 0;
            TIntegerField(Field).MaxValue := 99;
          end;
          4: begin
            TIntegerField(Field).MinValue := 0;
            TIntegerField(Field).MaxValue := 255;
          end;
          else
            Assert(False);
        end;
      end;
    end;
  end;
end;

function TCustomMyDataSetService.QuoteName(const AName: string): string;
begin
  Result := QuoteName(AName, FLeftQuote, FRightQuote);
end;

function TCustomMyDataSetService.QuoteName(const AName: string; const LeftQuote, RightQuote: string): string;
begin
  Result := TMyTableInfo.NormalizeName(AName, LeftQuote[1], RightQuote[1], FDataSet.Options.QuoteNames);
end;

function TCustomMyDataSetService.UnQuoteName(const AName: string): string;
begin
  Result := UnbracketIfPossible(AName);
end;

function TCustomMyDataSetService.SetProp(Prop: integer; const Value: variant): boolean;
begin
  Result := True;
  case Prop of
    prCheckRowVersion:
      FCheckRowVersion := Value;
    prLockType:
      FLockType := TLockRecordTypeI(Value);
  else
    Result := inherited SetProp(Prop, Value);
  end;
end;

// Open next rowset in statement. if rowset not returne theh OpenNext return False. If statement has error, then raised exception
function TCustomMyDataSetService.OpenNext: boolean;
var
  v: variant;
begin
  if not FDataSet.Active then begin
    FDataSet.Open;
    Result := True;
  end
  else begin
    BeginConnection;
    try
      if FDataSet.Prepared then
        DatabaseError(SOpenNextPreparedSQL);
      if IsFetchAll then
        DatabaseError(SOpenNextVsFetchAll);

      FDataSet.Close;
      FDataSet.Unprepare;

      GetIRecordSet.GetProp(prIsCanOpenNext, v);
      Result := v;

      if Result then
        try
          GetIRecordSet.SetProp(prOpenNext, True);
          FDataSet.FieldDefs.Updated := False;
          FDataSet.Open;
        finally
          GetIRecordSet.SetProp(prOpenNext, False);
        end;
    finally
      EndConnection;
    end;
  end;
end;

function TCustomMyDataSetService.GetIConnection: TMySQLConnection;
begin
  Result := TMySQLConnection(TDBAccessUtils.GetIConnection(UsedConnection));
  Assert(Result <> nil); //upd should be error
end;

function TCustomMyDataSetService.GetIRecordSet: TMySQLRecordSet;
begin
  Result := TMySQLRecordSet(inherited GetIRecordSet);
end;

function TCustomMyDataSetService.IsFullRefresh: boolean;
begin
  Result := inherited IsFullRefresh;
end;

{ TCustomMyDataTypesMap }

class function TCustomMyDataTypesMap.GetDataType(FieldType: TFieldType): integer;
begin
{$IFNDEF VER10P}
  if Integer(FieldType) = Integer(ftFixedWideChar) then
    FieldType := ftWideString;
{$ENDIF}

  Result := inherited GetDataType(FieldType);
end;

class function TCustomMyDataTypesMap.GetFieldType(DataType: Word): TFieldType;
begin
  case DataType of
    dtInt8:
      Result := ftSmallint;
    dtInt16:
      Result := ftSmallint;
    dtInt64:
      Result := ftLargeInt;
    dtWord:
      Result := ftWord;
    dtBoolean:
      Result := ftBoolean;
    dtCurrency:
      Result := ftCurrency;
  else
    Result := inherited GetFieldType(DataType);
  end;
end;

{ TMyServerEnumerator }

function TMyServerEnumerator.SetProp(Prop: integer; const Value: variant): boolean;
begin
  Result := inherited SetProp(Prop, Value);
end;

function TMyServerEnumerator.GetProp(Prop: integer; var Value: variant): boolean;
begin
  Result := inherited GetProp(Prop, Value);
end;

procedure TMyServerEnumerator.GetServerList(List: TStrings);
begin
{$IFDEF MSWINDOWS}
  CRNetManager.GetServerList(List, 'mysql');
{$ENDIF}
end;

end.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?