Insert failed on table with 300 integers and 300 char(20) - postgresql

I've tried to test TOAST functionality and created the code:
int length = 20;
using (NpgsqlConnection conn = new NpgsqlConnection(""))
{
conn.Open();
StringBuilder ct = new StringBuilder();
ct.Append("CREATE TABLE t300 (");
for (int i = 0; i < 300; i++)
{
ct.Append("i").Append(i).Append(" int not null, n").Append(i).Append(" varchar(").Append(length).Append(") not null, ");
}
ct.Remove(ct.Length - 2, 2).Append(");");
using (NpgsqlCommand cmd = new NpgsqlCommand(ct.ToString(), conn))
{
cmd.ExecuteNonQuery();
}
StringBuilder isql = new StringBuilder();
isql.Append("INSERT INTO t300 (");
StringBuilder vsql = new StringBuilder();
vsql.Append("VALUES (");
for (int i = 0; i < 300; i++)
{
isql.Append("i").Append(i).Append(", n").Append(i).Append(", ");
vsql.Append(":i").Append(i).Append(", :n").Append(i).Append(", ");
}
isql.Remove(isql.Length - 2, 2).Append(") ").Append(vsql).Remove(isql.Length - 2, 2).Append(");");
using (NpgsqlCommand cmd = new NpgsqlCommand(isql.ToString(), conn))
{
for (int i = 0; i < 300; i++)
{
cmd.Parameters.AddWithValue("i" + i.ToString(), NpgsqlDbType.Integer, i);
cmd.Parameters.AddWithValue("n" + i.ToString(), NpgsqlDbType.Varchar, length, i.ToString() + new string('n', length - i.ToString().Length));
}
for (int i = 0; i < 10000; i++)
{
cmd.ExecuteNonQuery();
}
}
}
This code fails on INSERT with exception '54000, row size (8424) exceeds limit (8160)'.
When I set 'length' variable to 26, the code works fine. Please tell me the workaround to eliminate this situation.
Postgres 12, Npgsql 4.1.5

Perhaps you have a misconception of how TOAST storage works. PostgreSQL does not compress the whole row and store it in the TOAST table, but each column of a varying length data type independently.
So after toasting, the row still consists of 600 columns, 300 of which (the integers) won't be toasted (4 bytes), and the other 300 toasted columns (the varchars) will now contain a TOAST header and a TOAST pointer.
Together this happens to be more than fits into a single block, and rows cannot span more than a single block. That causes the error.
The solution is not to use tables with so many columns. You should split the data in several tables (normalization usually takes care of that). If there are truly very many attributes to a single entity, chances are that not all of these attributes will get used in join or WHERE conditions. You could consider storing such attributes in a single jsonb column, where TOASTing will be much more efficient.

Related

Is there a better way to calculate the moving sum of a list in flutter

Is there a better way to calculate a moving sum of a list?
List<double?> rollingSum({int window = 3, List data = const []}) {
List<double?> sum = [];
int i = 0;
int maxLength = data.length - window + 1;
while (i < maxLength) {
List tmpData = data.getRange(i, i + window).toList();
double tmpSum = tmpData.reduce((a, b) => a + b);
sum.add(tmpSum);
i++;
}
// filling the first n values with null
i = 0;
while (i < window - 1) {
sum.insert(0, null);
i++;
}
return sum;
}
Well, the code is already clean for what you need. Maybe just some improvements like:
Use a for loop
You can use the method sublist which creates a "view" of a list, which is more efficient
To insert some values in the left/right of a list, there is a specific Dart method called padLeft, where you specify the lenght of the list which you want it to become (first parameter), then the value you want to use to fill it (second parameter). For example, if you have an array of N elements, and you want to fill it with X "null"s to the left, use padLeft(N+X, null).
List<double?> rollingSum({int window = 3, List data = const []}) {
List<double?> sum = [];
for (int i = 0; i < data.length - window + 1; i++) {
List tmpData = data.sublist(i, i + window);
double tmpSum = tmpData.reduce((a, b) => a + b);
sum.add(tmpSum);
}
sum.padLeft(window - 1, null);
return sum;
}
if I understand your problem correctly you can just calculate the window one time and in one loop you can for each iteration you can add the current element to the sum and subtract i - (window - 1)
so for an input like this
data = [1,2,3,4,5,6]
window = 3
the below code will result in [6,9,12,15]
int sum = 0;
List<double> res = [];
for (int i = 0;i<data.length;i++) {
sum += data[i];
if (i < window - 1) {
continue;
}
res.add(sum);
sum -= data[i - (window - 1)]; // remove element that got out of the window size
}
this way you won't have to use getRange nor sublist nor reduce as all of those are expensive functions in terms of time and space complexity

