IRIS Enable Long Strings
On IRIS version 2024.1.0.262.0 I have a table that store streams as %GlobalCharacterStream.
But depeding on the blob being saved I get the error: [Error: <<MAXSTRING>]
I had that with Caché, but to solve that I'd just enable the long strings on the page System Administration > Configuration > System Configuration > Memory and Startup > Enable Long Strings.
But for Iris I can't find that configuration, I looked on every config page from the portal and couldn't find it.
Btw this blobs are stored on Caché and the system using IRIS is reading from Caché and saving on IRIS.
Where, on IRIS, can I make the same configuration of Long Strings that exists on Caché?
I don't think that long string support is the issue.
Can you provide details on when/where you get the <MAXSTRING> error?
When Inserting on a table with the following SQL:
INSERT INTO ERP.Arquivos (Blob, Descricao, FileName, MimeType, IDIntegracao, Updated, UpdateUser, Inserted, InsertUser) VALUES ({Stream}, 'some Description', 'filename.jpg', 1, 10, CURRENT_TIMESTAMP, 'username', CURRENT_TIMESTAMP, 'username')
Inner Exception: [SQLCODE: <-400>:<Ocorreu um erro fatal>]
[Error: <<MAXSTRING>zExecute+5^%sqlcq.RODOFORCE4.cls54.1>]
[Location: <ServerLoop>]
----------------------------
This SQL works fine when dealing with small streams, but on some larger files I get the error above.
I figured it was the long strings because we had the problem with large SQL's on Caché and we needed to enable the Long Strings Config.
Just to see things clear, the size of a stream is limited by the size of the database (some GBs or even TBs) and the size of the storage media (hdd,sdd), whichever smaller is (less the size of other globals). The size of a table row (all fields together) is limited by the string size (either 32KB or 3.6MB). In a table row you can put a REFERENCE of a stream but not the stream itself.
The Stream is a Blob of an image that has 2.830KB
This blob was inserted on Caché the exacly same way and works, but for that we had to enable the Long Strings config.
When trying the same SQL on IRIS I'm getting the MAXSTRING error, that I suppose it's because the Long Strings config is not enabled.
Please correct me if I'm wrong, but I really don't see any other thing that could be causing that.
It's the first time that I'm using IRIS so it's very possible that I'm missing something, but considering previous experiences with Caché the first thing that comes to my mind is this config.
When looking on IRIS documentation I only find the path "System Administration > Configuration > System Configuration > Memory and Startup > Enable Long Strings."
But when oppening it on IRIS Management Portal the "Enable Long Strings" config just does not exist.
On IRIS, long strings are enabled per default, you can check that
set x="", $e(x,3641144)="z" // OK set x="", $e(x,3641145)="z" // <MAXSTRING> error
String Length Limit
True that, but if there's a known long-but-below-3.5-mb field it can be moved into a separate node for storage so it won't interfere with other fields.
Also class inheritance might split the storage into a few nodes.
I noticed that you are using the {Stream} syntax, which is typical for trigger code or calculated field.
Could you check the following code at your place:
I have saved a 16 MB file without any problems:
The stream was actually a placeholder, the SQL is generated via C# and sent via the IRIS Driver.

