Question

I have a table in my Pervasive.SQL table that is of type LongVarChar, which is essentially a blob type field designed for string data.

When I execute a PsqlDataReader against this table, the field size the reader reports for the field is 65500. There is also a flag for IsLong, which is rightly true.

I would have expected the field size to be either something much larger than 65500, or -1, because I thought I understood that to be the flag for "as long as it needs to be", or some such thing.

Do I have any control over this at a high enough level to do it generically? As in, without knowing anything about the table I am reading, or the fields it contains? Some way to tell it to automatically recognize that the field is massive and to thusly set an appropriately large size?

Note that I have manually tested the outcome that I want by retrieving the schema, resetting the field size from 65500 to Int32.MaxValue and then loading data from the reader. With 65500, I would get a constraint exception. At Int32.MaxValue, I do not.

Additional information found in Pervasive's documentation:

In a single call to SQLGetData, the maximum number of characters returned by Pervasive PSQL for a LONGVARCHAR or LONGVARBINARY columns is 65500. Multiple calls must be made to SQLGetData to retrieve column data over 65500 characters.

That seems to explain why the PsqlDataReader is getting the size of 65500. Likely they make a single call and use the size. But...still do not know what to do about the impact that that limitation is having on my ability to DataTable.Load(reader). It does fetch the complete field data, by the way. I think it is only the schema fetch that is wrong.

Was it helpful?

Solution 2

Since this never got an answer, I'll post the remedy I ended up using:

foreach (DataColumn dc in dt.Columns)
{
    if (dc.DataType == typeof(String) && dc.MaxLength == 65500)  //only true for LongVarChar
        dc.MaxLength = Int32.MaxValue;
}

This code appears near the end of a method that loads data into a DataTable. Once the table is filled, this loop kicks in and expands the field width for any LongVarChar columns, beating the default limitation.

OTHER TIPS

Here's some code I wrote for someone else with a similar problem some time ago. It loads a text file into a LongVarChar field then reads it back and writes it to a new file.

using System;
using System.Data;
using System.Data.SqlTypes;
using System.IO;
using Pervasive.Data.SqlClient;

class LoadText
{
    static string fileName = @"loadtext.txt";

    static PsqlConnection conn = null;
    static PsqlCommand cmd = null;

    static void Main()
    {
        try
        {
            string textFile = fileName;
            Console.WriteLine("Loading File: " + textFile);
            conn = new PsqlConnection(@"ServerDSN=DEMODATA");
            conn.Open();
            cmd = new PsqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = @"create table texttable(textfile varchar(255),textdata longvarchar)";
            //cmd.ExecuteNonQuery();

            cmd.CommandText = @"insert into texttable values (?,?)";
            cmd.Parameters.Add("@textfile", PsqlDbType.VarChar, 30);
            cmd.Parameters.Add("@textdata", PsqlDbType.LongVarChar, 1000000);

            Console.WriteLine("Loading File: " + textFile);

            FileStream fs1 = new FileStream(textFile, FileMode.Open, FileAccess.Read);
            StreamReader sr1 = new StreamReader(fs1);
            string textData = "";
            textData = sr1.ReadToEnd();

            Console.WriteLine("TextBytes has length {0} bytes.", textData.Length);

            //string textData = GetTextFile(textFile);
            cmd.Parameters["@textfile"].Value = textFile;
            cmd.Parameters["@textdata"].Value = textData;

            cmd.CommandText = cmd.CommandText;
            cmd.ExecuteNonQuery();

            Console.WriteLine("Loaded {0} into texttable.", fileName);

            cmd.CommandText = "select * from texttable";
            PsqlDataReader dr = cmd.ExecuteReader();
            if (dr.HasRows)
            {
                dr.Read();
                textFile = @"Output.txt";
                StreamWriter sw = new StreamWriter(textFile);
                sw.Write(dr[1].ToString());
                Console.WriteLine("TextFile: {0}.\nTextData written to {1}", dr[0].ToString(), textFile);
            }

        }
        catch (PsqlException ex)
        {
            Console.WriteLine(ex.ToString());
        }
        finally
        {
            conn.Close();
        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top