Repository: duckdb/duckdb (language: python)

Issue:
No function matches 'bitstring(BIT, INTEGER_LITERAL)'
### What happens?

The [bitstring function](https://duckdb.org/docs/sql/functions/bitstring.html#bitstringbitstring-length) doesn't work. The given example results in this error:

```
Binder Error: No function matches the given name and argument types 'bitstring(BIT, INTEGER_LITERAL)'. You might need to add explicit type casts.
	Candidate functions:
	bitstring(VARCHAR, INTEGER) -> BIT

LINE 1: SELECT bitstring('1010'::BITSTRING, 7);
```

### To Reproduce

```sql
SELECT bitstring('1010'::BITSTRING, 7);
```

### OS:

Linux

### DuckDB Version:

1.0.0

### DuckDB Client:

CLI

### Hardware:

_No response_

### Full Name:

Liam Diprose

### Affiliation:

Liam Diprose

### What is the latest build you tested with? If possible, we recommend testing with the latest nightly build.

I have not tested with any build

### Did you include all relevant data sets for reproducing the issue?

Yes

### Did you include all code required to reproduce the issue?

- [X] Yes, I have

### Did you include all relevant configuration (e.g., CPU architecture, Python version, Linux distribution) to reproduce the issue?

- [X] Yes, I have


Discussion / hints:
Hi, indeed. As a temporary workaround, the following works:
```sql
SELECT bitstring('1010', 7);
```


Fix patch:
diff --git a/src/common/types/bit.cpp b/src/common/types/bit.cpp
index f263c2c42975..12293592519f 100644
--- a/src/common/types/bit.cpp
+++ b/src/common/types/bit.cpp
@@ -22,7 +22,7 @@ idx_t Bit::ComputeBitstringLen(idx_t len) {
 	return result;
 }
 
-static inline idx_t GetBitPadding(const string_t &bit_string) {
+static inline idx_t GetBitPadding(const bitstring_t &bit_string) {
 	auto data = const_data_ptr_cast(bit_string.GetData());
 	D_ASSERT(idx_t(data[0]) <= 8);
 	return data[0];
@@ -37,14 +37,14 @@ static inline idx_t GetBitSize(const string_t &str) {
 	return str_len;
 }
 
-uint8_t Bit::GetFirstByte(const string_t &str) {
+uint8_t Bit::GetFirstByte(const bitstring_t &str) {
 	D_ASSERT(str.GetSize() > 1);
 
 	auto data = const_data_ptr_cast(str.GetData());
 	return data[1] & ((1 << (8 - data[0])) - 1);
 }
 
-void Bit::Finalize(string_t &str) {
+void Bit::Finalize(bitstring_t &str) {
 	// bit strings require all padding bits to be set to 1
 	// this method sets all padding bits to 1
 	auto padding = GetBitPadding(str);
@@ -55,7 +55,7 @@ void Bit::Finalize(string_t &str) {
 	Bit::Verify(str);
 }
 
-void Bit::SetEmptyBitString(string_t &target, string_t &input) {
+void Bit::SetEmptyBitString(bitstring_t &target, string_t &input) {
 	char *res_buf = target.GetDataWriteable();
 	const char *buf = input.GetData();
 	memset(res_buf, 0, input.GetSize());
@@ -63,7 +63,7 @@ void Bit::SetEmptyBitString(string_t &target, string_t &input) {
 	Bit::Finalize(target);
 }
 
-void Bit::SetEmptyBitString(string_t &target, idx_t len) {
+void Bit::SetEmptyBitString(bitstring_t &target, idx_t len) {
 	char *res_buf = target.GetDataWriteable();
 	memset(res_buf, 0, target.GetSize());
 	res_buf[0] = ComputePadding(len);
@@ -71,7 +71,7 @@ void Bit::SetEmptyBitString(string_t &target, idx_t len) {
 }
 
 // **** casting functions ****
-void Bit::ToString(string_t bits, char *output) {
+void Bit::ToString(bitstring_t bits, char *output) {
 	auto data = const_data_ptr_cast(bits.GetData());
 	auto len = bits.GetSize();
 
@@ -87,7 +87,7 @@ void Bit::ToString(string_t bits, char *output) {
 	}
 }
 
-string Bit::ToString(string_t str) {
+string Bit::ToString(bitstring_t str) {
 	auto len = BitLength(str);
 	auto buffer = make_unsafe_uniq_array_uninitialized<char>(len);
 	ToString(str, buffer.get());
@@ -117,7 +117,7 @@ bool Bit::TryGetBitStringSize(string_t str, idx_t &str_len, string *error_messag
 	return true;
 }
 
-void Bit::ToBit(string_t str, string_t &output_str) {
+void Bit::ToBit(string_t str, bitstring_t &output_str) {
 	auto data = const_data_ptr_cast(str.GetData());
 	auto len = str.GetSize();
 	auto output = output_str.GetDataWriteable();
@@ -151,12 +151,12 @@ void Bit::ToBit(string_t str, string_t &output_str) {
 string Bit::ToBit(string_t str) {
 	auto bit_len = GetBitSize(str);
 	auto buffer = make_unsafe_uniq_array_uninitialized<char>(bit_len);
-	string_t output_str(buffer.get(), UnsafeNumericCast<uint32_t>(bit_len));
+	bitstring_t output_str(buffer.get(), UnsafeNumericCast<uint32_t>(bit_len));
 	Bit::ToBit(str, output_str);
 	return output_str.GetString();
 }
 
-void Bit::BlobToBit(string_t blob, string_t &output_str) {
+void Bit::BlobToBit(string_t blob, bitstring_t &output_str) {
 	auto data = const_data_ptr_cast(blob.GetData());
 	auto output = output_str.GetDataWriteable();
 	idx_t size = blob.GetSize();
@@ -167,12 +167,12 @@ void Bit::BlobToBit(string_t blob, string_t &output_str) {
 
 string Bit::BlobToBit(string_t blob) {
 	auto buffer = make_unsafe_uniq_array_uninitialized<char>(blob.GetSize() + 1);
-	string_t output_str(buffer.get(), UnsafeNumericCast<uint32_t>(blob.GetSize() + 1));
+	bitstring_t output_str(buffer.get(), UnsafeNumericCast<uint32_t>(blob.GetSize() + 1));
 	Bit::BlobToBit(blob, output_str);
 	return output_str.GetString();
 }
 
-void Bit::BitToBlob(string_t bit, string_t &output_blob) {
+void Bit::BitToBlob(bitstring_t bit, string_t &output_blob) {
 	D_ASSERT(bit.GetSize() == output_blob.GetSize() + 1);
 
 	auto data = const_data_ptr_cast(bit.GetData());
@@ -189,7 +189,7 @@ void Bit::BitToBlob(string_t bit, string_t &output_blob) {
 	}
 }
 
-string Bit::BitToBlob(string_t bit) {
+string Bit::BitToBlob(bitstring_t bit) {
 	D_ASSERT(bit.GetSize() > 1);
 
 	auto buffer = make_unsafe_uniq_array_uninitialized<char>(bit.GetSize() - 1);
@@ -199,7 +199,7 @@ string Bit::BitToBlob(string_t bit) {
 }
 
 // **** scalar functions ****
-void Bit::BitString(const string_t &input, const idx_t &bit_length, string_t &result) {
+void Bit::BitString(const string_t &input, idx_t bit_length, bitstring_t &result) {
 	char *res_buf = result.GetDataWriteable();
 	const char *buf = input.GetData();
 
@@ -216,15 +216,35 @@ void Bit::BitString(const string_t &input, const idx_t &bit_length, string_t &re
 	Bit::Finalize(result);
 }
 
-idx_t Bit::BitLength(string_t bits) {
+void Bit::ExtendBitString(const bitstring_t &input, idx_t bit_length, bitstring_t &result) {
+	uint8_t *res_buf = reinterpret_cast<uint8_t *>(result.GetDataWriteable());
+
+	auto padding = ComputePadding(bit_length);
+	res_buf[0] = static_cast<uint8_t>(padding);
+
+	idx_t original_length = Bit::BitLength(input);
+	D_ASSERT(bit_length >= original_length);
+	idx_t shift = bit_length - original_length;
+	for (idx_t i = 0; i < bit_length; i++) {
+		if (i < shift) {
+			Bit::SetBit(result, i, 0);
+		} else {
+			idx_t bit = Bit::GetBit(input, i - shift);
+			Bit::SetBit(result, i, bit);
+		}
+	}
+	Bit::Finalize(result);
+}
+
+idx_t Bit::BitLength(bitstring_t bits) {
 	return ((bits.GetSize() - 1) * 8) - GetBitPadding(bits);
 }
 
-idx_t Bit::OctetLength(string_t bits) {
+idx_t Bit::OctetLength(bitstring_t bits) {
 	return bits.GetSize() - 1;
 }
 
-idx_t Bit::BitCount(string_t bits) {
+idx_t Bit::BitCount(bitstring_t bits) {
 	idx_t count = 0;
 	const char *buf = bits.GetData();
 	for (idx_t byte_idx = 1; byte_idx < OctetLength(bits) + 1; byte_idx++) {
@@ -235,7 +255,7 @@ idx_t Bit::BitCount(string_t bits) {
 	return count - GetBitPadding(bits);
 }
 
-idx_t Bit::BitPosition(string_t substring, string_t bits) {
+idx_t Bit::BitPosition(bitstring_t substring, bitstring_t bits) {
 	const char *buf = bits.GetData();
 	auto len = bits.GetSize();
 	auto substr_len = BitLength(substring);
@@ -269,7 +289,7 @@ idx_t Bit::BitPosition(string_t substring, string_t bits) {
 	return 0;
 }
 
-idx_t Bit::GetBit(string_t bit_string, idx_t n) {
+idx_t Bit::GetBit(bitstring_t bit_string, idx_t n) {
 	return Bit::GetBitInternal(bit_string, n + GetBitPadding(bit_string));
 }
 
@@ -277,7 +297,7 @@ idx_t Bit::GetBitIndex(idx_t n) {
 	return n / 8 + 1;
 }
 
-idx_t Bit::GetBitInternal(string_t bit_string, idx_t n) {
+idx_t Bit::GetBitInternal(bitstring_t bit_string, idx_t n) {
 	const char *buf = bit_string.GetData();
 	auto idx = Bit::GetBitIndex(n);
 	D_ASSERT(idx < bit_string.GetSize());
@@ -285,12 +305,12 @@ idx_t Bit::GetBitInternal(string_t bit_string, idx_t n) {
 	return (byte & 1 ? 1 : 0);
 }
 
-void Bit::SetBit(string_t &bit_string, idx_t n, idx_t new_value) {
+void Bit::SetBit(bitstring_t &bit_string, idx_t n, idx_t new_value) {
 	SetBitInternal(bit_string, n + GetBitPadding(bit_string), new_value);
 	Bit::Finalize(bit_string);
 }
 
-void Bit::SetBitInternal(string_t &bit_string, idx_t n, idx_t new_value) {
+void Bit::SetBitInternal(bitstring_t &bit_string, idx_t n, idx_t new_value) {
 	uint8_t *buf = reinterpret_cast<uint8_t *>(bit_string.GetDataWriteable());
 
 	auto idx = Bit::GetBitIndex(n);
@@ -305,7 +325,7 @@ void Bit::SetBitInternal(string_t &bit_string, idx_t n, idx_t new_value) {
 }
 
 // **** BITWISE operators ****
-void Bit::RightShift(const string_t &bit_string, const idx_t &shift, string_t &result) {
+void Bit::RightShift(const bitstring_t &bit_string, idx_t shift, bitstring_t &result) {
 	uint8_t *res_buf = reinterpret_cast<uint8_t *>(result.GetDataWriteable());
 	const uint8_t *buf = reinterpret_cast<const uint8_t *>(bit_string.GetData());
 
@@ -321,7 +341,7 @@ void Bit::RightShift(const string_t &bit_string, const idx_t &shift, string_t &r
 	Bit::Finalize(result);
 }
 
-void Bit::LeftShift(const string_t &bit_string, const idx_t &shift, string_t &result) {
+void Bit::LeftShift(const bitstring_t &bit_string, idx_t shift, bitstring_t &result) {
 	uint8_t *res_buf = reinterpret_cast<uint8_t *>(result.GetDataWriteable());
 	const uint8_t *buf = reinterpret_cast<const uint8_t *>(bit_string.GetData());
 
@@ -337,7 +357,7 @@ void Bit::LeftShift(const string_t &bit_string, const idx_t &shift, string_t &re
 	Bit::Finalize(result);
 }
 
-void Bit::BitwiseAnd(const string_t &rhs, const string_t &lhs, string_t &result) {
+void Bit::BitwiseAnd(const bitstring_t &rhs, const bitstring_t &lhs, bitstring_t &result) {
 	if (Bit::BitLength(lhs) != Bit::BitLength(rhs)) {
 		throw InvalidInputException("Cannot AND bit strings of different sizes");
 	}
@@ -353,7 +373,7 @@ void Bit::BitwiseAnd(const string_t &rhs, const string_t &lhs, string_t &result)
 	Bit::Finalize(result);
 }
 
-void Bit::BitwiseOr(const string_t &rhs, const string_t &lhs, string_t &result) {
+void Bit::BitwiseOr(const bitstring_t &rhs, const bitstring_t &lhs, bitstring_t &result) {
 	if (Bit::BitLength(lhs) != Bit::BitLength(rhs)) {
 		throw InvalidInputException("Cannot OR bit strings of different sizes");
 	}
@@ -369,7 +389,7 @@ void Bit::BitwiseOr(const string_t &rhs, const string_t &lhs, string_t &result)
 	Bit::Finalize(result);
 }
 
-void Bit::BitwiseXor(const string_t &rhs, const string_t &lhs, string_t &result) {
+void Bit::BitwiseXor(const bitstring_t &rhs, const bitstring_t &lhs, bitstring_t &result) {
 	if (Bit::BitLength(lhs) != Bit::BitLength(rhs)) {
 		throw InvalidInputException("Cannot XOR bit strings of different sizes");
 	}
@@ -385,7 +405,7 @@ void Bit::BitwiseXor(const string_t &rhs, const string_t &lhs, string_t &result)
 	Bit::Finalize(result);
 }
 
-void Bit::BitwiseNot(const string_t &input, string_t &result) {
+void Bit::BitwiseNot(const bitstring_t &input, bitstring_t &result) {
 	uint8_t *result_buf = reinterpret_cast<uint8_t *>(result.GetDataWriteable());
 	const uint8_t *buf = reinterpret_cast<const uint8_t *>(input.GetData());
 
@@ -396,7 +416,7 @@ void Bit::BitwiseNot(const string_t &input, string_t &result) {
 	Bit::Finalize(result);
 }
 
-void Bit::Verify(const string_t &input) {
+void Bit::Verify(const bitstring_t &input) {
 #ifdef DEBUG
 	// bit strings require all padding bits to be set to 1
 	auto padding = GetBitPadding(input);
diff --git a/src/core_functions/function_list.cpp b/src/core_functions/function_list.cpp
index 16a5dff379ee..ca77e030964d 100644
--- a/src/core_functions/function_list.cpp
+++ b/src/core_functions/function_list.cpp
@@ -116,7 +116,7 @@ static const StaticFunctionDefinition internal_functions[] = {
 	DUCKDB_AGGREGATE_FUNCTION_SET(BitOrFun),
 	DUCKDB_SCALAR_FUNCTION(BitPositionFun),
 	DUCKDB_AGGREGATE_FUNCTION_SET(BitXorFun),
-	DUCKDB_SCALAR_FUNCTION(BitStringFun),
+	DUCKDB_SCALAR_FUNCTION_SET(BitStringFun),
 	DUCKDB_AGGREGATE_FUNCTION_SET(BitstringAggFun),
 	DUCKDB_AGGREGATE_FUNCTION(BoolAndFun),
 	DUCKDB_AGGREGATE_FUNCTION(BoolOrFun),
diff --git a/src/core_functions/scalar/bit/bitstring.cpp b/src/core_functions/scalar/bit/bitstring.cpp
index fc1768850f07..9a9a5eae0f60 100644
--- a/src/core_functions/scalar/bit/bitstring.cpp
+++ b/src/core_functions/scalar/bit/bitstring.cpp
@@ -7,28 +7,46 @@ namespace duckdb {
 //===--------------------------------------------------------------------===//
 // BitStringFunction
 //===--------------------------------------------------------------------===//
+template <bool FROM_STRING>
 static void BitStringFunction(DataChunk &args, ExpressionState &state, Vector &result) {
 	BinaryExecutor::Execute<string_t, int32_t, string_t>(
 	    args.data[0], args.data[1], result, args.size(), [&](string_t input, int32_t n) {
 		    if (n < 0) {
 			    throw InvalidInputException("The bitstring length cannot be negative");
 		    }
-		    if (idx_t(n) < input.GetSize()) {
+		    idx_t input_length;
+		    if (FROM_STRING) {
+			    input_length = input.GetSize();
+		    } else {
+			    input_length = Bit::BitLength(input);
+		    }
+		    if (idx_t(n) < input_length) {
 			    throw InvalidInputException("Length must be equal or larger than input string");
 		    }
 		    idx_t len;
-		    Bit::TryGetBitStringSize(input, len, nullptr); // string verification
+		    if (FROM_STRING) {
+			    Bit::TryGetBitStringSize(input, len, nullptr); // string verification
+		    }
 
 		    len = Bit::ComputeBitstringLen(UnsafeNumericCast<idx_t>(n));
 		    string_t target = StringVector::EmptyString(result, len);
-		    Bit::BitString(input, UnsafeNumericCast<idx_t>(n), target);
+		    if (FROM_STRING) {
+			    Bit::BitString(input, UnsafeNumericCast<idx_t>(n), target);
+		    } else {
+			    Bit::ExtendBitString(input, UnsafeNumericCast<idx_t>(n), target);
+		    }
 		    target.Finalize();
 		    return target;
 	    });
 }
 
-ScalarFunction BitStringFun::GetFunction() {
-	return ScalarFunction({LogicalType::VARCHAR, LogicalType::INTEGER}, LogicalType::BIT, BitStringFunction);
+ScalarFunctionSet BitStringFun::GetFunctions() {
+	ScalarFunctionSet bitstring;
+	bitstring.AddFunction(
+	    ScalarFunction({LogicalType::VARCHAR, LogicalType::INTEGER}, LogicalType::BIT, BitStringFunction<true>));
+	bitstring.AddFunction(
+	    ScalarFunction({LogicalType::BIT, LogicalType::INTEGER}, LogicalType::BIT, BitStringFunction<false>));
+	return bitstring;
 }
 
 //===--------------------------------------------------------------------===//
diff --git a/src/core_functions/scalar/bit/functions.json b/src/core_functions/scalar/bit/functions.json
index 0870e6831426..ac46a530a841 100644
--- a/src/core_functions/scalar/bit/functions.json
+++ b/src/core_functions/scalar/bit/functions.json
@@ -26,6 +26,6 @@
         "description": "Pads the bitstring until the specified length",
         "example": "bitstring('1010'::BIT, 7)",
         "struct": "BitStringFun",
-        "type": "scalar_function"
+        "type": "scalar_function_set"
     }
 ]
\ No newline at end of file
diff --git a/src/include/duckdb/common/types/bit.hpp b/src/include/duckdb/common/types/bit.hpp
index 5a1a8209dde1..cbf599139ec5 100644
--- a/src/include/duckdb/common/types/bit.hpp
+++ b/src/include/duckdb/common/types/bit.hpp
@@ -17,85 +17,88 @@
 
 namespace duckdb {
 
+using bitstring_t = duckdb::string_t;
+
 //! The Bit class is a static class that holds helper functions for the BIT type.
 class Bit {
 public:
 	//! Returns the number of bits in the bit string
-	DUCKDB_API static idx_t BitLength(string_t bits);
+	DUCKDB_API static idx_t BitLength(bitstring_t bits);
 	//! Returns the number of set bits in the bit string
-	DUCKDB_API static idx_t BitCount(string_t bits);
+	DUCKDB_API static idx_t BitCount(bitstring_t bits);
 	//! Returns the number of bytes in the bit string
-	DUCKDB_API static idx_t OctetLength(string_t bits);
+	DUCKDB_API static idx_t OctetLength(bitstring_t bits);
 	//! Extracts the nth bit from bit string; the first (leftmost) bit is indexed 0
-	DUCKDB_API static idx_t GetBit(string_t bit_string, idx_t n);
+	DUCKDB_API static idx_t GetBit(bitstring_t bit_string, idx_t n);
 	//! Sets the nth bit in bit string to newvalue; the first (leftmost) bit is indexed 0
-	DUCKDB_API static void SetBit(string_t &bit_string, idx_t n, idx_t new_value);
+	DUCKDB_API static void SetBit(bitstring_t &bit_string, idx_t n, idx_t new_value);
 	//! Returns first starting index of the specified substring within bits, or zero if it's not present.
-	DUCKDB_API static idx_t BitPosition(string_t substring, string_t bits);
+	DUCKDB_API static idx_t BitPosition(bitstring_t substring, bitstring_t bits);
 	//! Converts bits to a string, writing the output to the designated output string.
 	//! The string needs to have space for at least GetStringSize(bits) bytes.
-	DUCKDB_API static void ToString(string_t bits, char *output);
-	DUCKDB_API static string ToString(string_t str);
+	DUCKDB_API static void ToString(bitstring_t bits, char *output);
+	DUCKDB_API static string ToString(bitstring_t bits);
 	//! Returns the bit size of a string -> bit conversion
 	DUCKDB_API static bool TryGetBitStringSize(string_t str, idx_t &result_size, string *error_message);
 	//! Convert a string to a bit. This function should ONLY be called after calling GetBitSize, since it does NOT
 	//! perform data validation.
-	DUCKDB_API static void ToBit(string_t str, string_t &output);
+	DUCKDB_API static void ToBit(string_t str, bitstring_t &output);
 
 	DUCKDB_API static string ToBit(string_t str);
 
 	//! output needs to have enough space allocated before calling this function (blob size + 1)
-	DUCKDB_API static void BlobToBit(string_t blob, string_t &output);
+	DUCKDB_API static void BlobToBit(string_t blob, bitstring_t &output);
 
 	DUCKDB_API static string BlobToBit(string_t blob);
 
 	//! output_str needs to have enough space allocated before calling this function (sizeof(T) + 1)
 	template <class T>
-	static void NumericToBit(T numeric, string_t &output_str);
+	static void NumericToBit(T numeric, bitstring_t &output_str);
 
 	template <class T>
 	static string NumericToBit(T numeric);
 
 	//! bit is expected to fit inside of output num (bit size <= sizeof(T) + 1)
 	template <class T>
-	static void BitToNumeric(string_t bit, T &output_num);
+	static void BitToNumeric(bitstring_t bit, T &output_num);
 
 	template <class T>
-	static T BitToNumeric(string_t bit);
+	static T BitToNumeric(bitstring_t bit);
 
 	//! bit is expected to fit inside of output_blob (bit size = output_blob + 1)
-	static void BitToBlob(string_t bit, string_t &output_blob);
+	static void BitToBlob(bitstring_t bit, string_t &output_blob);
 
-	static string BitToBlob(string_t bit);
+	static string BitToBlob(bitstring_t bit);
 
 	//! Creates a new bitstring of determined length
-	DUCKDB_API static void BitString(const string_t &input, const idx_t &len, string_t &result);
-	DUCKDB_API static void SetEmptyBitString(string_t &target, string_t &input);
-	DUCKDB_API static void SetEmptyBitString(string_t &target, idx_t len);
+	DUCKDB_API static void BitString(const string_t &input, idx_t len, bitstring_t &result);
+	DUCKDB_API static void ExtendBitString(const bitstring_t &input, idx_t bit_length, bitstring_t &result);
+	DUCKDB_API static void SetEmptyBitString(bitstring_t &target, string_t &input);
+	DUCKDB_API static void SetEmptyBitString(bitstring_t &target, idx_t len);
 	DUCKDB_API static idx_t ComputeBitstringLen(idx_t len);
 
-	DUCKDB_API static void RightShift(const string_t &bit_string, const idx_t &shif, string_t &result);
-	DUCKDB_API static void LeftShift(const string_t &bit_string, const idx_t &shift, string_t &result);
-	DUCKDB_API static void BitwiseAnd(const string_t &rhs, const string_t &lhs, string_t &result);
-	DUCKDB_API static void BitwiseOr(const string_t &rhs, const string_t &lhs, string_t &result);
-	DUCKDB_API static void BitwiseXor(const string_t &rhs, const string_t &lhs, string_t &result);
-	DUCKDB_API static void BitwiseNot(const string_t &rhs, string_t &result);
+	DUCKDB_API static void RightShift(const bitstring_t &bit_string, idx_t shift, bitstring_t &result);
+	DUCKDB_API static void LeftShift(const bitstring_t &bit_string, idx_t shift, bitstring_t &result);
+	DUCKDB_API static void BitwiseAnd(const bitstring_t &rhs, const bitstring_t &lhs, bitstring_t &result);
+	DUCKDB_API static void BitwiseOr(const bitstring_t &rhs, const bitstring_t &lhs, bitstring_t &result);
+	DUCKDB_API static void BitwiseXor(const bitstring_t &rhs, const bitstring_t &lhs, bitstring_t &result);
+	DUCKDB_API static void BitwiseNot(const bitstring_t &rhs, bitstring_t &result);
 
-	DUCKDB_API static void Verify(const string_t &input);
+	DUCKDB_API static void Verify(const bitstring_t &input);
 
 private:
-	static void Finalize(string_t &str);
-	static idx_t GetBitInternal(string_t bit_string, idx_t n);
-	static void SetBitInternal(string_t &bit_string, idx_t n, idx_t new_value);
+	static void Finalize(bitstring_t &str);
+	static idx_t GetBitInternal(bitstring_t bit_string, idx_t n);
+	static void SetBitInternal(bitstring_t &bit_string, idx_t n, idx_t new_value);
 	static idx_t GetBitIndex(idx_t n);
-	static uint8_t GetFirstByte(const string_t &str);
+	static uint8_t GetFirstByte(const bitstring_t &str);
 };
 
 //===--------------------------------------------------------------------===//
 // Bit Template definitions
 //===--------------------------------------------------------------------===//
 template <class T>
-void Bit::NumericToBit(T numeric, string_t &output_str) {
+void Bit::NumericToBit(T numeric, bitstring_t &output_str) {
 	D_ASSERT(output_str.GetSize() >= sizeof(T) + 1);
 
 	auto output = output_str.GetDataWriteable();
@@ -113,20 +116,20 @@ template <class T>
 string Bit::NumericToBit(T numeric) {
 	auto bit_len = sizeof(T) + 1;
 	auto buffer = make_unsafe_uniq_array_uninitialized<char>(bit_len);
-	string_t output_str(buffer.get(), UnsafeNumericCast<uint32_t>(bit_len));
+	bitstring_t output_str(buffer.get(), UnsafeNumericCast<uint32_t>(bit_len));
 	Bit::NumericToBit(numeric, output_str);
 	return output_str.GetString();
 }
 
 template <class T>
-T Bit::BitToNumeric(string_t bit) {
+T Bit::BitToNumeric(bitstring_t bit) {
 	T output;
 	Bit::BitToNumeric(bit, output);
 	return (output);
 }
 
 template <class T>
-void Bit::BitToNumeric(string_t bit, T &output_num) {
+void Bit::BitToNumeric(bitstring_t bit, T &output_num) {
 	D_ASSERT(bit.GetSize() <= sizeof(T) + 1);
 
 	output_num = 0;
diff --git a/src/include/duckdb/core_functions/scalar/bit_functions.hpp b/src/include/duckdb/core_functions/scalar/bit_functions.hpp
index c114d72a68ad..f66427b6d7b5 100644
--- a/src/include/duckdb/core_functions/scalar/bit_functions.hpp
+++ b/src/include/duckdb/core_functions/scalar/bit_functions.hpp
@@ -48,7 +48,7 @@ struct BitStringFun {
 	static constexpr const char *Description = "Pads the bitstring until the specified length";
 	static constexpr const char *Example = "bitstring('1010'::BIT, 7)";
 
-	static ScalarFunction GetFunction();
+	static ScalarFunctionSet GetFunctions();
 };
 
 } // namespace duckdb


Test patch:
diff --git a/test/sql/types/bit/test_bit.test b/test/sql/types/bit/test_bit.test
index 5f561d648f8d..a7a0c0a5d521 100644
--- a/test/sql/types/bit/test_bit.test
+++ b/test/sql/types/bit/test_bit.test
@@ -20,31 +20,47 @@ statement ok
 CREATE TABLE bits (b bit);
 
 # test creating a bitstring of determined size
+
+foreach cast VARCHAR BIT
+
 query I
-SELECT bitstring('0101011', 15);
+SELECT bitstring('0101011'::${cast}, 15);
 ----
 000000000101011
 
 query I
-SELECT bitstring('1', 6);
+SELECT bitstring('1'::${cast}, 6);
 ----
 000001
 
+query I
+SELECT bitstring('1'::${cast}, 1);
+----
+1
+
+query I
+SELECT bitstring('0101011'::${cast}, 203);
+----
+00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101011
+
+query I
+SELECT bitstring('111100001111000010101010'::${cast}, 36);
+----
+000000000000111100001111000010101010
+
 statement error
-SELECT bitstring('0101011', 3);
+SELECT bitstring('0101011'::${cast}, 3);
 ----
 <REGEX>:Invalid Input Error.*Length must be equal or larger than input string.*
 
+# cast
+endloop
+
 statement error
 SELECT bitstring('', 0);
 ----
 <REGEX>:Conversion Error.*Cannot cast empty string to BIT.*
 
-query I
-SELECT bitstring('1', 1);
-----
-1
-
 statement error
 SELECT bitstring('5', 10);
 ----
@@ -55,11 +71,6 @@ SELECT bitstring('0101011');
 ----
 <REGEX>:Binder Error.*No function matches.*
 
-query I
-SELECT bitstring('0101011', 203);
-----
-00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000101011
-
 # insert valid bit strings
 statement ok
 INSERT INTO bits VALUES('101011010'), ('111'), ('1010010101111111001101')