Category Archives: code

MySQL inner join vs left join

I wanted to make a super simple, cliff-notes-style introduction to inner joins and left joins, two of the most common joins you’ll encounter in MySQL-type relational databases. I always forget what they mean, so this is for me too. This is basically a condensed version of this wikipedia article.

All code in this post will use this sample database:

Employees can be assigned to departments. A department can have more than one employee, but an employee can only be in one department, or unassigned. Notice that one department, Marketing, has no employees assigned, and one employee, Williams, is not assigned to any department (signified by NULL in his DepartmentID column).

Joins compare all the rows in one table (the “left” table) against all the rows in another table (the “right” table), and let you ask meaningful questions that span multiple tables. An ON condition is used to specify what constitutes a “match” between any two rows picked from either table. In this post, the employee table will be the left table, and the department table willbe the right table, and all of our joins will use the ON condition where the DepartmentID matches between the two tables.

The output can then modified by the SELECT clause of the query, as usual, but all of the examples will use SELECT * for simplicity.

Left Join – “What department, if any, are my employees assigned to?”

In a left join, there will be a row in the output for each row in the left table, the table before the JOIN statement. The engine compares each row in the left table against each row in the right table and fills in the values based on the results of the ON condition.

SELECT *
FROM employee 
LEFT JOIN department 
ON employee.DepartmentID = department.DepartmentID;

The above query produces the following output:

Notice there is a row in the output for every employee, including the unassigned one, Williams, since employee is the left table in the join (appears before the JOIN keyword). For each employee, the engine finds the corresponding row in the department table, where the ON condition is met, where they have the same DepartmentID. For assigned employees, the output will contain all values from both rows.

However, for Williams’ row, the ON condition is not met. His DepartmentID is NULL, so there is no corresponding row in the department table to use in the output. Since this is a LEFT JOIN, the engine fills in the output values with NULL.

Notice also that the department with no employees, Marketing, does not show up in the output. This is because department is the right table in the join, and not every row in the right table is guaranteed to show up in the output in a LEFT JOIN. There was no employee row pointing to it, so it gets left out of the output.

This query answers the question “What department, if any, are my employees assigned to?” with NULL values signifying “none”.

Inner Join – “What department are my employees assigned to, excluding unassigned employees and empty departments?”

In an inner join, there will only be a row in the output if the ON condition is satisfied for both the left and the right tables.

SELECT *
FROM employee
INNER JOIN department
ON employee.DepartmentID = department.DepartmentID;

The above query produces the following output:

Notice this time there is no row in the output for the unassigned employee Williams OR the empty department Marketing. When the engine compares Williams’ row to the department table, it again finds no corresponding row where both DepartmentIDs satisfy the ON condition, where they are equal. Rather than fill in the missing values with NULL, it drops the row from the output completely. When the engine finishes comparing each employee row against the department table, again, Marketing was not used, and so it does not appear in the output either.

This query answers the question “Show me details of all employees that are assigned to a department, and details of said department”. It also answers the question, “Show me details of all departments with assigned employees, and details of said employees”.

Right Join – “What employees, if any, do my departments contain?”

I’m not going to go into it in-depth, as I haven’t seen it much in production, there is a corresponding right join to match the left join, where each row in the right table produces a row in the output, and the rest of the values are filled in from the corresponding rows in the left table, or NULL if no rows in the left table can be found that match the ON condition.

Query and output:

SELECT *
FROM employee 
RIGHT JOIN department ON employee.DepartmentID = department.DepartmentID;

2019 JavaScript String.replace() regex vs substring

Having done a bunch of HTML5/js work recently, I was curious about regex performance, especially in trivial cases where the power of regular expressions is not needed and a simple string substitution would suffice. I see regexes being used and recommended all over the web for simple string search-and-replace operations, and I typically regard that as bad advice, opting for the simpler substring-based substitution in my own code. But that makes the assumption that browser regex engines are not optimized to recognize simple string substitutions and use the simpler algorithm.

So it was time for a benchmark! It’s really simple, just replacing one word with another in a sentence that only has one occurrence of the search word.

Here are my results on Windows 10 across Edge, Firefox, and Chrome:

I was not surprised to see regex be from 75-97% slower in Firefox and Edge… but I was surprised to see regexes be 75%+ faster on Chrome!! That V8 regex engine must be highly optimized for simple regex cases!

I created a jsperf test case here – feel free to try it yourself and let me know what you get!

Documentation for String.replace() is here.

JS OOP Cheatsheet

Assume you have a JavaScript class, Car. You can create an instance of it:

new Car()

