Thursday, September 6, 2012

Remote Desktop fullscreen

It seems that whenever I click the Window Restore icon on a fullscreen Remote Desktop instance, a subsequent Window Maximize does not bring me back to the fullscreen. Instead I'm back in crappy maximized-with-vertical-scrollbars land.

The solution?

CTRL-ALT-BREAK

This will toggle you between fullscreen and crappy mode.

Wednesday, March 21, 2012

[mysql] UPDATE-JOIN

I used this query to identify duplicated records:

SELECT date, user_id, record_id
FROM records
WHERE active=1
GROUP BY date, user_id
HAVING COUNT(*)=2

Say it returns 26 records. Now I want to run a query to update these records' active column to zero. Simple, just nest the above as an outer query's IN clause, right?

UPDATE records
SET active=0
WHERE record_id IN (
  SELECT record_id
  FROM records
  WHERE active=1
  GROUP BY date, user_id
  HAVING COUNT(*)=2);

Nope. MySql has a little something to say about that plan.

You can't specify target table 'records' for update in FROM clause

Great, you can't nest a SELECT of the table you're updating. Fortunately, there is a way out, rewriting the above as an UPDATE-JOIN.

UPDATE records a 
JOIN (
  SELECT record_id
  FROM records
  WHERE active=1
  GROUP BY date, user_id
  HAVING COUNT(*)=2) b 
ON a.record_id=b.record_id
SET a.active=0;

Tuesday, February 14, 2012

[php] PHP_Incomplete_Class

You've saved an object instance of YourClassName into session. On a subsequent retrieval of this object from session, you discover it's now a __PHP_Incomplete_Class object!

your_object = __PHP_Incomplete_Class Object
(
  [__PHP_Incomplete_Class_Name] => YourClassName
  [id] => 123
  [name] => Fred
)

Check where you're doing the session_start. Chances are you did not include YourClassName (plus any required files of its inheritance chain, if applicable) before starting the session.

Monday, February 13, 2012

[mysql] Opening another result tab in workbench

Even when I have multiple scratch tabs open, MySql Workbench 5.3 always reuses the same "Result (1)" tab for displaying query results. But what if you want to compare the results of two queries?

Click the thumbtack icon at the top right of the Result window ("toggle pinned state of the page") after running the first. Now your next query will be forced to create a second Result tab.

[mysql] Querying column definitions

To list the columns and their definitions, simply run the query:

show columns from your_table_name

[php] Show warnings/errors

I'm always forgetting this.

error_reporting(E_ALL);
ini_set('display_errors', '1');

Wednesday, December 14, 2011

[js] Closure blocks

I haven't really come across much specifically about this, but making use of anonymous functions as callbacks to your asynchronous routines allows you to format these calls so that they look (and behave) like a regular structured block.

Asynchronous calls are, of course, a fact of life with AJAX, but they come up in other situations as well, like waiting for user input. Consider two approaches to the same functionality.

function getRec(id) {  // request
  showWorking(true);
  ajaxFetch(id);
}
function getRec_callback(rec) {  // receipt
  showWorking(false);
  displayRec(rec);
  // more stuff
}

/* Ajax */
function ajaxFetch(id) {
  var rec = // ..etc
  getRec_callback(rec);
}

In the above approach the request and receipt are split across two functions, getRec and getRec_callback, spanning the dreaded "asynchronous gap."

Here's another approach:

function getRec(id) { // request
  showWorking(true);
  ajaxFetch(id, function(rec) {  // receipt
    showWorking(false);
    displayRec(rec);
    // more stuff
  })
}

/* Ajax */
function ajaxFetch(id, callback) {
  var rec = // ..etc
  callback(rec);
}

The request and receipt are again split into two functions (this can't be avoided), but the use of a closure for the receipt allows us to combine both into getRec, and offers at the very least the appearance of a seamless flow of logic, from request to receipt.

But there's more than aesthetics at play here when you consider that Javascript closures can access the local variables of the enclosing function. This means any variables defined in the request block, prior to the asynchronous jump, will still be available and ready for use in the receipt block, after the asynchronous jump. So it not only looks like a nested block of code, it behaves like a nested block of code. And we have bridged the asynchronous gap.

Wednesday, November 23, 2011

[js] IE yellow download bar

Say you have a "download" link. Clicking it kicks off a Javascript function that ultimately navigates the browser to your download PHP script, which serves up the file via something like:

/* download.php */
..
header('Cache-Control: public'); 
header("Content-type: application/pdf");
header('Content-Disposition: attachment; filename="' . $filename . '"');
readfile($path . $filename);

In IE, this usually pops up a "File Download" dialog asking if you want to open or save the file; pretty convenient. But something went awry somewhere. You're now getting a yellow bar warning instead. Why?

To help protect your security, Internet Explorer blocked this site from downloading files to your computer. Click here for options...

Check your Javascript. IE will allow you, the developer, to initiate a download from a click event as long as you do so within the same execution thread. Let the click thread end, though, and try to navigate to the download script from another thread, and, hello, yellow bar. In other words, look out for setTimeout.

  download_onclick:function(id) {
    window.location.href = 'download.php?id=' + id;    // good to go
  }, ..
  download_onclick:function(id) {
    setTimeout(function() {
      window.location.href = 'download.php?id=' + id;  // yellow bar
    }, 1);
  }, ..

Monday, November 21, 2011

[php] Content-type:image whitespace woes

So today I noticed the code for displaying scanned images was no longer working. This code basically boils down to:

header('Content-type: image/jpeg');
readfile('some_file.jpg');

Pretty simple, right? Yet somehow, even though some_file.jpg really does exist, and it really is a JPEG, I'm getting nothing. IE gives me the "image not found" red X icon, Chrome gives me a blank. What?

Rummaging around the web, I found a couple references to how unintentional whitespace output by your PHP script can screw your header() call into the ground. This seemed a likely explanation, but where (and why) is my PHP spitting out unwanted whitespace?

Turns out the culprit was lurking within these closing lines of an include:

  static function asOptionalJoin($fk = 'ipc') {
    $c = new static();
    return CriteriaJoin::optional($c, $fk);
  }
}
?> 

Do you see it? Trick question; it's invisible.

  static function asOptionalJoin($fk = 'ipc') {
    $c = new static();
    return CriteriaJoin::optional($c, $fk);
  }
}
?> <— look again

Yes, a space immediately to the right of the closing ?> PHP tag was the source of my grief. Take that space away, and the header call works again and the image springs back to life.

Interesting side note: one of the aforementioned resources explains that closing ?> tags are not only optional (didn't know this), but that some frameworks actually forbid them in PHP-only source files for the very reason of keeping accidental whitespace out of the output.

Sounds good to me; they're gone.

Thursday, November 3, 2011

[js] Another unexpected result

Sticking with the same theme as last post's short-circuit trickery, another Javascript operation that has an unexpected result (for me, anyway) is the assignment operation.

alert (x = 'hi');

The resultant friendly greeting demonstrates that the assignment operation not only assigns a value but actually evaluates as that value. This offers additional opportunities at simplification:

add(last_row = row);
return this.property = object.calculate(arg);
// etc.