This is a print of the error with a part of the actual blob
I tried the same SQL on IRIS via DBeaver and got the same error.
When trying the same SQL on Caché it worked fine.
Just a thought...
Are you using the IRIS ODBC Driver when connecting to IRIS from DBeaver (or C#)?
Just wondering, did you look at the table (class) ERP.Arquivos definition? what is the MAXLEN of Blob?
I had an issue of that sort where MAXLEN only affects odbc/jdbc data
hth, Eyal
MAXLEN is not applicable for %GlobalCharacterStream (Blob). You will get compilation error #5480
Hi Antonio,
Are you using the IRISClient assembly from your IRIS 2024.1.0?
I have Visual Studio 2022, I am using InterSystems.Data.IRISClient.dll from my C:\InterSystems\IRIS20241\dev\dotnet\bin\net7.0.
I have an image file
03/28/2024 09:28 AM 5,261,669 myimage.png
I use following sample .Net app that I borrow from Cache 2018 and modify all Cache references with IRIS references, I have no problem inserting the 5.2MB image file into a blob field in my test table.
Harry
using System;
using System.IO;
// Add the following using statement
using InterSystems.Data.IRISClient;
namespace C_SharpConsoleExample
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class ConsoleApp
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
// Create a connection to Cache
IRISConnection conn = new IRISConnection();
// Cache server Connection Information
// Set Server to your IP address and port to Cache SuperServer port, Log File is optional
conn.ConnectionString = "Server = localhost; Log File=cprovider.log;Port=1972; Namespace=USER; Password = SYS; User ID = _SYSTEM;";
//Open a Connection to Cache
conn.Open();
// Create table with streams
IRISCommand dropCmd = new IRISCommand("drop table Sample.Streams", conn);
try
{
dropCmd.ExecuteNonQuery();
}
catch (Exception ex)
{
//Do nothing
string test = ex.Message;
}
// Create table with streams
IRISCommand cmd = new IRISCommand("create table Sample.Streams(binaryData LONGVARBINARY, characterData LONGVARCHAR)", conn);
cmd.ExecuteNonQuery();
// Insert stream data into table
cmd.CommandText = "insert into Sample.Streams(binaryData, characterData) values (?, ?)";
// One way to mark the parameter as a binary stream datatype and then set the Value
cmd.Parameters.Add(new IRISParameter("binaryData", IRISDbType.LongVarBinary));
cmd.Parameters[0].Value = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// An alternate way to bind the data to the parameter and then mark the parameter as a character stream
cmd.Parameters.Add(new IRISParameter("characterData", (string)"This is a short character stream!"));
cmd.Parameters[1].IRISDbType = IRISDbType.LongVarChar;
cmd.ExecuteNonQuery();
// Now insert two files from disk as streams
// Open binary file and read into byte[]
// FileStream fbs = new System.IO.FileStream(".\\ConsoleStream.exe", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
FileStream fbs = new System.IO.FileStream(".\\myimage.png", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite);
int filebLen = (int)fbs.Length;
byte[] filebData = new byte[filebLen];
fbs.Read(filebData, 0, (int)filebLen);
fbs.Close();
cmd.Parameters[0].Value = filebData;
cmd.Parameters[0].Size = filebLen;
// Open character file and read into string
StreamReader fcs = new StreamReader(new System.IO.FileStream(".\\cprovider.log", System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.ReadWrite));
string filecData = fcs.ReadToEnd();
int filecLen = filecData.Length;
fcs.Close();
cmd.Parameters[1].Value = filecData;
cmd.Parameters[1].Size = filecLen;
cmd.ExecuteNonQuery();
cmd.Parameters.Clear();
// Create an SQL Statement to execute (Command)
cmd.CommandText = "select ID,* from Sample.Streams";
// Execute and fetch the data from Cache
IRISDataReader reader = cmd.ExecuteReader();
Console.WriteLine("Output from statement: " + cmd.CommandText);
Console.WriteLine(" ");
Console.WriteLine("ID\tbinaryStream\t\tcharacterStream ");
while (reader.Read())
{
#if BYNUMBER
// Access Column by Number
Console.Write(reader[0]);
Console.Write("\t");
Console.Write(reader[1] + " : N/A");
Console.Write("\t");
Console.Write(reader[2]);
Console.Write("\t");
Console.WriteLine();
#else
// Access Column by Name
Console.Write(reader[reader.GetOrdinal("ID")]);
Console.Write("\t");
Console.Write(reader[reader.GetOrdinal("binaryData")] + " : N/A");
Console.Write("\t");
Console.Write(reader[reader.GetOrdinal("characterData")]);
Console.Write("\t");
Console.WriteLine();
#endif
}
Console.WriteLine("");
Console.WriteLine("End of characterStream output!");
// Cleanup Reader, Connection and Command
reader.Close();
cmd.Dispose();
conn.Close();
}
}
}
The driver of the ORM that I'm using was not using parameters on the SQL for the streams and I did not see that, I'm using it manually while it's not fixed on the ORM, thank you!
💡 This question is considered a Key Question. More details here.