/*
 * Microsoft JDBC Driver for SQL Server Copyright(c) Microsoft Corporation All rights reserved. This program is made
 * available under the terms of the MIT License. See the LICENSE file in the project root for more information.
 */
package com.microsoft.sqlserver.jdbc.connection;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;

import com.microsoft.sqlserver.jdbc.RandomUtil;
import com.microsoft.sqlserver.jdbc.SQLServerDataSource;
import com.microsoft.sqlserver.jdbc.TestUtils;
import com.microsoft.sqlserver.testframework.AbstractTest;
import com.microsoft.sqlserver.testframework.Constants;
import com.microsoft.sqlserver.testframework.DBTable;


@RunWith(JUnitPlatform.class)
@Tag(Constants.xAzureSQLDW)
public class DBMetadataTest extends AbstractTest {
    @Test
    public void testDatabaseMetaData() throws SQLException {
        String functionName = RandomUtil.getIdentifier("proc");
        functionName = DBTable.escapeIdentifier(functionName);
        SQLServerDataSource ds = new SQLServerDataSource();
        ds.setURL(connectionString);

        String sqlDropFunction = "if exists (select * from dbo.sysobjects where id = object_id(N'[dbo]."
                + TestUtils.escapeSingleQuotes(functionName) + "')" + "and xtype in (N'FN', N'IF', N'TF'))"
                + "drop function " + functionName;
        String sqlCreateFunction = "CREATE  FUNCTION " + functionName
                + " (@text varchar(8000), @delimiter varchar(20) = ' ') RETURNS @Strings TABLE "
                + "(position int IDENTITY PRIMARY KEY, value varchar(8000)) AS BEGIN INSERT INTO @Strings VALUES ('DDD') RETURN END ";

        try (Connection con = ds.getConnection(); Statement stmt = con.createStatement()) {
            // drop function
            stmt.execute(sqlDropFunction);
            // create function
            stmt.execute(sqlCreateFunction);

            DatabaseMetaData md = con.getMetaData();
            try (ResultSet arguments = md.getProcedureColumns(null, null, null, "@TABLE_RETURN_VALUE")) {

                if (arguments.next()) {
                    arguments.getString("COLUMN_NAME");
                    arguments.getString("DATA_TYPE"); // call this function to make sure it does not crash
                }
                arguments.getStatement().close();
            }
            stmt.execute(sqlDropFunction);
        }
    }
}

@@ -281,24 +281,86 @@
 nection;%0D%0A%0D%0A
+import static org.junit.jupiter.api.Assertions.assertTrue;%0D%0A%0D%0A
 import java.
@@ -1245,17 +1245,31 @@
         
-f
+String escapedF
 unctionN
@@ -1569,17 +1569,24 @@
 eQuotes(
-f
+escapedF
 unctionN
@@ -1671,25 +1671,32 @@
 unction %22 + 
-f
+escapedF
 unctionName;
@@ -1754,17 +1754,24 @@
 ION %22 + 
-f
+escapedF
 unctionN
@@ -2386,20 +2386,28 @@
 , null, 
-null
+functionName
 , %22@TABL
@@ -2427,18 +2427,16 @@
 E%22)) %7B%0D%0A
-%0D%0A
         
@@ -2480,32 +2480,43 @@
                 
+assertTrue(
 arguments.getStr
@@ -2524,130 +2524,209 @@
 ng(%22
-COLUMN_NAME%22);%0D%0A                    arguments.getString(%22DATA_TYPE%22); // call this function to make sure it does not crash
+PROCEDURE_NAME%22).startsWith(functionName), %22Expected Stored Procedure was not retrieved.%22);%0D%0A                %7D else %7B%0D%0A                    assertTrue(false, %22Expected Stored Procedure was not found.%22);
 %0D%0A  

Fix deadlock by querying only the procedure created (#1423)