Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Parameter of type binary(8) can be confused with type rowversion #2762

Open
1 task done
staticlibs opened this issue Jul 20, 2024 · 1 comment
Open
1 task done
Labels
bug Something isn't working

Comments

@staticlibs
Copy link
Contributor

staticlibs commented Jul 20, 2024

What happened?

When sp_executesql is called through RPC and parameter of type binary(8) is supplied, then this parameter PgType is determined as rowversion instead of binary(8). There is no typmodin registered for rowversion, so zero Oid is returned for it and query fails with cache lookup failed for function 0.

It seems to happen only with RPC calls, can be reproduced with the following C# program:

using System.Data;
using System.Text;
using Microsoft.Data.SqlClient;

class Program
{
    static void Main()
    {
        string cstr = "Data Source=192.168.122.1,1433;Initial Catalog=master;User ID=jdbc_user;Password=12345678;Trust Server Certificate=yes;Connection Timeout=600";
        using SqlConnection conn = new(cstr);
        conn.Open();
        string sql = "select 'foo' where @P1 is not null";
        using SqlCommand cmd = new SqlCommand(sql, conn);
        cmd.Parameters.Add("@P1", SqlDbType.Binary, 8).Value = Encoding.ASCII.GetBytes("foo");
        using SqlDataReader reader = cmd.ExecuteReader();
        while (reader.Read())
        {
            Console.WriteLine("{0}", reader.GetString(0));
        }
    }
}
> dotnet run
Unhandled exception. Microsoft.Data.SqlClient.SqlException (0x80131904): cache lookup failed for function 0
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
...

This happens because rowversion is registered as binary with maxLen 8, and if PgOid is looked up by TDS binary type with maxLen 8 - then rowversion is returned for it.

There is an easy workaround - to not supply maxLen to lookup call when the type is binary. But I wonder if there should be a more general solution to this.

Version

BABEL_4_X_DEV (Default)

Extension

babelfishpg_tds

Which flavor of Linux are you using when you see the bug?

Fedora

Relevant log output

fmgr_info_cxt_security(Oid functionId, FmgrInfo * finfo, MemoryContext mcxt, _Bool ignore_security) (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/utils/fmgr/fmgr.c:193)
fmgr_info(Oid functionId, FmgrInfo * finfo) (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/utils/fmgr/fmgr.c:139)
OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1) (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/utils/fmgr/fmgr.c:1576)
babelfishpg_tds.so!GetTypModForToken(ParameterToken token) (/home/alex/projects/postgres/dev/babelfish_extensions/contrib/babelfishpg_tds/src/backend/tds/tdsresponse.c:2475)
babelfishpg_tds.so!DeclareVariables(TDSRequestSP req, FunctionCallInfo * fcinfo, unsigned long options) (/home/alex/projects/postgres/dev/babelfish_extensions/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c:296)
babelfishpg_tds.so!SPExecuteSQL(TDSRequestSP req) (/home/alex/projects/postgres/dev/babelfish_extensions/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c:529)
babelfishpg_tds.so!ProcessRPCRequest(TDSRequest request) (/home/alex/projects/postgres/dev/babelfish_extensions/contrib/babelfishpg_tds/src/backend/tds/tdsrpc.c:3623)
babelfishpg_tds.so!ProcessTDSRequest(TDSRequest request) (/home/alex/projects/postgres/dev/babelfish_extensions/contrib/babelfishpg_tds/src/backend/tds/tdsprotocol.c:386)
babelfishpg_tds.so!TdsSocketBackend() (/home/alex/projects/postgres/dev/babelfish_extensions/contrib/babelfishpg_tds/src/backend/tds/tdsprotocol.c:635)
babelfishpg_tds.so!pe_process_command() (/home/alex/projects/postgres/dev/babelfish_extensions/contrib/babelfishpg_tds/src/backend/tds/tds_srv.c:450)
PostgresMain(const char * dbname, const char * username) (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/tcop/postgres.c:4665)
babelfishpg_tds.so!pe_mainfunc(Port * port) (/home/alex/projects/postgres/dev/babelfish_extensions/contrib/babelfishpg_tds/src/backend/tds/tds_srv.c:384)
BackendRun(Port * port) (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/postmaster/postmaster.c:4640)
BackendStartup(Port * port) (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/postmaster/postmaster.c:4367)
ServerLoop() (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/postmaster/postmaster.c:1953)
PostmasterMain(int argc, char ** argv) (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/postmaster/postmaster.c:1499)
main(int argc, char ** argv) (/home/alex/projects/postgres/dev/postgresql_modified_for_babelfish/src/backend/main/main.c:198)

Code of Conduct

  • I agree to follow this project's Code of Conduct.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants