SQL Server native ODBC driver

Hi!

One of our clients is currently using the "SQL Server" ODBC driver and both insert and update cause an error: "Error -1: [Microsoft][ODBC SQL Server Driver]Invalid precision value" on several Aurelius entities.
The SQL seems to be correct but we are always getting the error above. It's worth noting that in some cases the update works but not the insert.
Any ideas what may be happening here or do you need more details? I have a hunch that you may have an answer about this. If you do not, I will happily provide more details.

Cheers!

I suggest that first you try to update the MS SQL Server ODBC/Native client driver in such computer. Maybe it's an issue with an old client.

Hi!
Unfortunately that's a non-solution. We know it's a very outdated driver but we have no direct access to their systems. They have an intensely managed environment and are hellbent sideways over into not updating anything unless there is absolutely zero other way. From 1 to 10, the difficulty of getting them to update their environment is 125.

Have you ever encountered this kind of error? It may be present in other drivers as well and we get it even with a very simple entity such as this:

  [AbstractEntity]
  TIDLogModelBase = class( TIDModelBase, IDataLog )
  strict private
    [Column('USER_INS', [], 50)]
    FUSER_INS: Nullable<string>;

    [Column('DATA_INS', [])]
    FDATA_INS: Nullable<TDateTime>;

    [Column('USER_UPD', [], 50)]
    FUSER_UPD: Nullable<string>;

    [Column('DATA_UPD', [])]
    FDATA_UPD: Nullable<TDateTime>;

    FUnixConvert: IUnixDateTimeConvert;
    FStringConvert: INullableString;
  strict protected
    function GetUserIns: string;
    function GetDataIns: Int64;
    procedure SetUserIns( const Value: string );
    procedure SetDataIns( const Value: Int64 );
    function GetUserUpd: string;
    function GetDataUpd: Int64;
    procedure SetUserUpd( const Value: string );
    procedure SetDataUpd( const Value: Int64 );
  public
    constructor Create; override;
    property USER_INS: Nullable<string> read FUSER_INS write FUSER_INS;
    property DATA_INS: Nullable<TDateTime> read FDATA_INS write FDATA_INS;
    property USER_UPD: Nullable<string> read FUSER_UPD write FUSER_UPD;
    property DATA_UPD: Nullable<TDateTime> read FDATA_UPD write FDATA_UPD;
  end;
  
  [AbstractEntity]
  TIDNullableDescription250WithLog= class( TIDLogModelBase )
  strict private
    [Column('DESCRIZIONE', [], 250)]
    FDescrizione: Nullable<string>;
    procedure SetDescription(const Value: Nullable<string>);
  public
    property Descrizione: Nullable<string> read FDescrizione write SetDescription;
  end;

  [Enumeration(TEnumMappingType.emInteger)]
  TSchedulePeriod = ( spHourly, spDaily, spWeekly );
  // un semplice contenitore di info relative al Task schedulato, usato per la transizione dal TaskScheduler ai Task su server REST
  [Entity,Automapping]
  [Table('CMTTASKS')]
  TCMTTASKS = class( TIDNullableDescription250WithLog )
  private
    [Column('TASK', [TColumnProp.Required], 50)]
    FTASK: string;
    [Column('PERIODO',[TColumnProp.Required])]
    FPERIODO: TSchedulePeriod;

    [Column('DATA_INIZIO', [])]
    FDATA_INIZIO: Nullable<TDateTime>;

    [Column('ATTIVO',[],1)]
    FATTIVO: Nullable<string>;

    [Column('LAST_EXEC', [],50)]
    FLAST_EXEC: Nullable<string>;

    [Column('NEXT_EXEC', [],50)]
    FNEXT_EXEC: Nullable<string>;
  public
    property TASK: string read FTASK write FTASK;
    property PERIODO: TSchedulePeriod read FPERIODO WRITE FPERIODO;
    property DATA_INIZIO: Nullable<TDateTime> read FDATA_INIZIO write FDATA_INIZIO;
    property ATTIVO: Nullable<string> read FATTIVO write FATTIVO;
    property LAST_EXEC: Nullable<string> read FLAST_EXEC write FLAST_EXEC;
    property NEXT_EXEC: Nullable<string> read FNEXT_EXEC write FNEXT_EXEC;
  end;
  

Obviously the concrete entity being TCMTTASKS. Now, the way tasks are organized is this; task properties are stored in the tables and task names coming from there are compared to set task names in the code and executed accordingly.
This is the code inside the POST for the service:

var
  PostValidate: IScheduledTaskPostValidate;
  Entity: TCMTTASKS;
begin
  if UTF8ToString(Item.NomeTask).IsEmpty then
  begin
    MakeErrorStatus(ResultStatus, RESULT_CODE_BAD_INPUT_PARAMETERS,'Item.NomeTask empty');
    Exit;
  end;
  PostValidate := TScheduledTasksPostValidate.Create;
  InitServiceInterface(PostValidate);
  PostValidate.ObjectToValidate := Item;
  if not PostValidate.Validate then
  begin
    MakeErrorStatus(ResultStatus, PostValidate);
    Exit;
  end;
  try
    Entity := TCMTTASKS.Create;
    ORM := Item;
    Entity.ID := Item.id;
    Entity.TASK := UTF8ToString(Item.NomeTask);
    Entity.Descrizione := UTF8ToString(Item.Descrizione);
    case Item.Periodo of
      1: Entity.PERIODO := spHourly;
      2: Entity.PERIODO := spDaily;
      3: Entity.PERIODO := spWeekly;
      else
        Entity.PERIODO := spDaily;
  end;
  Entity.DATA_INIZIO := System.DateUtils.UnixToDateTime(Item.DataInizio);
  if Item.Attivo then
    Entity.ATTIVO := 'T'
  else
    Entity.ATTIVO := 'F';
  if Item.DataUltimaEsecuzione <> UNIX_TIMESTAMP_NULL_VALUE then
    Entity.LAST_EXEC := FormatDateTime('dd/mm/yyyy hh:nn:ss',System.DateUtils.UnixToDateTime(Item.DataUltimaEsecuzione));
  if Item.DataProssimaEsecuzione <> UNIX_TIMESTAMP_NULL_VALUE then
    Entity.NEXT_EXEC := FormatDateTime('dd/mm/yyyy hh:nn:ss',System.DateUtils.UnixToDateTime(Item.DataProssimaEsecuzione));
    ObjectManager.SaveOrUpdate(Entity);
    MakeErrorStatus(ResultStatus, RESULT_CODE_SUCCESS,'');
    TBFiveRestServer( Server ).AddOrUpdateTask(Result);
  except
    on E: Exception do
    begin
      MakeErrorStatus(ResultStatus, RESULT_CODE_EXCEPTION_TRAPPED, E.Message);
      Exit;
    end;
  end;
end;

This is, of course, simplified BUT TESTED before being posted and causing the error specified in the OP. A similar code for the update, however, DOES NOT cause the issue, although using our more refined system (which is needed because our entities intermingle quite a bit so we have a system to avoid replicating code).

Can you please offer ideas as to how to avoid said error? I am fairly certain that ultimately the problem is the driver's but as I was saying above this client is extremely averse to change and we have no
timeframe even on whether or not they will update it. 

Thanks!

Well, what can I say about this. I understand that it's completely your business and customer, but software has requirements. What should you do if the customer complains that your software doesn't work in his Windows 98 installation and that updating the OS is out of the question?

If the driver is very outdated, it's a high chance that the software is not working properly because of that, and the driver should be updated because the version he's using is not supported.

Having said that, we can try to help you if you can help us. Are you able to:

  1. Check which driver version he's using.
  2. Install such driver in your development machine and
  3. Create a project that reproduces the issue in your controlled development environment?

This way we might be able to do so in our environment here, reproduce the issue and try to find a solution. If the solution proves to be not complex or time consuming to be solved then we can try to implement it.

Hi!
First off, thanks!
I get that it's a big ask and tbh I thought other people may have encountered this scenario because for some types of customers (fi banks) is fairly common.
I will try to get a controlled sample running and let you know.

Thank you!

Please find a very narrowed-down project attached.
ODBCBugTest.zip (8.1 KB)

Thank you for the project. But unfortunately I can't reproduce the problem. But of course, my environment is not the same as your customer.
So I need more information:

  1. Are you able to reproduce the issue in your development computer, or is it only reproducible at your customer?
  2. What is the exact SQL Server driver version that causes the issue to happen?

This is what I have:

Hi!

This is our driver and we see the issue:
immagine

It appears we are several builds behind and yes, we can repro the issue.

Thanks

Unfortunately, I just cannot reproduce the issue.

Since you are able to reproduce it at your side, can you please try to provide more information? Like the call stack at the moment of the error, so at least we have an idea of the exact line in source code that is causing the error, the SQL statement being executed, etc.?