denisenkom / pytds

Python DBAPI driver for MSSQL using pure Python TDS (Tabular Data Stream) protocol implementation
MIT License
190 stars 52 forks source link

Named Parameters, NULL handling and RAISERROR #118

Open jholladay10 opened 3 years ago

jholladay10 commented 3 years ago

I'm sending multiple statements using the named parameters mechanism. I like to use RAISERROR, which does sprintf substitution. So my %d in my RAISERROR statement is tripping up the operation % rename in pytds.

It also looks like the code is attempting to get around not being able to infer the type from the parameter values if the value is NONE. Unless I'm missing something, my named parameters would all have to be %()s in the sql in order for this to work. I'm thinking that's unnecessary.

My suggestion is to allow the caller to optionally specify a type with a value in a tuple. Infer the type if one isn't provided explicitly. We're planning to do this. I can provide code if you want.

jholladay10 commented 3 years ago

I now see that it should be possible to pass a Column object in as a value. Is that the intended solution? If so, it would be nice if the operation % rename only occurred if the rename was actually required, giving the caller the opportunity to avoid the rename consequences altogether if it's unnecessary.

What about something like this?

        elif isinstance(params, dict):
            # prepend names with @
            rename = {}
            for name, value in params.items():
                if value is None:
                    rename[name] = 'NULL'
                else:
                    if name.startswith('@'):
                        mssql_name = name
                    else:
                        mssql_name = '@{0}'.format(name)
                        rename[name] = mssql_name
                    named_params[mssql_name] = value
            if rename:
                operation = operation % rename