How to collect all data from first column in table into array?

I using netbeans 8.
I need to loop to collect all employee ID from first column of jtable and store those IDs into an arraylist.
if (jTabledetail.getRowCount() > 0) {
String ecode = "";
int ishasRow = jTabledetail.getRowCount();// total 1 row
for (int r = 0; r <= ishasRow; r++) {// loop twice. First loop is gone, return to second loop or final loop for 1 row exists giving error bellow.
ecode = jTabledetail.getValueAt(r, 0).toString();
arrempcode.add(ecode);
}
}
I also tried changing to ==>> for (int r = 0; r < ishasRow; r++) but not worked.
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 1 >= 1
at java.util.Vector.elementAt(Vector.java:474)
at javax.swing.table.DefaultTableModel.getValueAt(DefaultTableModel.java:648)
at javax.swing.JTable.getValueAt(JTable.java:2717)
I don't understand the error. I known that the error comes from loop expression. I am not sure for this error.
Now my jtable named "jTabledetail" has 1 row exists.
Do I need to change something for this case of error? I am not sure that the loop expression is wrong.
Thank you very much.
DefaultTableModel tableModel = (DefaultTableModel) TableName.getModel();
Get the row count of the table
int rowCount = tableModel.getRowCount();
Declare ArrayList
ArrayList<Object> list = new ArrayList<Object>();
Traversing table and adding values into arraylist
for(int i=0; i<rowCount; i++){
for(int j=0; j<tableModel.getColumnCount(); j++){
if(j==0){
list.add(tableModel.getValueAt(i,j));
}
}
}

How to achieve space between columns in itext 7 tables?

I need to achieve a table that looks like the one in the picure, with space between columns. I tried:
cell.setPaddingLeft(10);
cell.setMarginLeft(10);
extractionMediaTable.setVerticalBorderSpacing(10);
But none of these seem to affect the table. Any suggestions?
This should help:
table.setBorderCollapse(BorderCollapsePropertyValue.SEPARATE);
table.setVerticalBorderSpacing(10);
table.setHorizontalBorderSpacing(10);
Some explanations:
By default iText creates tables with collapsed borders, so the first line overrides that.
Once the borders are separated, one can set the spacing (either horizontal or vertical) between them.
For example, look at the snippet below and the screenshot of the resultant pdf:
Table table = new Table(3);
table.setBorderCollapse(BorderCollapsePropertyValue.SEPARATE);
table.setVerticalBorderSpacing(10);
table.setHorizontalBorderSpacing(10);
for (int j = 0; j < 10; j++) {
for (int i = 0; i < 3; i++) {
table.addCell(new Cell().add(new Paragraph("Cell row " + j + "col " + i )));
}
}

Entity Framework bulk add of over 100,000, items

I am building an app that will store stock tick data. one of my methods needs to take an array of items, currently c. 100,000 items but will be over 1,000,000 at a time, and add them to an entity database. this is my current add logic:-
var tickContext = new DataAccess();
// array is created, add it to the entity database
for (int j = 0; j < tickDataArray.Length; j++)
{
MarketTickData temp2 = new MarketTickData();
if(j > 1)
temp2 = tickDataArray[j-1];
MarketTickData temp = tickDataArray[j];
tickContext.TickBarData.Add(tickDataArray[j]);
tickContext.Configuration.AutoDetectChangesEnabled = false;
tickContext.Configuration.ValidateOnSaveEnabled = false;
if (j % 200 == 0)
{
tickContext.SaveChanges();
tickContext.Dispose();
tickContext = new DataAccess();
}
}
// add remaining items to database
tickContext.SaveChanges();
tickContext.Configuration.AutoDetectChangesEnabled = true;
tickContext.Configuration.ValidateOnSaveEnabled = true;
When I test my logic on various sizes of tickContext before saving I am not seeing huge improvments in preformance. At a Context size of 50 my adds are taking 47 Seconds, 1000 is 54 Seconds and the best is 200 items taking 44 seconds. But it is still relatively slow.
Is there a way to improve this ?

Sand 3D Printer Slicing Issue

