getting a {_stack: [ array ]} to a string to put into mysql database - mysql

I am trying to get a list of titles that was stored in a mysql database to be put into an array, so I can put it into the various commands found in card-deck and then save it back to the database.
sql = `SELECT * FROM ${brawlname} WHERE brawlid = ("${brawlID}")`;
con.query(sql, function(err, rows, fields) {
if (err) throw err;
var playerAid = rows[0].playerAid
var playerBid = rows[0].playerBid
var playerAname = rows[0].playerAname
var playerBname = rows[0].playerBname
var deckanme = rows[0].deckname
var brawlID = rows[0].brawlid
console.log(`${deckname} found in database!`)
if (message.author.id == playerAid) {
var playerAdeck = JSON.stringify(list) //I've omitted this in various attempts and went right to .split.
console.log(playerAdeck)
var playerAdeckarray = playerAdeck.split(", ")
var maindeckA = new Deck()
maindeckA.cards(playerAdeckarray)
console.log(maindeckA)
newdeckA = maindeckA.join(", ") //error happens here.
console.log(newdeckA)
The error I get from the indicated line is
throw err; // Rethrow non-MySQL errors
TypeError: maindeckA.join is not a function
The first line above is when the list goes through Stringify, the last part is after it goes through the .card method.
So in the example text above, I then take the list of names that is obtained from a mysql query and turn it into a string that then creates the deck object. In another file, I take this list of card names, pull it from the database, shuffle it, then try and transform it into a new string and save it back all to have the same error on the .join(", ") line. The functions work from card-deck, but the way to transform it into a string to put into the database doesn't. Anytime I put something into one of the functions related to card-deck1 I can't get it to a form that works in the database. I've tried .join, .toString(), etc... and most of them either give me [object Object] or the "is not a function" error.
Thanks for any and all help! :D

Related

How to use node streams to insert big data into mysql?

I'm trying to use node stream to insert 10 million records into mysql. Is there a way to do this with node stream? I'm not finding very useful or 'friendly' answers or documentation about this issue anywhere. So far I'm able to insert 45K records, but I'm getting some errors trying with a record set any bigger than that.
Also, what's the callback in the code below supposed to do here? I'm not sure where I got this code from and I'm not actually passing a call back, so, maybe that's the problem!! :D Any ideas? What would the callback actually be? Maybe the callback is supposed to take chunk and pass a chunk at a time? How could I rework this to get it to work consistently? I just don't think this code below is actually splitting the data up into chunks at all. How do I split it up into manageable chunks?
Depending on the amount of records I try this with I get different errors. The errors I am getting are:
For 50K - 80K sometimes I get this error:
Error: connect ETIMEDOUT
at Connection._handleConnectTimeout
I get this error for 100K records or above:
Error: ER_NET_PACKET_TOO_LARGE: Got a packet bigger than 'max_allowed_packet' bytes
at Query.Sequence._packetToError
This error for around 55K records:
Error: write EPIPE
at WriteWrap.afterWrite [as oncomplete] (net.js:788:14)
It's kind of wild to get 3 different errors depending on the amount of records I'm trying to insert.
Here's the code (It's working fine for 45000 records, but not for anything bigger):
var db = require('./index.js');
var faker = require('faker');
var stream = require('stream');
var songs = [];
var size = 10000000;
var songList = function(){
for (var i = 0; i < size; i++) {
var song = [i, faker.random.words(1,2), faker.name.findName(), faker.internet.url(1,50), faker.random.words(1,2), faker.random.words(1,20)];
songs.push(song);
}
console.log('songs', songs);
return songs;
}
var songSql = "INSERT INTO songs (song_id, song_name, artist, song_url, song_album, song_playlist) VALUES ?";
var songValues = songList();
var songSeed = function() {
console.log('x: ', x);
var query = db.connection.query(songSql, [songValues]).stream({highWaterMark: 5});
var testStream = new stream.Transform({highWaterMark: 5, objectMode: true});
testStream._write = function(chunk,encoding,callback) {
setTimeout(function() {
console.log('my chunk: ', chunk);
callback();
},1000);
}
// Pipe the query stream into the testStream
query.pipe(testStream)
// Monitor data events on the side to see when we pause
query.on("result",function(d,i) {
console.log("Data Sent")
})
}
songSeed();
On the MySQL server increase max_allowed_packet to 1G. There's no real downside to this.

felixge MYSQL module delay?

I'm using a node.js + websocket + https://github.com/felixge/node-mysql.
I have a small script here:
sql.query('SELECT hash FROM dateinfo ORDER BY date LIMIT 1',function(error,erows){
if(error) throw err;
var oldhash,oldrolls;
for (var i = 0; i < rows.length; i++) {
oldhash = rows[i].hash;
oldrolls = rows[i].rolls;
};
console.log(oldhash);
});
After successful query, console prints "undefined". But if I print that variable after some time (let's say 1s), it will print "test" (as the mysql field contains "test").
I heard that this is the problem with node.js async...
I'm stuck here, what should I do?
Thanks for the help.
rows is actually undefined since your second parameter is called erows

AS3 How to Send Multiple Messages in writeUTF?

So with TCP in AS3, I'm trying to write strings over to the server and then to the clients, but it appears to only be able to read one at a time. This is not good because I'm sending messages based on keys being pressed, and the client has an action that needs to be taken place based on what key is pressed. Since multiple keys can be pressed at a time, obviously it does not work correctly.
Client example:
if (keys[p1_jump_key])
{
p1_up = "down";
sock.writeUTF("p1_up_down");
sock.flush();
}
else
{
p1_up = "up";
sock.writeUTF("p1_up_up");
sock.flush();
}
if (keys[p1_crouch_key])
{
p1_down = "down";
sock.writeUTF("p1_down_down");
sock.flush();
}
else
{
p1_down = "up";
sock.writeUTF("p1_down_up");
sock.flush();
}
And then here is the server:
function socketDataHandler(event:ProgressEvent):void{
var socket:Socket = event.target as Socket;
var message:String = socket.readUTF();
for each (var socket:Socket in clientSockets)
{
socket.writeUTF(message);
socket.flush();
}}
And finally, here is the recieving client (I have a method that allows the server to differentiate between the two):
if(msg=="p1_down_down"){
p1_down="down";
}
if(msg=="p1_down_up"){
p1_down="up";
}
if(msg=="p1_up_down"){
p1_down="down";
}
if(msg=="p1_up_up"){
p1_down="up";
}
Now many of you already see the issue, as when the down key is up, it sends the message "p1_down_up". When the up key is up, it sends the message "p1_up_up". Both messages are sending at once when neither of them are being pressed. The receiving client is, I suppose, just getting one of the signals, or perhaps neither of them. How do I make MULTIPLE signals get wrote and read over the server? I tried using an array but you can't write those apparently. Thank you.
For anyone else who comes across this like I did trying to figure out how to accomplish this, I have to say that the other solution supplied is highly inefficient, overly complicated and too hard to read. Instead of adding a null byte to the end of your message and pushing packets into arrays, you can simply have the server send the length of the entire message to determine whether the message is in multiple packets, and to make sure you read multiple writes in the correct order.
Here is a working client receive function. I send data as compressed Objects converted to ByteArrays. Objects can store any type of data which make them a good candidate for transferring complex information from server to client.
var messageBytes: ByteArray = new ByteArray;
var messageLength: int = 0;
var readBuffer = false;
function receiveTCP(e: ProgressEvent): void {
while (e.target.bytesAvailable >= 4) {//Loop to see if there is data in the socket that is available to read.
if (messageLength == 0) {
messageLength = e.target.readUnsignedInt();//read the first 4 bytes of data to get the size of the message and store it as our message length.
readBuffer = true;//set the readBuffer to true. While this is true, the function wont be reading any more data from the server until the current message is finished being read.
}
if (messageLength <= e.target.bytesAvailable) {//check to see if our message is finished being read.
if (readBuffer == true) {//Make sure another message isn't being read. Without this check, another incoming message from the server will overwrite the current one from being executed.
e.target.readBytes(messageBytes, 0, messageLength);//reads the byte array into our messageBytes ByteArray declared at the top.
messageBytes.uncompress();//decompresses our message
var message: Object = new Object();
message = messageBytes.readObject();//Writes our ByteArray into an object again.
receiveMessage(message);//send our message to another function for the data to be executed.
messageLength = 0;//reset our messageLength for the next message.
readBuffer = false;//reset our buffer so that the client can read the next message being received, or the next message in line.
} else {
receiveTCP(e);//if there is another message in wait and the previous one isn't finished reading, execute the same function with the same event data again. Eventually the buffer will open and the message will be read.
}
} else {
break;//If the message is split up into multiple packets, this will reset the loop to continue reading the message until all the packets are accounted for.
}
}
}
This will prevent Clogging, allow you to receive multiple messages simultaneously and put together messages that were delivered in multiple packets.
Admittedly, this took a while to figure out. If you need the serverside code for sending the message, let me know.
The TCP protocol consists of a bi-directional stream of bytes, and as such message boundaries are not preserved. Due to this, if you are sending messages too often, you can end up reading from the buffer two messages instead of one.
Thus, some of the messages you are sending might be being processed together, which fails the comparison test on the receiving end.
To fix this, you can append a delimiter at the end of each message. This way, you'll know where every message you sent begins and ends, allowing you to split and process them separately. This also means you don't need to flush after every write to the buffer.
For instance, you could use a null byte (\0) as delimiter.
if(keys[p1_jump_key])
{
p1_up = "down";
sock.writeUTF("p1_up_down\0");
}
...
sock.flush();
And on the receiving end, we trim any trailing delimiters and then split the message into the smaller packets.
EDIT: Fixing the issue you described gives rise to another one: your messages might be being split over two buffer reads. I've edited my code to reflect a solution to this, by creating a temporary variable where partial messages are stored, to be prepended to the other part(s) of the message in the following reads.
// First we check to see if there are any 'parts' of a message that we've stored temporarily from the last read. If so, prepend them to the message string, which must be its continuation
if(temp != "")
{
msg = temp + msg;
temp = "";
}
// Now we begin processing our packet
var splitPackets:Array = msg.split("\0");
var packets:Array = new Array();
// Deal with incomplete message reads
if(splitPackets[splitPackets.length - 1] != "")
{
// If the last item in our array isn't empty, it means out message stream ended in a partial message. Hence, we have to store this value temporarily, and append it on the next read of the stream
temp = splitPackets[splitPackets.length - 1];
}
// If the last item in our array is empty, it means our message stream ends in a full message
for(var i = 0; i < splitPackets.length - 1; i++)
{
packets[i] = splitPackets[i];
}
for(var i = 0; i < packets.length; i++)
{
if(packets[i] == "p1_down_down")
{
// Process each packet individually here
...
// If you have already processed the packet, move on to the next
continue;
}
// Processing code for other packets
...
}
Hope this helps!

Google Docs Script Issue with Split through Function

First time poster here for Google Script related services, hopefully I put it in the right place! I'm encountering an error and I can't seem to find the right terminology to look up a solution. Below is the function. Within it I have a variable, string1, that I apply the split to. If I hard-code the value of the string (in the line commented out in the string), then it works and I receive the correct output. If, on the other hand, I try to pass that string into the function from another function, I receive the following error:
"TypeError: Cannot find function split in object Wed Oct 30 2013 09:00:26 GMT-0400 (EDT),danno,ticket,netid,request,mac,Error - Invalid Mac / Mac Not Found."
Note: My call to the function looks like this - formatEmailRow(completeEmailArray[i])
function formatEmailRow(rowToFormat) {
var formattedString = "";
var array1 = [];
var string1 = "";
///////////////////////
string1 = rowToFormat;
//string1 ="10/30/2013 9:00:26,danno,ticket,netid,request,mac,Error - Invalid Mac / Mac Not Found ";
///////////////////////
array1 = string1.split(",| ,|, ");
if (array1 != ""){
for (var i = 0; i < array1.length; i++) {
formattedString = formattedString + " " +(array1[i]);
}}
return formattedString;
}
Please help!
Thanks ahead of time, any advice is appreciated!
-Danno
You're getting that error because .split() isn't a method contained in the type of object you've passed in. Since you're new to this, it's worth a pause to read up on Objects and Methods - this is a quick overview.
You want to receive a String, but it seems that you're not. The problem will be with the code that's calling formatEmailRow().
My guess is that you're passing an array - probably all the cells in a row - but here's how you can check.
Add this line as the first line in your function:
Logger.log("rowToFormat = " + JSON.stringify(rowToFormat));
... then run, with your error. Check the logs - you want to see that you are getting a simple string. If you're getting an array, then you know what you need to fix. (Maybe you want to get the array after all!)

google visualization api, identify tableid in response function

Hmmm, maybe someone can help me out here or point me in the right direction , as i have been banging my head against the wall for a number of days now and dont seem to be gettin anywhere useful.
(and admittedly i'm pretty new with regards to json,objects, google visulization etc)
essentially, i am running 3 different queries on the same page against 3 different fusion tables, which in return are supposed to return an array of 3 different xets of markers.
all is fine, when i run the queries individually and make an array of the markers .
however, running the 3 queries on the same page, i can't seem to find a way to identify the query in the response function.
any hints much appreciated. and i'll be happy to provide more info if needed (tried to get rid of some unneccessary stuff)
this is what i have. thanks
a) calling the function "setFusionData()" with all relevant vars. something like setFusionData("'LatLng','name'", 2729461);
(this is calles 3 times with different variables)
function setFusionData(selColumns,tableId) {
/****
an actual query example is this:
http://www.google.com/fusiontables/gvizdata?tqx=reqId:1234&tq="select+'LatLng','name'+from+2729461"
****/
var query = new google.visualization.Query(
'http://www.google.com/fusiontables/gvizdata?tqx=reqId:1234&tq='+ encodeURIComponent("SELECT "+selColumns+" FROM "+tableId+"")
);
query.send(getFusionData); //do something with the response
}
function getFusionData(response) {
/**
here, is the problem as i need to get the table id or reqId or anything that is uniquely passed on from "setFusionData" above
also something like
alert(JSON.stringify(response)) does not return any reqId or table id either
***/
/*return rows/columns and add values to an array of markers***/
var numRows = response.getDataTable().getNumberOfRows();
var numCols = response.getDataTable().getNumberOfColumns();
for (i = 0; i < numRows; i++) {
/* add markers to array etc this works fine***/
}
}
i also tried something like this:
function setFusionData(selColumns,tableId) {
......
query.send(getFusionData({reqId:tableId}));
}
function getFusionData(response) {
alert(response['reqId']);//returns tableId. but how do i get the tableData ?
}
with wich i can get the reqId, but not the table*Data*. So I am only able to get either id or data :(
----edit----------------
after messing around a bit more (see below) it appears that the key/value pairs that get returned when typing the query into the browser directly are different than what gets returned by the call from the script...i.e the following
http ://www.google.com/fusiontables/gvizdata?tqx=reqId:1234&tq="select+'LatLng','name'+from+2729461"
typed directly into the browser bar will return
version:'0.5',reqId:'1234',status:'ok',table etc
however, calling the same from within the script returns something like
{
"rj":"0.5","ef":"ok","pb":[],"qb":[],"h":"{"cols":
[{"id":"col2","label":"LatLng","type":"string"},{"id":"col1","label":"name","type":"string"}],
"rows":
[{"c":[{"v":"47.20572,12.70414"},
{"v":"Hohe Tauern"}]},{"c":[{"v":"47.5530395,12.925611"},{"v":"Berchtesgaden"}]},{"c":[{"v":"47.5585405,14.61887"},{"v":"Gesu00e4use"}]}],
"p":{"totalrows":3}
}"
}
, so no 'reqId' but only some cryptic keys (without one that looks like the reqId either)...... anyone any idea why that would/could be ?
Sometimes you can figure it out by just looking at the JSON response, your sample request returns:
google.visualization.Query.setResponse({
version:'0.5',
reqId:'1234',
status:'ok',
table: {
...
}
})
You already got response.reqId to identify which request is this the response for, now you can use response.table to create a new DataTable instance:
var dt = new google.visualization.DataTable(response.table);
Or, since you have multiple tables, put then in an array indexed with the reqId
tables[response.reqId] = new google.visualization.DataTable(response.table);
You'd do var tables = new Array() before calling setFusionData() for the first time.