It’s really just a constructor function:

function Car() {}

Then:

  • Car.prototype.method is an instance method.

  • this.var inside Car() constructor or an instance method is an instance variable.

  • Car.var is a static (class-level) variable.

  • Car.method is a static method.

AGAL Error #3613: The native shader compilation failed

What a cryptic error message, yeah? Good grief! Thanks Adobe! Googling didn’t come up with very much, either.

Turned out I was passing two constant registers to an operation.

So basically, in order to compare two temporary registers, you have to copy one of them to a temporary register first.

This code failed in my vertex shader:
ife vc7.x, vc5.x

But this code works:

mov vt1, vc7
ife vt1.x, vc5.x

Go figure. Wonder why that is. Solution found on a comment on this article.

Flash Builder 4.7 crashes loading workbench OSX

Today I had a similar problem to the one in this post – but instead of hanging, Flash Builder just failed to start up and quit during the “loading workbench” phase of initialization.

In the earlier post, I mentioned deleting a .snap file in [workspacelocation]/.metadata/.plugins/org.eclipse.core.resources, but previously I hadn’t been able to find it. This time, there WAS a .snap file in that folder, but it was hidden.

Deleted it, and Flash Builder starts up like a champ.

Extract sounds and images from FLA in Flash CC with JSFL

Recently I learned that Flash CC dropped the ability to export WAV files! Dumb move by Adobe in my opinion, but what’s done is done.

After some Googling, I discovered this post on stackoverflow that contains a JSFL script to enable extracting sounds or images from the library of an FLA. It’s a few years old at this point, but I can confirm it still works for sounds as of Flash Pro CC 2014. If anyone has a more modern solution I’m all ears, but I’ll repost the code here in case that link ever breaks:

// Result of attempts to export will go to the output panel,
// so clear that first fl.outputPanel.clear();

// If bitmaps/audio in the library have been selected, export only
// those. Otherwise, export all bitmaps/audio in the library.

var lib;
if (fl.getDocumentDOM().library.getSelectedItems().length > 0) {
    lib = fl.getDocumentDOM().library.getSelectedItems(); 
} else { lib = fl.getDocumentDOM().library.items; } 

// Get destination directory for files 
var imageFileURLBase = fl.browseForFolderURL("Select a folder."); 
var imageFileURL; 

var totalItems = lib.length;
// Iterate through items and save bitmaps and 
// audio files to the selected directory.
for (var i = 0; i < totalItems; i++) 
{
    var libItem = lib[i];
    if (libItem.itemType == "bitmap" || libItem.itemType == "sound") 
    {
        // Check the audio files original Compression Type if "RAW" export only as a .wav file
        // Any other compression type then export as the libItem's name defines.
        if(libItem.itemType == "sound" && libItem.originalCompressionType == "RAW")
        {
            wavName = libItem.name.split('.')[0]+'.wav';
            imageFileURL = imageFileURLBase + "/" + wavName;
        } else {
            imageFileURL = imageFileURLBase + "/" + libItem.name;
        }
        var success = libItem.exportToFile(imageFileURL);
        fl.trace(imageFileURL + ": " + success);
    }
}

You'll need to save this to a file with a .jsfl extension, select any number of sounds or images from the library, and then go to Commands > Run Command in Flash Pro and navigate to the file. It'll ask you for an output directory and save the selected items there. If you don't select items in the library beforehand, it'll export all sounds and images found in the library.

To get the command to show up in the commands menu, put the file here:

Windows 7: boot drive\Users\username\AppData\Local\Adobe\Flash CC\language\Configuration\Commands

Windows Vista: boot drive\Users\username\Local Settings\Application Data\Adobe\Flash CC\language\Configuration\Commands

Mac OS X: Macintosh HD/Users/userName/Library/Application Support/Adobe/Flash CC/language/Configuration/Commands

filesystem data from here

ANE for iOS with Custom Framework – Using Custom Fonts

We’re developing a set of games for iOS, some objective-C and some using Adobe AIR, and we’re using an iOS custom framework to hold a bunch of storyboard-based screens that we want to use across all the apps.

On the AIR side, we’ve created an Adobe Native Extension and figured out how to include our framework in it. This may be a subject for another blog post, because it was quite complicated, but this post really helped us figure out how to get all the images, storyboards, and sound files (among other assets) to get included in the ANE, and thus into the final app. We also used it to include our custom font file that the storyboards made heavy use of.