For my doctoral thesis I am building a 3D printer based loosely off of one from the University of Twente:
http://pwdr.github.io/
So far, everything has gone relatively smoothly. The hardware part took longer than expected, but the electronics frighten me a little bit. I can sucessfully jog all the motors and, mechanically, everything does what is supposed to do.
However, now that I am working on the software side, I am getting headaches.
The Pwder people wrote a code that uses Processing to take an .STL file and slice it into layers. Upon running the code, a Processing GUI opens where I can load a model. The model loads fine (I'm using the Utah Teapot) and shows that it will take 149 layers.
Upon hitting "convert" the program is supposed to take the .STL file and slice it into layers, followed by writing a text file that I can then upload to an SD card. The printer will then print directly from the SD card.
However, when I hit "convert" I get an "Array Index Out of Bounds" error. I'm not quite sure what this means.. can anyone enlighten me?
The code can be found below, along with a picture of the error.
Thank you.
// Convert the graphical output of the sliced STL into a printable binary format.
// The bytes are read by the Arduino firmware
PrintWriter output, outputUpper;
int loc;
int LTR = 0;
int lowernozzles = 8;
int uppernozzles = 4;
int nozzles = lowernozzles+uppernozzles;
int printXcoordinate = 120+280; // Left margin 120
int printYcoordinate = 30+190; // Top margin 30
int printWidth = 120; // Total image width 650
int printHeight = 120; // Total image height 480
int layer_size = printWidth * printHeight/nozzles * 2;
void convertModel() {
// Create config file for the printer, trailing comma for convenience
output = createWriter("PWDR/PWDRCONF.TXT"); output.print(printWidth+","+printHeight/nozzles+","+maxSlices+","+inkSaturation+ ",");
output.flush();
output.close();
int index = 0;
byte[] print_data = new byte[layer_size * 2];
// Steps of 12 nozzles in Y direction
for (int y = printYcoordinate; y < printYcoordinate+printHeight; y=y+nozzles ) {
// Set a variable to know wheter we're moving LTR of RTL
LTR++;
// Step in X direction
for (int x = 0; x < printWidth; x++) {
// Clear the temp strings
String[] LowerStr = {""};
String LowerStr2 = "";
String[] UpperStr = {""};
String UpperStr2 = "";
// For every step in Y direction, sample the 12 nozzles
for ( int i=0; i<nozzles; i++) {
// Calculate the location in the pixel array, use total window width!
// Use the LTR to determine the direction
if (LTR % 2 == 1){
loc = printXcoordinate + printWidth - x + (y+i) * width;
} else {
loc = printXcoordinate + x + (y+i) * width;
}
if (brightness(pixels[loc]) < 100) {
// Write a zero when the pixel is white (or should be white, as the preview is inverted)
if (i<uppernozzles) {
UpperStr = append(UpperStr, "0");
} else {
LowerStr = append(LowerStr, "0");
}
} else {
// Write a one when the pixel is black
if (i<uppernozzles) {
UpperStr = append(UpperStr, "1");
} else {
LowerStr = append(LowerStr, "1");
}
}
}
LowerStr2 = join(LowerStr, "");
print_data[index] = byte(unbinary(LowerStr2));
index++;
UpperStr2 = join(UpperStr, "");
print_data[index] = byte(unbinary(UpperStr2));
index++;
}
}
if (sliceNumber >= 1 && sliceNumber < 10){
String DEST_FILE = "PWDR/PWDR000"+sliceNumber+".DAT";
File dataFile = sketchFile(DEST_FILE);
if (dataFile.exists()){
dataFile.delete();
}
saveBytes(DEST_FILE, print_data); // Savebytes directly causes bug under Windows
} else if (sliceNumber >= 10 && sliceNumber < 100){
String DEST_FILE = "PWDR/PWDR00"+sliceNumber+".DAT";
File dataFile = sketchFile(DEST_FILE);
if (dataFile.exists()){
dataFile.delete();
}
saveBytes(DEST_FILE, print_data); // Savebytes directly causes bug under Windows
} else if (sliceNumber >= 100 && sliceNumber < 1000){
String DEST_FILE = "PWDR/PWDR0"+sliceNumber+".DAT";
File dataFile = sketchFile(DEST_FILE);
if (dataFile.exists()){
dataFile.delete();
}
saveBytes(DEST_FILE, print_data); // Savebytes directly causes bug under Windows
} else if (sliceNumber >= 1000) {
String DEST_FILE = "PWDR/PWDR"+sliceNumber+".DAT";
File dataFile = sketchFile(DEST_FILE);
if (dataFile.exists()){
dataFile.delete();
}
saveBytes(DEST_FILE, print_data); // Savebytes directly causes bug under Windows
}
sliceNumber++;
println(sliceNumber);
}
What's happening is that print_data is smaller than index. (For example, if index is 123, but print_data only has 122 elements.)
Size of print_data is layer_size * 2 or printWidth * printHeight/nozzles * 4 or 4800
Max size of index is printHeight/nozzles * 2 * printWidth or 20*120 or 2400.
This seems alright, so I probably missed something, and it appears to be placing data in element 4800, which is weird. I suggest a bunch of print statements to get the size of print_data and the index.