The U.S. Marine Corps has officially declared the MK22 Mod 0 Advanced Sniper Rifle (ASR) fully operational, a year ahead of schedule. Manufactured by Barrett Firearms, this cutting-edge system represents a monumental leap in sniper capabilities, offering unmatched precision, flexibility, and sustainability to Marines in the field.
A Game-Changer for Marine Snipers
The MK22 replaces the legacy M40A6 and Mk13 Mod 7 sniper rifles, consolidating their roles into a single modular platform. This bolt-action rifle supports multiple calibers—7.62x51mm NATO, .300 Norma Magnum, and .338 Norma Magnum—giving Marines the ability to tailor their weapon for specific mission requirements. With an effective range of up to 1,500 meters, the MK22 outpaces its predecessors while lightening the logistical load.
Kevin Marion, a logistics specialist with Marine Corps Systems Command, highlighted the operational advantages: “Marines like the ability to conduct caliber conversions at their level and the fact that they only have one rifle instead of the two it replaced. This shift improves operational efficiency, reduces the logistical burden, and lightens the individual Marine’s load.”
Barrett’s Commitment to Innovation
Barrett Firearms, renowned for its contributions to military precision weaponry, played a pivotal role in the MK 22’s development. Bryan James, CEO of Barrett Firearms, emphasized the importance of this milestone:
“The MK22 isn’t just another rifle; it’s a modular, mission-adaptable system that empowers the warfighter with unmatched precision and flexibility. We’re honored to contribute to this pivotal modernization effort for the U.S. Military and Marine Corps, and to support our nation’s elite forces.”
Barrett’s design philosophy centered on creating a complete system for operational efficiency. Each MK 22 kit includes three barrels, a state-of-the-art M317 Precision Day Optic (7-35x variable magnification), 15 magazines, a cleaning and tool kit, a sound suppressor, and mission-specific components like a scout sniper tripod and anti-reflection device.
The MK 22’s modularity allows Marines to quickly convert calibers in the field, ensuring readiness for any mission. The rifle’s design also simplifies maintenance, enabling most repairs to be completed at the organizational level. Should a barrel fail, it can be replaced without sidelining the weapon, a critical improvement over older systems.
“Maintenance is streamlined, and the ability to conduct caliber conversions in the field ensures that Marines are equipped for any mission, anytime, anywhere,” James added.
Collaboration Across Forces
The MK 22’s journey began as part of a Special Operations Command (SOCOM) initiative and transitioned to the Marine Corps via the “Special Operations Forces (SOF) to service” process. Contracting was led by the U.S. Army, whose collaboration with Barrett and the Marine Corps helped fast-track the program to full operational capability.
Maj. Michael Billings of Marine Corps Systems Command called the achievement a major win: “FOC a full year ahead of schedule is a testament to the teamwork and dedication of all parties involved. This milestone delivers enhanced sniper capabilities to the battlefield sooner than expected.”
Preparing for the Future Fight
The MK 22 exemplifies the Marine Corps’ commitment to staying ahead of near-peer adversaries like Russia and China. As Marines adopt this revolutionary system, they gain a tactical edge, ensuring readiness for the challenges of modern and future warfare.
As Bryan James aptly put it, “The MK 22 Mod 0 Advanced Sniper Rifle exemplifies our dedication to precision, innovation, and mission success. As the Marine Corps ushers in this new era of sniper capabilities, Barrett stands ready to support their efforts and the future fight.”
One year ago, I didn’t know how to bake bread. I just knew how to follow a recipe.
If everything went perfectly, I could turn out something plain but palatable. But should anything change—temperature, timing, flour, Mercury being in Scorpio—I’d turn out a partly poofy pancake. I presented my partly poofy pancakes to people, and they were polite, but those platters were not particularly palatable.
During a group vacation last year, a friend made fresh sourdough loaves every day, and we devoured it. He gladly shared his knowledge, his starter, and his go-to recipe. I took it home, tried it out, and made a naturally leavened, artisanal pancake.
I took my confusion to YouTube, where I found Hendrik Kleinwächter’s “The Bread Code” channel and his video promising a course on “Your First Sourdough Bread.” I watched and learned a lot, but I couldn’t quite translate 30 minutes of intensive couch time to hours of mixing, raising, slicing, and baking. Pancakes, part three.
It felt like there had to be more to this. And there was—a whole GitHub repository more.
The Bread Code gave Kleinwächter a gratifying second career, and it’s given me bread I’m eager to serve people. This week alone, I’m making sourdough Parker House rolls, a rosemary olive loaf for Friendsgiving, and then a za’atar flatbread and standard wheat loaf for actual Thanksgiving. And each of us has learned more about perhaps the most important aspect of coding, bread, teaching, and lots of other things: patience.
Resources, not recipes
The Bread Code is centered around a book, The Sourdough Framework. It’s an open source codebase that self-compiles into new LaTeX book editions and is free to read online. It might have exactly one recipe, if you can call a 68-page middle-section journey a recipe. It has 17 flowcharts, 15 tables, and dozens of timelines, process illustrations, and photos of sourdough going both well and terribly. Like any cookbook, there’s a bit about Kleinwächter’s history with this food, and some sourdough bread history. Then the reader is dropped straight into "How Sourdough Works," which is in no way a summary.
"To understand the many enzymatic reactions that take place when flour and water are mixed, we must first understand seeds and their role in the lifecycle of wheat and other grains," Kleinwächter writes. From there, we follow a seed through hibernation, germination, photosynthesis, and, through humans’ grinding of these seeds, exposure to amylase and protease enzymes.
I had arrived at this book with these specific loaf problems to address. But first, it asks me to consider, "What is wheat?" This sparked vivid memories of Computer Science 114, in which a professor, asked to troubleshoot misbehaving code, would instead tell students to “Think like a compiler,” or “Consider the recursive way to do it."
And yet, "What is wheat" did help. Having a sense of what was happening inside my starter, and my dough (which is really just a big, slow starter), helped me diagnose what was going right or wrong with my breads. Extra-sticky dough and tightly arrayed holes in the bread meant I had let the bacteria win out over the yeast. I learned when to be rough with the dough to form gluten and when to gently guide it into shape to preserve its gas-filled form.
I could eat a slice of each loaf and get a sense of how things had gone. The inputs, outputs, and errors could be ascertained and analyzed more easily than in my prior stance, which was, roughly, "This starter is cursed and so am I." Using hydration percentages, measurements relative to protein content, a few tests, and troubleshooting steps, I could move closer to fresh, delicious bread. Framework: accomplished.
I have found myself very grateful lately that Kleinwächter did not find success with 30-minute YouTube tutorials. Strangely, so has he.
Sometimes weird scoring looks pretty neat.
Kevin Purdy
Sometimes weird scoring looks pretty neat.
Kevin Purdy
I have tried doing decorative "leaves" and other little scoring designs, with varied results.
Kevin Purdy
I have tried doing decorative "leaves" and other little scoring designs, with varied results.
Kevin Purdy
Cross section.
Kevin Purdy
Cross section.
Kevin Purdy
I have tried doing decorative "leaves" and other little scoring designs, with varied results.
Kevin Purdy
Cross section.
Kevin Purdy
The slow bread of childhood dreams
“I have had some successful startups; I have also had disastrous startups,” Kleinwächter said in an interview. “I have made some money, then I’ve been poor again. I’ve done so many things.”
Most of those things involve software. Kleinwächter is a German full-stack engineer, and he has founded firms and worked at companies related to blogging, e-commerce, food ordering, travel, and health. He tried to escape the boom-bust startup cycle by starting his own digital agency before one of his products was acquired by hotel booking firm Trivago. After that, he needed a break—and he could afford to take one.
“I went to Naples, worked there in a pizzeria for a week, and just figured out, ‘What do I want to do with my life?’ And I found my passion. My passion is to teach people how to make amazing bread and pizza at home,” Kleinwächter said.
Kleinwächter’s formative bread experiences—weekend loaves baked by his mother, awe-inspiring pizza from Italian ski towns, discovering all the extra ingredients in a supermarket’s version of the dark Schwarzbrot—made him want to bake his own. Like me, he started with recipes, and he wasted a lot of time and flour turning out stuff that produced both failures and a drive for knowledge. He dug in, learned as much as he could, and once he had his head around the how and why, he worked on a way to guide others along the path.
Too thick to be a flatbread, too flat to slice for breakfast: The painful pancake.
Kevin Purdy
Too thick to be a flatbread, too flat to slice for breakfast: The painful pancake.
Kevin Purdy
You wanted avocado toast; now you’ve got… this.
Kevin Purdy
You wanted avocado toast; now you’ve got… this.
Kevin Purdy
Too thick to be a flatbread, too flat to slice for breakfast: The painful pancake.
Kevin Purdy
You wanted avocado toast; now you’ve got… this.
Kevin Purdy
Bugs and syntax errors in baking
When using recipes, there’s a strong, societally reinforced idea that there is one best, tested, and timed way to arrive at a finished food. That’s why we have America’s Test Kitchen, The Food Lab, and all manner of blogs and videos promoting food “hacks.” I should know; I wrote up a whole bunch of them as a young Lifehacker writer. I’m still a fan of such things, from the standpoint of simply getting food done.
As such, the ultimate “hack” for making bread is to use commercial yeast, i.e., dried “active” or “instant” yeast. A manufacturer has done the work of selecting and isolating yeast at its prime state and preserving it for you. Get your liquids and dough to a yeast-friendly temperature and you’ve removed most of the variables; your success should be repeatable. If you just want bread, you can make the iconic no-knead bread with prepared yeast and very little intervention, and you’ll probably get bread that’s better than you can get at the grocery store.
Baking sourdough—or “naturally leavened,” or with “levain”—means a lot of intervention. You are cultivating and maintaining a small ecosystem of yeast and bacteria, unleashing them onto flour, water, and salt, and stepping in after they’ve produced enough flavor and lift—but before they eat all the stretchy gluten bonds. What that looks like depends on many things: your water, your flours, what you fed your starter, how active it was when you added it, the air in your home, and other variables. Most important is your ability to notice things over long periods of time.
The Bread Code‘s depiction of how sourdough starters are born, developed, and refined.
The Bread Code
The Bread Code‘s depiction of how sourdough starters are born, developed, and refined.
The Bread Code
If you take nothing else from The Bread Code, take this: You can measure a sample of your dough in an easy-to-read container, rather than guess at a big bowl.
The Bread Code
If you take nothing else from The Bread Code, take this: You can measure a sample of your dough in an easy-to-read container, rather than guess at a big bowl.
The Bread Code
The Bread Code‘s depiction of how sourdough starters are born, developed, and refined.
The Bread Code
If you take nothing else from The Bread Code, take this: You can measure a sample of your dough in an easy-to-read container, rather than guess at a big bowl.
The Bread Code
When things go wrong, debugging can be tricky. I was able to personally ask Kleinwächter what was up with my bread, because I was interviewing him for this article. There were many potential answers, including:
I should recognize, first off, that I was trying to bake the hardest kind of bread: Freestanding wheat-based sourdough
You have to watch—and smell—your starter to make sure it has the right mix of yeast to bacteria before you use it
Using less starter (lower “inoculation”) would make it easier not to over-ferment
Eyeballing my dough rise in a bowl was hard; try measuring a sample in something like an aliquot tube
Winter and summer are very different dough timings, even with modern indoor climate control.
But I kept with it. I was particularly susceptible to wanting things to go quicker and demanding to see a huge rise in my dough before baking. This ironically leads to the flattest results, as the bacteria eats all the gluten bonds. When I slowed down, changed just one thing at a time, and looked deeper into my results, I got better.
YouTube faces and TikTok sausage
Emailing and trading video responses with Kleinwächter, I got the sense that he, too, has learned to go the slow, steady route with his Bread Code project.
For a while, he was turning out YouTube videos, and he wanted them to work. “I’m very data-driven and very analytical. I always read the video metrics, and I try to optimize my videos,” Kleinwächter said. “Which means I have to use a clickbait title, and I have to use a clickbait-y thumbnail, plus I need to make sure that I catch people in the first 30 seconds of the video.” This, however, is “not good for us as humans because it leads to more and more extreme content.”
Kleinwächter also dabbled in TikTok, making videos in which, leaning into his German heritage, “the idea was to turn everything into a sausage.” The metrics and imperatives on TikTok were similar to those on YouTube but hyperscaled. He could put hours or days into a video, only for 1 percent of his 200,000 YouTube subscribers to see it unless he caught the algorithm wind.
The frustrations inspired him to slow down and focus on his site and his book. With his community’s help, The Bread Code has just finished its second Kickstarter-backed printing run of 2,000 copies. There’s a Discord full of bread heads eager to diagnose and correct each other’s loaves and occasional pull requests from inspired readers. Kleinwächter has seen people go from buying what he calls “Turbo bread” at the store to making their own, and that’s what keeps him going. He’s not gambling on an attention-getting hit, but he’s in better control of how his knowledge and message get out.
“I think homemade bread is something that’s super, super undervalued, and I see a lot of benefits to making it yourself,” Kleinwächter said. “Good bread just contains flour, water, and salt—nothing else.”
You gotta keep doing it—that’s the hard part
I can’t say it has been entirely smooth sailing ever since I self-certified with The Bread Code framework. I know what level of fermentation I’m aiming for, but I sometimes get home from an outing later than planned, arriving at dough that’s trying to escape its bucket. My starter can be very temperamental when my house gets dry and chilly in the winter. And my dough slicing (scoring), being the very last step before baking, can be rushed, resulting in some loaves with weird “ears,” not quite ready for the bakery window.
But that’s all part of it. Your sourdough starter is a collection of organisms that are best suited to what you’ve fed them, developed over time, shaped by their environment. There are some modern hacks that can help make good bread, like using a pH meter. But the big hack is just doing it, learning from it, and getting better at figuring out what’s going on. I’m thankful that folks like Kleinwächter are out there encouraging folks like me to slow down, hack less, and learn more.
Warner Bros partnered with a PR firm to create Wayne Enterprises, a company that sells luxury items inspired by Batman and his billionaire alter ego, Bruce Wayne. That includes ten fully functional replicas of the Tumbler, the version of the Batmobile from Nolan’s Dark Knight Trilogy. The $3M vehicles have a 6.2L 525 hp engine plus gun and jet engine effects.
Axios’ CEO said this week that regular citizens can’t be journalists because they don’t have fancy credentials and demanded that we take corporate news seriously again.
Ready to upgrade your tooth-brushing game beyond that basic manual brush? It’s time to get something that can actually clean your teeth effectively. The Philips Sonicare ProtectiveClean 5300 is like having a tiny dental hygienist living in your bathroom. It buzzes at 62,000 movements per minute and tells you when you’re brushing too hard, which is something most of us are guilty of. But most of all, it gives you that deep clean that you’re craving, and you can stave off dental issues and cavities by using it.
This electric toothbrush has a little something for everyone, which is part of what makes it such a great option for making sure your teeth are sparkling clean. Got sensitive gums? There’s a mode for that. Fighting coffee stains? There’s a whitening mode. All you really need to do is supply toothpaste and work the brush along all the important spots. Then your reward for being diligent is a whole mouth full of sparkling, glittery teeth with a superior clean that feels much more complete than what you’d get from a basic toothbrush.
Just want a basic clean? Yep, there’s a mode for that too. The pressure sensor is particularly clever – it actually tells you when you’re going too hard, which helps protect your gums from that overzealous morning brushing. And unlike some electric toothbrushes that die after a few days, this one keeps going for two weeks on a single charge, perfect for trips where you might forget the charger.
Anyone who’s been told they brush too hard at the dentist can use this brush, as can anyone who wants to upgrade their oral care without spending hundreds. The included travel case is actually decent too, not just a flimsy plastic afterthought.
I recently became aware of WeSQL. A MySQL-compatible database that separates compute and storage, using S3 as the storage layer. The product uses a columnar format by default which is significantly more space-efficient than InnoDB.
WeSQL introduces a new storage engine called SmartEngine using a LSM-tree-based structure that is ideal for a storage bucket implementation, and documentation shows the implementation of raft replication to combat latency concerns. There is a lot more information to review, the serverless architecture and WeScale, a database proxy and resource manager.
It was very easy to take it for an initial spin using a docker container and an AWS S3 bucket. I would really like to try CloudFlare R2 which implements the S3 API.
Under the covers there are over 180 new variables comprising 83 for the smartengine, 57 for raft, and 22 for objectstore and more. This implies a lot of tunable options and a lot of complexity to optimize for a variety of workloads using the 79 new status variables.
I was able to launch a demo and confirm
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 8.0.35 |
+-----------+
1 row in set (0.01 sec)
mysql> SELECT @@wesql_version;
+-----------------+
| @@wesql_version |
+-----------------+
| 0.1.0 |
+-----------------+
1 row in set (0.00 sec)
One of my early tests showed that it does not support FOREIGN KEYS, which is not a major concern.
ERROR 1235 (42000) at line 10: SE currently doesn't support foreign key constraints
I did have some subsequent issues with the current docs version 8.0.35-0.1.0_beta1.37 and I did revert to a prior version from docs earlier this week 8.0.35-0.1.0_beta1.gedaf338.36. Given it’s a very new product I am sure there is a lot of ongoing development.
This is just a quick introduction but it’s a definitely a different architecture in the RDBMS landscape for MySQL compatibility. I hope to run some more tests using the provided sysbench use cases and my own workloads to delve under the covers more.
At the 2024 Federalist Society National Lawyers Convention, Professor Mark W. Smith delivered a compelling speech on the Second Amendment, emphasizing the Supreme Court’s decision in New York State Rifle & Pistol Association v. Bruen and its profound impact on gun rights in America.
Understanding the “Unqualified Command” of the Second Amendment
Professor Smith began by highlighting the Supreme Court’s characterization of the Second Amendment as an “unqualified command.” This designation underscores that the right to keep and bear arms is fundamental and not subject to arbitrary restrictions. He stressed that any ambiguity in historical context should default to the clear text of the Second Amendment, ensuring that the government bears the burden of justifying any limitations on this right.
The Role of Historical Analogues in Gun Control Legislation
A significant portion of the speech focused on how courts should evaluate historical precedents when assessing modern gun control laws. Professor Smith outlined key criteria for determining suitable historical analogues:
Actual Laws: Only enacted laws, not mere proposals or societal norms, should be considered.
Relevant Time Period: The primary focus should be on laws from 1791, the year the Second Amendment was ratified, as these reflect the original understanding of the right.
Constitutional Consistency: Historical laws rooted in unconstitutional practices, such as those based on racial discrimination, should be disregarded.
Prevalence and Duration: Laws that were widespread and enduring carry more weight than isolated or short-lived statutes.
By adhering to these guidelines, courts can ensure that modern interpretations of the Second Amendment remain faithful to its original intent.
Applying the “Why” & “How” Analysis
Professor Smith introduced the “why” and “how” framework to assess the relevance of historical laws to contemporary issues:
Why: The purpose behind the historical law.
How: The method by which the law was implemented.
He illustrated this with the Supreme Court’s decision in District of Columbia v. Heller, where the Court found that historical bans on “dangerous and unusual” weapons did not justify modern handgun bans, as handguns are commonly used for lawful purposes today.
The Impact of Bruen & Rahimi on Second Amendment Jurisprudence
Discussing the Bruen decision, Professor Smith noted that the Court rejected New York’s restrictive “may issue” permitting system, finding no historical precedent for such limitations on public carry. He also addressed the Rahimi case, emphasizing that it represents a routine application of the principles established in Heller and Bruen, reinforcing the necessity for courts to adhere to historical context when evaluating gun control measures.
Guarding Against Overgeneralization
To prevent the erosion of Second Amendment rights through overly broad interpretations, Professor Smith proposed several safeguards:
Consistency with the Second Amendment’s Text: Derived principles must not contradict the explicit guarantee of the right to keep and bear arms.
Alignment with Supreme Court Precedent: Any historical principle must be in harmony with established Court rulings.
Focus on Law-Abiding Citizens: The analysis should center on the rights of lawful individuals, not the actions of criminals.
Preservation of the Amendment’s Purpose: Any derived principle should uphold the Second Amendment’s role in protecting against tyranny and ensuring self-defense.
By implementing these measures, courts can maintain a faithful interpretation of the Second Amendment, safeguarding it from dilution through generalized reasoning.
Let’s Get it Done!
Professor Smith’s address serves as a vital reminder of the importance of adhering to the original understanding of the Second Amendment. His insights provide a robust framework for evaluating modern gun control laws, ensuring that the fundamental right to keep and bear arms remains protected for future generations.
We live in a weird world, a world where someone will take a perfectly fine AR-15 action and turn it into a wannabe Star Wars blaster. Yet, if you can accept that madness, Canto Arms wants to talk to you. They have just announced an upgrade to their Star Wars-esque pistol, and present to the well-heeled buyer the new DL-44 Hero.
At this point, some TFB readers are wondering what on earth the weirdo pistol pictured above could possibly be. Others might remember back in 2021 when we showed you the first Canto Arms DL44 pistol.
Back then, we told you:
In recent years, Star Wars fans have begun to ditch their dreams of building a Mauser C96 based replica of Han Solo’s DL-44 blaster due to soaring costs, and have a new hope in the much more affordable AR-15 DL-44 clones. Enter Canto Arms, which, at present have a dedicated line of AR-15 DL-44 clones for sale, both as complete .22LR pistols, and as parts kits, plus many other accessory options to complete the DL-44 build you never thought possible. Purists will no doubt scoff at a non-Mauser blaster clone, but with Canto Arms’ Nocturne 22 Heavy Blaster, you can have a close representation of Han Solo’s blaster for less than half of what a C96 conversion would cost, and you get to save the remaining Mausers at the same time.
So if you want to concealed carry like Luke Skywalker but on a Tusken Raider budget, the DL-44 is expensive, but a lot less expensive than building a replica Star Wars blaster from a C96 (and don’t get us started on the cost of building an E-11 Stormtrooper Blaster from a Sterling submachine gun…).
What sets the DL-44 Hero apart?
It looks as if the DL-44 Hero is basically a gussied-up version of the original .22LR pistol.
In the film industry, a hero prop weapon is a meticulously crafted piece designed to dazzle the audience with up close detail. Inspired by this concept, we proudly present the DL-44 Hero – a stunningly detailed blaster that captures the very essence of this legendary weapon. From the finely machined detail of the billet upper and lower receivers to the authentic Aurebesh engravings, this blaster is sure to turn heads at the range.
So, Star Wars-universe engravings on a custom upper and lower (the lower is from Strike Industries). There’s also a round knob on the receiver that wasn’t on the original DL-44, making the Hero look more like the original C96-based blaster used in the Star Wars movies. There’s an improved mag release, machined from billet, and trigger upgrades from Longitudinal Grind. A BoreBuddy quiet bolt group is available as an option.
Canto Arms throws in a nylon X-Form mag with the purchase, and you can buy more if you want matching reloads. Canto Arms also includes the scope, rings and 45-degree mounts, but you must install the scope yourself.
Asking price? $1,499.95. See more details on Canto Arms’ website here.
How to Train Your Dragon follows a tribe of Vikings who display their worth by hunting mighty dragons. That is, save for the chieftain’s son, Hiccup (Mason Thames of The Black Phone fame), who befriends a jet-black dragon named Toothless and trains it to become man’s best friend—all while keeping their training sessions a secret from his aforementioned tribe of dragon-killing Vikings.
The teaser trailer gets everything out of the way that detractors would break their bingo cards out for when it comes to the song and dance of yet another live-action project from Hollywood. First off, it shows us the sweeping vistas of a mountainous countryside, impressive ship craftsmanship, and original film actor Gerard Butler in a Viking get-up as the chieftain, Stoick. The trailer also gives us a glimpse of Hiccup and Toothless meeting for the first time… all the while replicating the original film’s big referential moment of Toothless accepting Hiccup’s head pats.
While we couched today’s trailer by saying it was our first look, it would behoove us to mention that How to Train Your Dragon’s teaser trailer leaked ahead of its official release in non-U.S. territories. Though, in a glass half-full look at the whole situation, folks weren’t complaining about how bad the trailer looked like they did with the first official still image of the film, pointing to its desaturated colors and overall lack of whimsy.
As the trailer showcases, the movie’s CG animation for Toothless looks pretty spectacular and the set pieces for the Viking village are also a comparable to the animated films. Although the brief teaser nails the important component of making Toothless look good, time will tell whether the film will measure up to its originator’s sense of heart and humor.
How to Train Your Dragon originally released in 2010. Alongside Butler, the film starred Jay Baruchel as Hiccup and America Ferrera as his love interest, Astrid. It became so popular that it garnered two sequel films, five short films, and two TV series. The live-action film was written and directed by Dean DeBlois, who co-wrote and co-directed the animated original, and wrote and directed its two sequels. Additional cast members include Nico Parker (The Last of Us) as Astrid, Nick Frost as Gobber, and Julian Dennison (Deadpool 2) as Fishlegs.
How To Train Your Dragon is slated to release June 13, 2025.
This was principally written for my SQL students but I thought it might be useful to others. SQL calculation are performed row-by-row in the SELECT-list. In its simplest form without even touching a table, you can add two literal numbers like this:
SELECT 2 + 2 AS result;
It will display the result of the addition to the column alias result as a derived table, or the following result:
+--------+
| result |
+--------+
| 4 |
+--------+
1 row in set (0.00 sec)
Unfortunately, the use of literal values as shown above doesn’t really let you see how the calculation is made row-by-row because it only returns only one row. You can rewrite the two literal values into one variable by using a Common Table Expressions (CTEs). The CTE creates an struct tuple with only one x element. Another way to describe what the CTE does would say, it creates a derived table named struct with a single x column in the SELECT-list.
The CTE runs first, then a subsequent query may use the CTE’s derived table results. Below is a query that uses the value in the struct.x derived table (or references the struct tuple’s x element) twice while assigning the value to a new column alias, labelled result. The FROM clause places the struct tuple in the queries namespace, which lets you reference it in the SELECT-list.
WITH struct AS
(SELECT 2 AS x)
SELECT struct.x + struct.x AS result
FROM struct;
Like the literal example, it will display the result of the addition to the column alias result as a derived table of one row:
+--------+
| result |
+--------+
| 4 |
+--------+
1 row in set (0.00 sec)
Having laid a basis for a simple calculation in one row, let’s expand the example and demonstrate how to perform row-by-row calculations. The example requires introducing some new concepts. One uses the UNION ALL set operator to fabricate a CTE derived table with three rows. Another uses a comma within the WITH clause to create two derived tables or CTEs. The last uses the CROSS JOIN to add the single row CTE’s single y column to each of the rows returned by the multiple row CTE.
The CROSS JOIN is a Cartesian product, which multiplies the rows in one table against the rows in another table while adding the columns from each table. That means fabricating a table of one column and one row lets you put a variable into all the rows of another table or set of tables combined through an equijoin or non-equijoin operation.
The query below takes a struct1 derived table of one column and three rows and a struct2 derived table of one column and one row, then uses a CROSS JOIN to create a new derived table, which would be a table of two columns and three rows. The Cartesian product only provides the two columns that we will multiply to create new data.
The SELECT-list lets us fabricate a new column where we multiply the values of column x and column y to create a set of new results in column result.
WITH struct1 AS
(SELECT 1 AS x UNION ALL
SELECT 2 AS x UNION ALL
SELECT 3 AS x)
, struct2 AS
(SELECT 10 AS y)
SELECT struct1.x AS x
, struct2.y AS y
, struct1.x * struct2.y AS result
FROM struct1 CROSS JOIN struct2;
The query returns the following results, which show the values used to calculate the result and the result:
+---+----+--------+
| x | y | result |
+---+----+--------+
| 1 | 10 | 10 |
| 2 | 10 | 20 |
| 3 | 10 | 30 |
+---+----+--------+
3 rows in set (0.00 sec)
As a rule, the columns x and y would not be displayed in the final derived table. You would only see the result columns’ values.
Let’s use an example from Alan Bwaulieu’s Learning SQL book with a twist. Rather than manually fabricating the ordinal numbers twice, let’s use the scope reference of a subsequent CTE to reference an earlier CTE. That would create two ten row tables of one column each, or a Cartesian product of a 100 row table with two columns. Then, let’s use the SELECT-list lets us fabricate only a new column, which will add 1 to the numbers 0 to 99 to give us the numbers 1 to a 100.
WITH ones AS
(SELECT 0 AS x UNION ALL
SELECT 1 AS x UNION ALL
SELECT 2 AS x UNION ALL
SELECT 3 AS x UNION ALL
SELECT 4 AS x UNION ALL
SELECT 5 AS x UNION ALL
SELECT 6 AS x UNION ALL
SELECT 7 AS x UNION ALL
SELECT 8 AS x UNION ALL
SELECT 9 AS x )
, tens AS
(SELECT x * 10 AS x FROM ones)
SELECT ones.x + tens.x + 1 AS ordinal
FROM ones CROSS JOIN tens
ORDER BY ordinal;
Moving on to more complex math, let’s create a numerals table with the result from our prior query. It will enable calculating the factors of exponents. The easiest way to create the table is shown below (only caveat is that it will build it with a biting rather than an int data type).
CREATE TABLE numerals AS
WITH ones AS
(SELECT 0 AS x UNION ALL
SELECT 1 AS x UNION ALL
SELECT 2 AS x UNION ALL
SELECT 3 AS x UNION ALL
SELECT 4 AS x UNION ALL
SELECT 5 AS x UNION ALL
SELECT 6 AS x UNION ALL
SELECT 7 AS x UNION ALL
SELECT 8 AS x UNION ALL
SELECT 9 AS x )
, tens AS
(SELECT x * 10 AS x FROM ones)
SELECT ones.x + tens.x + 1 AS ordinal
FROM ones CROSS JOIN tens
ORDER BY ordinal;
It can be described after running the foregoing script in MySQL as:
+---------+--------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+--------+------+-----+---------+-------+
| ordinal | bigint | NO | | 0 | |
+---------+--------+------+-----+---------+-------+
1 row in set (0.00 sec)
The next query accepts a substitution variable into the WITH clause, which means an external program will call it. (Although, you could use a session level variable, which I would discourage.) This query returns the factors for any given exponent:
WITH magic AS
(SELECT %s AS vkey)
SELECT CONCAT(magic.vkey,'^',LOG(magic.vkey,n.ordinal)) AS powers
, n.ordinal AS result
FROM numerals n CROSS JOIN magic
WHERE MOD(n.ordinal,magic.vkey) = 0
AND LOG(magic.vkey,n.ordinal) REGEXP '^[0-9]*$'
OR n.ordinal = 1
ORDER BY n.ordinal;
FYI, the regular expression is used to guarantee only integer return values and the 1 returns the identity property of an exponent raised to the zero power.
Assuming you created the numerals table, put the foregoing query in a query.sql file (because I was to lazy to write the full parameter handling), and you run it in the same directory as this Python program, it’ll take any valid integer as a value.
#!/usr/bin/python
# ------------------------------------------------------------
# Name: power.py
# Date: 19 Oct 2024
# ------------------------------------------------------------
# Purpose:
# -------
# The program shows you how to provide a single agrument
# to a query and print the formatted output.
#
# You can call the program:
#
# ./power.py 3
#
# ------------------------------------------------------------
# Import libraries.
import sys
import mysql.connector
from mysql.connector import errorcode
# ============================================================
# Define a local padding function.
# ============================================================
def pad(valueIn):
# Define local variable.
padding = ''
# Convert single digit numbers to strings.
if isinstance(valueIn,int) and len(str(valueIn)) == 1:
padding = ' '
# Return padding space.
return padding
# ============================================================
# End local function defintion.
# ============================================================
# Define any local variables.
powerIn = 2
query = ""
# ============================================================
# Capture argument list minus the program name.
# ============================================================
arguments = sys.argv[1:]
# ============================================================
# If one or more arguments exists and the first one is an
# a string that can cast to an int, convert it to an int,
# assign it to a variable, and ignore any other arguments
# in the list.
# ============================================================
if len(arguments) >= 1 and arguments[0].isdigit():
powerIn = int(arguments[0])
# ============================================================
# Use a try-catch block to read and parse a query from a
# a file found in the same local directory as the Python
# program.
# ============================================================
try:
file = open('query.sql','r')
query = file.read().replace('\n',' ').replace(';','')
file.close()
except IOError:
print("Could not read file:", fileName)
# ============================================================
# Attempt connection in a try-catch block.
# ============================================================
# --------------------------------------------------------
# Open connection, bind variable in query and format
# query output before closing the cursor.
# --------------------------------------------------------
try:
# Open connection.
cnx = mysql.connector.connect(user='student', password='student',
host='127.0.0.1',
database='studentdb')
# Create cursor.
cursor = cnx.cursor()
# Execute cursor, and coerce string to tuple.
cursor.execute(query, (powerIn,))
# Display the rows returned by the query.
for (powers, result) in cursor:
print((" {} is: {}").format(powers, pad(result) + str(result)))
# Close cursor.
cursor.close()
# --------------------------------------------------------
# Handle MySQL exception
# --------------------------------------------------------
except mysql.connector.Error as e:
if e.errno == errorcode.ER_ACCESS_DENIED_ERROR:
print("Something is wrong with your user name or password")
elif e.errno == errorcode.ER_BAD_DB_ERROR:
print("Database does not exist")
else:
print("Error code:", e.errno) # error number
print("SQLSTATE value:", e.sqlstate) # SQLSTATE value
print("Error message:", e.msg) # error message
# --------------------------------------------------------
# Close connection after try-catch completes.
# --------------------------------------------------------
# Close the connection when the try block completes.
else:
cnx.close()
If you forget to call it with a numeric parameter, it uses 2 as the default. You would call it as follows from a Linux prompt from the local directory:
./power.py
It returns:
2^0 is: 1
2^1 is: 2
2^2 is: 4
2^3 is: 8
2^4 is: 16
2^5 is: 32
2^6 is: 64
If you call it with a numeric parameter, it uses the numeric value. You would call it as follows from a Linux prompt from the local directory:
./power.py 3
It returns:
3^0 is: 1
3^1 is: 3
3^2 is: 9
3^3 is: 27
3^4 is: 81
As always, I hope the post helps folks sort out how and why things work.