However, this was not enough. Using this post, I was able to troubleshoot all the possible steps that could go wrong. I had to make sure that the .ttf file got included in the final output of the framework, but the real key was Step 4 – adding the font information to your app’s info.plist file. Since an ANE is NOT an app, these keys need to go in the info.plist of the final app the ANE gets included in. But AIR apps use an Application Descriptor File, not an info.plist file. The info.plist file of the completed .IPA is auto-generated when the app is built.

Not to worry, Adobe has provided a place in said app descriptor file where you can specify items to add to the auto-generated info.plist. Appropriately enough, it’s called the InfoAdditions element. The content of this element must be wrapped in CDATA tags, and anything inside it will be added to the info.plist of the final app. So, in an XCode sample app, I followed step 4 above and created the required key/value in XCode’s graphical plist editor, and then opened the generated file in a text editor and copy/pasted those values. Here’s what I got:

<key>UIAppFonts</key>
<array>
	<string>name-of-your-font.ttf</string>
</array>

And here’s what that looks like pasted into an InfoAdditions tag in the app descriptor:

<iPhone>
	<InfoAdditions><!&#91;CDATA&#91;
		<key>UIAppFonts</key>
		<array>
			<string>name-of-your-font.ttf</string>
		</array>
	&#93;&#93;></InfoAdditions>
</iPhone>

I’ve omitted lots of other things that are in my descriptor for brevity – keys specifying minimum iOS version, custom URL schemes, which devices the app targets – but you get the idea.

Once I had this all put together, it worked like a charm! Our storyboards look great as ever with their custom fonts!

Flash Builder 4.7 hangs loading workbench OSX

Today Flash Builder randomly started hanging while loading the workbench on startup.

I found a lot of places that said to delete the .snap directory located at [workspacelocation]/.metadata/.plugins/org.eclipse.core.resources but there was never a .snap file or folder.

Eventually I found a trick here that said the following:

remove all the <editor> elements in workspace\.metadata\.plugins\org.eclipse.ui.workbench\workbench.xml

I did that and at least got Flash Builder to start up.

You apparently can also delete all the files in the [workspacelocation]/.metadata/.plugins/org.eclipse.ui.workbench as well (this removes your custom window layouts), but I haven’t tried this method.

As a last-ditch effort, you could do one of the following:

  • delete your .metadata folder in your workspace folder. You will have to reimport ALL your projects after doing this.
  • close Flash Builder, rename your workspace folder (defaults to “Adobe Flash Builder 4.7”), and re-open Flash Builder. It will create a new, empty workspace. Then quit flash builder again, delete the empty workspace, and rename your old workspace to its old name. Hopefully when you start Flash Builder again, things will work better.
  • This post has the following workaround (copied here to protect against link-rot). This is for Flash Builder 4.5 but may work for 4.7.
    This happens because the Eclipse workspace gets corrupted. The easiest way I've found to recover from this is as follows:
     
    1. Use Windows Task Manager (Ctrl+Shift+Esc) to make sure FlashBuilder.exe isn't running as a process. End the process if it is.
    2. Navigate to your workspace folder (the default location is under your users folder in "Adobe Flash Builder 4.5", though you may have placed is elsewhere).
    Mine is c:\Users\grayson\Adobe Flash Builder 4.5
    3. There is a folder named .metadata (on Windows 7 there is an issue where it may appear as a nameless folder because Windows started truncating the "extension")
    move it to another location on your hard drive.
    4. Launch Flash Builder to make sure that this it has solved the issue.
    5. Close Flash Builder (this writes the default workspace settings to the .metadata folder in your workspace location)
    Inside the original copy of the .metadata folder you made, COPY the following folders to the same location in the newly created .metadata folder in your workspace folder, overwriting the files and folders that are there.
    .metadata\.plugins\org.eclipse.core.resources\
    .metadata\.plugins\org.eclipse.core.runtime\
    (as I mentioned before, Windows 7 can truncate the folder names to be without the last portion of the name, so you may see two folders that appear to be named "org.eclipse.core.runtime". Copying them will still work)
    6. This will restore the projects, workspace settings, and key bindings. (the dialog/window layout will be reset to the defaults and External Tool Configurations aren't copied. I looked but didn't find where those are stored)

FlashDevelop 4.6 BinaryHeader error on startup on Win64 8.1

Today FlashDevelop got stuck on startup into an infinite loop of the following error:

Binary stream '0' does not contain a valid BinaryHeader. Possible causes are invalid stream or object version change between serialization and deserialization.

I found this really old forum post that said to delete the whole FlashDevelop app data folder.

So, I deleted/renamed the folder located at C:/Users/YOURUSERNAME/AppData/Local/FlashDevelop, and it works again!