AI 资讯
Subqueries vs CTEs: Query Optimizer Internals & Memory Spooling Explained
Many engineers believe Common Table Expressions (CTEs) are always faster than subqueries. In modern SQL Server (and PostgreSQL), that is a myth . Here is what actually happens under the hood: 1. Inlining & The Query Optimizer By default, the SQL optimizer treats standard CTEs and derived tables (subqueries) almost identically: The engine expands both into the same relational tree. They generate the exact same execution plan and I/O cost . -- Pattern A: Derived Table (Subquery) SELECT DeptID , EmpName , Salary FROM ( SELECT DeptID , EmpName , Salary , DENSE_RANK () OVER ( PARTITION BY DeptID ORDER BY Salary DESC ) AS rnk FROM Employees ) RankedData WHERE rnk <= 2 ; -- Pattern B: Common Table Expression (CTE) WITH RankedData AS ( SELECT DeptID , EmpName , Salary , DENSE_RANK () OVER ( PARTITION BY DeptID ORDER BY Salary DESC ) AS rnk FROM Employees ) SELECT DeptID , EmpName , Salary FROM RankedData WHERE rnk <= 2 ; 2. When CTEs Truly Win: Readability & Pipeline Stacking: You can chain 5 CTEs sequentially without deeply nested pyramid brackets. In-Place Deduplication: In SQL Server, you can run DELETE directly on a CTE, and it deletes duplicate rows straight from the real underlying table! WITH DuplicateCleaner AS ( SELECT CustomerID , Email , ROW_NUMBER () OVER ( PARTITION BY Email ORDER BY RegistrationDate ASC ) AS rn FROM Customers WHERE Email IS NOT NULL ) DELETE FROM DuplicateCleaner WHERE rn > 1 ; -- ✅ Clean in-place deletion! 3. The Big Trap (Spooling Overhead): If you reference the same CTE multiple times in a query (e.g. CTE_A JOIN CTE_A ), SQL Server may execute the underlying CTE query multiple times or create a Lazy Spool in tempdb . -> Fix: For heavy multi-million row reuse, use a Temporary Table ( #TempTable ) with an explicit Clustered Index instead! 💡 How do you choose between CTEs, Temp Tables, and Subqueries in your pipelines? 💼 Connect on LinkedIn: linkedin.com/in/arpitmbangre
AI 资讯
How I Debugged a phpMyAdmin 500 Error While Importing a Large SQL File on Laragon
I recently ran into a weird issue while working on a Laravel project on Windows using Laragon . Everything was working fine until I tried to import a database through phpMyAdmin. Instead of an SQL error, phpMyAdmin simply returned: Internal Server Error The server encountered an internal error or misconfiguration... No useful message. Just HTTP 500. My SQL file was around 97 MB , so at first I thought it was probably a PHP upload limit issue. It wasn't that simple. Here is how I debugged it. 1. Check which PHP configuration is actually running From Laragon Terminal: php --ini Then I checked the important error settings: php.exe -r "echo 'error_log=' . ini_get('error_log') . PHP_EOL;" php.exe -r "echo 'log_errors=' . ini_get('log_errors') . PHP_EOL;" php.exe -r "echo 'display_errors=' . ini_get('display_errors') . PHP_EOL;" My output was: error_log=D:/C-data/laragon/tmp/php_errors.log log_errors=1 display_errors=1 One small Laragon/Git Bash issue I also found was: type php returned: php is aliased to `winpty php.exe' Because of that, commands like: php -i | grep ... sometimes returned: stdout is not a tty Using php.exe directly avoids that problem. 2. Check the PHP error log My PHP error log was: D:/C-data/laragon/tmp/php_errors.log I reproduced the import error and checked it: tail -n 50 /d/C-data/laragon/tmp/php_errors.log Nothing useful appeared. That was an important clue. 3. Make sure browser PHP and CLI PHP use the same php.ini I created a temporary file: <?php phpinfo (); Then opened it through the browser. Important values were: Server API: CGI/FastCGI PHP Version: 8.4.4 Loaded Configuration File: D:\C-data\laragon\bin\php\php-8.4.4-nts-Win32-vs17-x64\php.ini My PHP limits were already high enough: upload_max_filesize = 512M post_max_size = 512M memory_limit = 512M max_execution_time = 36000 So the 97 MB SQL file should have been allowed by PHP. 4. Check Apache logs I located the Apache error log with: grep -Ri "ErrorLog" /d/C-data/laragon/etc/apache2 /d/C-da
AI 资讯
How I Built Memory for a Local AI Companion Without Sending Chats to a Server
A chatbot can sound convincing for five minutes without remembering anything. Then you mention the job interview you were stressed about last week, the name of your dog, or a small detail from a late-night conversation. It replies like none of it happened. That is where most "AI companion" demos fall apart. I am building Local Waifu , a desktop AI companion that runs on the user's own Mac or PC. One of the rules I set early was simple: conversations and memories should stay on the machine. No central chat database. No server that needs to be online for the character to remember someone. The rule sounds clean. Building it was not. Saving chats is not memory The first version of memory was the obvious one: save messages. That gives you history, which is useful, but it does not solve recall. A long chat history grows fast. Sending all of it back to a local language model on every message is slow, expensive in context space, and usually makes the reply worse. The model does not need to see every conversation from the last six months. It needs the few pieces that matter right now. If someone says, "I have to take Luna to the vet tomorrow," the character should be able to find that Luna is their dog. It should not need to reread hundreds of unrelated messages about work, movies, and dinner plans to get there. So I treated chat history and long-term memory as different things. Chat history is the recent conversation. It gives the model immediate context. Long-term memory is a small collection of facts, moments, preferences, and relationship details that may matter later. Those memories need to be searchable by meaning, not only by exact words. The memory data stays in SQLite I wanted the app to work without a hosted database, so the storage layer is local SQLite. Each character gets their own data. Chats, memories, extracted entities, and relationships are stored locally on the device. If a user creates two characters, one character does not quietly inherit the other one's
AI 资讯
How to Practice SQL Online With Nothing Installed (And Where Your Data Goes)
By Michael Nocito , data analyst · Published August 8, 2026 By the end of this page you will be running real SQL against a real database with nothing installed, and you will know which of the free browser tools suits which job. You will also know the thing none of them puts on the front page: some of them run entirely inside your browser, and some upload whatever you paste to a stranger's server. That difference decides what you are allowed to practise on. Here is what to actually do today. If you want a database already loaded and questions already written, open sql-practice.com . If you want to create your own tables and share the result with someone, open DB Fiddle . Both start working immediately with no account. The short version: browser-only tools keep your data on your machine, server-backed tools do not, and neither kind is the right place for anything from work. Where the data goes is the one idea that should drive your choice, so it gets the picture. The original carries a diagram here. In words: Two panels side by side, each drawn as a laptop outline containing a browser window. In the left panel a small data box sits inside the browser window, with a short circular arrow looping back into itself, showing the data never leaves the laptop. In the right panel the same data box has a long arrow leading out of the laptop, across a gap, and into a separate server rack drawn beyond the laptop's edge, with a copy of the data box now sitting in the rack as well. The original box remains, showing the data has been copied out rather than moved. Every tool below was opened and checked on 8 August 2026. These sites change often, so the descriptions describe what was actually on screen, and anything I could not confirm by looking is not claimed here. 1. Run your first query, right now Before the explanation: what do you think has to exist on your computer for a SELECT statement to return rows? The honest answer is nothing at all, and that surprises people who have sp
开发者
Where to Get a Sample Database to Practice SQL (And How to Check It Loaded)
By Michael Nocito , data analyst · Published August 8, 2026 By the end of this page you will have a real database sitting on your own computer, with 11 tables, 3,503 tracks and 412 customer invoices in it, and you will have run a query that proves every table arrived intact. Then you will run a join across two of those tables, which is the thing a single spreadsheet can never teach you. It takes about five minutes and costs nothing. Here is what to actually do today. Download the Chinook database file, open it in DB Browser for SQLite, and run one query that counts the rows in every table. If the counts match the ones printed below, you have a working practice environment and you can stop shopping for one. The short version: get Chinook_Sqlite.sqlite , open it, count the rows, then join two tables. Northwind and Sakila are the other two names you will see, and there is a table further down saying when each is the right pick. The reason a sample database beats the CSV you already have is one idea, so it gets the picture. The original carries a diagram here. In words: Two panels side by side. The left panel holds a single grid of rows and columns, standing alone with nothing attached to it. The right panel holds four smaller grids arranged around each other. A highlighted column at the edge of each small grid is joined by a solid line to a matching highlighted column on a neighbouring grid, so all four grids are wired together into a connected shape. The left panel has no lines at all, because there is nothing for a line to reach. Every number on this page is real. I downloaded Chinook v1.4.5 and Northwind on 8 August 2026 and ran each query with SQLite 3.51.1. The counts, the outputs and the row multiplication are what came back, not what should have come back. If you have no database software at all yet, how to set up a SQL database is the fifteen-minute version of that step, and this page picks up right after it. 1. Why one CSV is not enough Before the explanation:
AI 资讯
Column Comments in PostgreSQL and MySQL: How to Document Columns Without a Migration
Disclosure: I build Schemity , a desktop ERD tool - this post is from our blog and uses it for the examples. TL;DR: The database has a built-in place to document a column - COMMENT ON COLUMN in PostgreSQL, the COMMENT attribute in MySQL - and almost nobody fills it in, because a sentence of prose has to travel the same path as a schema change: a migration file, a review, a deploy. Schemity keeps field descriptions in the diagram instead, where editing one generates no SQL, reads existing database comments in on import, and exports the result as a data dictionary. You can document a database column without touching the database: write the description in the model rather than in the schema. That sounds like a dodge until you price the alternative. The database's own mechanism for column documentation, COMMENT ON COLUMN in PostgreSQL and the COMMENT attribute in MySQL, sends a sentence of prose down exactly the same path as a change to how data is stored - a migration file, a code review, an approval, a deploy window - and on MySQL it does something worse than that. Schemity keeps field descriptions in the diagram, where editing one produces no SQL at all. This is why so many production schemas have thousands of columns and almost no comments. Not because nobody wanted to write them. Because writing one costs a deploy. How do I document a database column without running a migration? Keep the description in the model rather than in the storage engine. A field description is a fact about what the column means to your team; it changes no type, no constraint, no index, and nothing about what the database will accept. When it lives in the diagram, editing it is like editing a comment in a code file: you change it, review it in the same pull request as everything else, and nothing has to run against production for it to take effect. The moment that description is a column comment, it stops being prose and becomes DDL. Now it needs a migration file, and the migration needs a
AI 资讯
Academic social network developed to connect students through knowledge exchange.
SkillShare is an academic social network developed to connect students through knowledge exchange, informal tutoring, and collaboration among users with different skills. The project aims to facilitate collective learning through a modern, dynamic, and responsive web platform. The project was developed as a Course Completion Project (TCC) for the Technical Course in Information Technology at the Escola Técnica de Brasilia (ETB).
AI 资讯
Read-Only by Design: Letting AI Explore Your Database Without the Risk of Writes
There's a moment every developer hits the first time they connect an AI assistant to a real database: it works beautifully, the model writes a clean SELECT , you get your answer in seconds — and then a small, cold thought arrives. What if it had written DELETE instead? That worry is healthy. An AI agent that can query your production database is also, by default, an AI agent that can UPDATE , DROP , and TRUNCATE it. Large language models are probabilistic. They hallucinate. They misread a vague prompt like "clean up the test users" as an instruction to actually delete rows. You don't want the only thing standing between a confused model and your orders table to be good intentions. The fix isn't to keep AI away from your data. It's to make write operations structurally impossible — read-only by design, enforced at layers the model can't talk its way past. This post walks through how to do that properly, from the database grant all the way up to query-level guardrails. Why "just prompt it to be careful" fails The tempting shortcut is to add "only run SELECT queries, never modify data" to your system prompt and call it a day. Don't rely on this. Prompt instructions are suggestions, not enforcement. A cleverly worded user request, an injected instruction hidden in some data the model reads, or a plain misunderstanding can all lead the model to generate a destructive statement anyway. Real read-only access is enforced below the model — in places where no amount of clever text can override it. Think of it as defense in depth, with at least three independent layers: Layer What it stops Enforced by Database permissions Any write reaching the engine SQL GRANT / REVOKE Connection / replica Writes even being routed to a writable node Read replica, read-only transaction Query parser / broker Non-SELECT statements before they run SQL parsing, allowlists Any one of these is decent. All three together mean a write has to defeat your database engine, your routing, and your parser s
开源项目
🔥 NawfalMotii79 / PLFM_RADAR - Open-source, low-cost 10.5 GHz PLFM phased array RADAR syste
GitHub热门项目 | Open-source, low-cost 10.5 GHz PLFM phased array RADAR system | Stars: 24,169 | 204 stars today | 语言: PLSQL
AI 资讯
How to Replicate MySQL to BigQuery with Sling
How to Replicate MySQL to BigQuery with Sling Last updated: July 2026 Getting MySQL data into BigQuery usually means picking a tradeoff. Hand-rolled scripts are cheap to start and expensive to keep alive once schemas drift. Managed connectors are quick to set up but bill per row and put your pipeline behind someone else's control plane. Sling sits in between: a single binary, a few lines of YAML, and a load path that uses BigQuery's own bulk ingest underneath. This guide walks through a real replication, end to end. Everything below — the row counts, the timings, the type mapping — comes from an actual run against a MySQL 8.4 source and a live BigQuery dataset. You can reproduce it. Installation Sling is a single binary with no runtime dependencies. Install it however suits your setup: # macOS / Linux curl -fsSL https://slingdata.io/install.sh | bash # Windows irm https://slingdata.io/install.ps1 | iex # Python pip install sling Confirm it's on your path: sling --version Connection setup Sling needs two connections: the MySQL source and the BigQuery target. Both can be set with sling conns set , which writes them to ~/.sling/env.yaml . MySQL source sling conns set mysql_source type = mysql host = 127.0.0.1 port = 3306 \ user = root password = mypass database = demo Or with a connection string: sling conns set mysql_source url = "mysql://root:mypass@127.0.0.1:3306/demo" BigQuery target BigQuery authenticates with a service-account key. The account needs BigQuery Data Editor and BigQuery Job User on the target project. sling conns set bigquery_target type = bigquery \ project = my-project dataset = demo \ key_file = /path/to/service-account.json If you have a Google Cloud Storage bucket handy, add gc_bucket=my-bucket . Sling will stage batches there and trigger a BigQuery load job from GCS, which is the fastest bulk path. Without a bucket, Sling stages locally and still loads in bulk — that's the setup used for every number in this guide. Test both connections sling c
AI 资讯
Five SQL Bugs That Never Threw an Error
A week cleaning 290 booking records taught me more about silent failure than any error message ever has Last week I cleaned a deliberately messy dataset; 290 booking records from Safari Connect, Nairobi bus platform, 21 columns, 23 catalogued data problems. Class exercise, but the data was built from real failure modes. The problems I'd been warned about took an afternoon. The ones that cost me were the five that ran perfectly, returned plausible output, and were wrong. Every one of these produced a result. None produced an error. 1. The date heuristic that silently dropped five bookings The dataset had three date formats in one column: 2024-09-15 , 15/09/2024 ,and 09-25-2024 . Two of those are ambiguous - 01-18-2024 is unmistakably MM-DD-YYYY because there's no month 18, but 04-10-2024 could be either. The supplied guide handled it like this: UPDATE bookings_staging SET departure_date = TO_DATE ( departure_date , 'MM-DD-YYYY' ):: TEXT WHERE departure_date LIKE '%-%' AND LENGTH ( departure_date ) = 10 AND SPLIT_PART ( departure_date , '-' , 2 ):: INTEGER > 12 ; Read that last condition. If the second component is too large to be a month,this must be month-first. Reasonable logic - and it only fires when the day happens to be 13 or higher. Five rows had days between 1 and 12. They never converted. Then the next step filtered on ISO format: INSERT INTO bookings SELECT ... FROM bookings_staging WHERE departure_date SIMILAR TO '[0-9]{4}-[0-9]{2}-[0-9]{2}' ; ...and dropped them. No error. No warning. Five completed bookings and KES 3,840 of revenue gone from every downstream total. The guide's expected row count was written as "~280+", which is loose enough to hide it. The fix is to match on shape, not to infer from values: WHERE departure_date ~ '^ \d {2}- \d {2}- \d {4}$' Anchored patterns are mutually exclusive, so you can classify every row before touching any of it: SELECT CASE WHEN departure_date ~ '^ \d {4}- \d {2}- \d {2}$' THEN 'ISO' WHEN departure_date ~ '^ \d
AI 资讯
Your Database Is Making 4 Promises. Here's What ACID Means.
Introduction Your program keeps opening transactions. A signup writes a new user row. A checkout debits one account and credits another. A form submission updates three related tables at once. You wrap it all in BEGIN and COMMIT and move on, trusting that the database will handle whatever happens in between. Most of the time it does. But what is it actually promising you when it handles that? And what does it have to do behind the scenes to keep that promise? Say a user transfers ₹1,000 from Account A to Account B. The application runs two updates: subtract 1,000 from A, add 1,000 to B. Now say the server crashes right after the first update runs but before the second one does. Account A: -₹1,000 Account B: +₹0 That money didn't move. It vanished. No error message fixes that, and no user accepts "the server restarted" as an explanation for their missing balance. This is the exact problem a set of guarantees called ACID was built to solve. Most developers can recite the acronym, Atomicity, Consistency, Isolation, Durability, without being able to explain what any of the four words actually promise, or what the database has to do internally to keep those promises. This article tries to fix that. -- 1. What Is a Transaction? Before ACID makes sense, you need to understand what a transaction actually is. A transaction is a group of one or more database operations treated as a single logical unit of work. Either the whole group succeeds, or none of it does. The bank transfer above is a textbook transaction: two updates that only make sense together. In SQL, a transaction usually looks like this: BEGIN ; UPDATE accounts SET balance = balance - 1000 WHERE id = 1 ; UPDATE accounts SET balance = balance + 1000 WHERE id = 2 ; COMMIT ; BEGIN tells the database "everything from here on is one unit." COMMIT tells it "we're done, make it permanent." If something goes wrong in between, a constraint violation, a crash, the application deciding to cancel, the database can issue a RO
开发者
AWS Introduces Native Vector Search for DynamoDB
Amazon DynamoDB recently introduced native vector search, allowing developers to store embeddings alongside application data and run approximate nearest-neighbor queries directly from DynamoDB without using a separate vector database. The feature supports filtered similarity searches and configurable vector indexes for semantic search workloads. By Renato Losio
AI 资讯
Modern IT Helpdesk & Ticketing System Built with PHP Native & MySQL
Are you looking for a clean, efficient, and modern way to manage IT support requests? Stop dealing with messy manual reports via chat and start using a professional ticketing system! In this video, I’m showcasing "HelpdeskKu"—a powerful, custom-built IT ticketing system designed for efficiency and ease of use. It’s built using pure PHP Native (making it fast and easy to customize) and styled with a sleek Dark Obsidian theme using Tailwind CSS. This app features three user roles (Admin, IT Support, and User) with an automated workflow, real-time analytics, and secure session management.
产品设计
Why 'WHERE x = NULL' Never Works in SQL (And What to Use Instead)
Adapted from the SQL Essentials Companion Guide . You write a query to find every customer with no phone number on file. WHERE phone = NULL looks obviously correct — and it returns zero rows, even though you can see NULL sitting right there in the column. Nothing crashes. No error. The query just quietly lies to you about what's in the table. This isn't SQL being broken. It's SQL being consistent about something most languages don't force you to think about: NULL doesn't mean "nothing," it means "unknown." And you can't compare something to unknown with = and expect a real answer. What's actually happening Take this table: -- customers | id | name | phone | | ----|-------------|------------| | 1 | Jordan Lee | 555 - 0142 | | 2 | Sam Rivera | NULL | | 3 | Alex Chen | 555 - 0198 | SELECT name FROM customers WHERE phone = NULL ; -- returns 0 rows SQL doesn't evaluate conditions as just true or false — it has a third result: unknown . phone = NULL asks "does this unknown value equal this other unknown value?" There's no way to answer that, so SQL returns UNKNOWN for every single row, including Sam Rivera's. And WHERE only keeps rows where the condition is TRUE . UNKNOWN doesn't qualify, so the row gets filtered out — the exact same as if it had evaluated to FALSE . This is true even for the row that "should" match. NULL = NULL isn't TRUE — it's also UNKNOWN . NULL never equals anything, not even another NULL . That's the whole rule, and it applies uniformly, which is why = can't be patched into working here — it's not almost right, it's answering a different question than the one you're asking. The fix, step by step Recognize the symptom : a query that runs cleanly but returns fewer rows than it should — especially zero rows when you can see matching data — with a NULL column somewhere in the WHERE clause. Swap = for IS NULL (or != for IS NOT NULL ). These are dedicated operators built specifically to test for absence, not comparison operators being asked to do somethin
AI 资讯
Sandboxes That Cost Nothing
If you work with external APIs, you know the problem. There is no dev.github.com , no staging.api.companieshouse.gov.uk , no test endpoint for the thing you actually depend on. Production is the only source. So how do you get a development environment without re-fetching everything you already have? The usual answer is to copy: duplicate the warehouse, or keep a separate dev database and sync it periodically. Both are slow, both drift, and both cost storage in proportion to the number of people on the team. Interlace does something else. An environment is not a copy of your data, it is a set of views over it. Fingerprints first Every model gets a fingerprint: a hash of its canonical SQL — or its Python source — together with its strategy configuration and its upstream fingerprints. A build writes an immutable physical table named after that fingerprint. interlace__main.orders__a1b2c3 That table never changes. If the model's definition changes, the new version gets a new fingerprint and a new table, and the old one stays exactly where it is. An environment is then just a set of views pointing at fingerprinted tables. Production is the unprefixed namespace; every other environment prefixes its schema. Environment View for main.orders prod main.orders dev dev__main.orders pr-142 pr-142__main.orders Consumers and BI tools connect to main.orders and never learn that a fingerprint exists. There is no environment list to configure, either — an environment exists once something has been promoted to it. Why the sandbox is free Here is where the re-fetching problem disappears. Applying to a sandbox does not rebuild models whose fingerprint already exists. It points the sandbox's views at the tables production already built. interlace apply --env dev Change one model out of forty and the sandbox builds one model. The other thirty-nine are reused — not copied, reused, the same physical tables production is reading. The expensive source extract that ran this morning is the table
AI 资讯
I Reverse-Engineered a Restaurant ERP With No Documentation. Here's What It Taught Me About Being a Self-Taught Developer.
There is no manual for TronSoft. No API reference, no schema diagram, no forum thread explaining why a comanda refuses to close. If you want to understand it, you open the database and start pulling threads until something makes sense. That's exactly what I did — for months, on top of my actual job. The problem nobody wrote down I'm the Operations Manager at a restaurant in Itaúna, a mid-sized town in Minas Gerais, Brazil. I'm also the only person there who writes software. Not because I was hired to — because the restaurant runs on a Brazilian ERP called TronSoft, built on a Firebird database, and Firebird doesn't come with the kind of ecosystem you get around Postgres or MySQL. No Stack Overflow flood of answers. No official docs beyond a thin operator manual. Vendor support exists, but it's slow, and it doesn't scale to "I want to automate this specific internal workflow at 11pm on a Tuesday." So when I needed to automate payment reconciliation, close out comandas without touching the vendor's fragile UI, and trigger fiscal document emission (NFC-e) reliably, I didn't have a spec to follow. I had a live production database and a lot of curiosity. Learning a system by watching it think I started the way you'd expect: opening tables, guessing at relationships, breaking things in a test environment until I understood why they broke. Over time that turned into something more systematic — I ended up documenting 390 tables and 514 foreign keys across roughly 40 functional modules, entirely from observation. No vendor documentation, no source code access. Just structure, inference, and a lot of trial and error. Some of what I learned only reveals itself under pressure: Firebird's SQL dialect has its own quirks — FIRST 1 instead of LIMIT , for one. Small thing, but it breaks every query you copy-paste from a Postgres tutorial. Primary keys aren't auto-incrementing in the way you'd assume. They're driven by generators ( GEN_ID ), and if you write a record without syncing
AI 资讯
iris-agentic-dev -- Give Your AI a Live Connection to IRIS, Part 1: The Problem, the Tool, and Getting Started
Part 1 of a series. Part 2 covers the full tool catalog. Part 3 covers ObjectScript skills. Part 4 covers benchmarking and measuring what actually improves. The Problem Hiding in the Comments Thomas Mazur's post "Frogs, Chickens, AI, and VS Code" on VS Code productivity — Peacock, scoped workspace files, Copilot Agent mode — drew a sharper problem in the comments. Pietro Di Leo and Mike.W pointed out that when you work server-side in VS Code, the isfs:// workspace most production IRIS shops use, Copilot can only see the files open in your editor . It cannot index the virtual filesystem. On a mature IRIS application with thousands of classes, the AI works through a keyhole. John Murray pointed people at a project I've been building — iris-agentic-dev — and noted no Developer Community article existed for it yet. So here it is: why the problem exists, how the tool addresses it, and how to get it running in about five minutes. Why the AI Can't See Your Namespace When you open an isfs:// workspace, your IRIS classes live on the server, not on disk. The VS Code ObjectScript extension streams them to you on demand via the Atelier API — open a class, it fetches it; save it, it writes back. This works beautifully for editing. AI assistants such as Copilot work differently. They need a picture of the code around the file you're editing. Who calls this method? What inherits from this class? What other code touches this global? On a local project, the assistant can scan the files to answer those questions. An isfs:// workspace materializes files only when you open them, so there is nothing complete to scan. For a new project with a handful of classes, that may be tolerable. For a production IRIS system — ten thousand classes, Ensemble productions, custom %Library subclasses, business logic accumulated across years of development — the AI becomes nearly useless for the hard questions. It can help you write a new method if you paste in the surrounding context yourself. It cannot
AI 资讯
Running the same SQL checks in a browser, CLI and pull request
I wanted one set of SQL checks to work in three places: while exploring a query, from a terminal and during code review. That became SQL Atlas. It is a local, deterministic SQL analyzer with a browser interface, a CLI and a GitHub Action. This article covers the interfaces, the CI contract and the limits of static SQL analysis. One analyzer, three interfaces The analyzer returns structured data instead of printing messages directly. Each interface decides how to present the same result: The browser explains findings and links them to learning material. The CLI returns text, JSON or Markdown and uses stable exit codes. The GitHub Action converts findings into file annotations and a job summary. Keeping presentation outside the analyzer prevents the CLI and Action from becoming separate implementations with different behavior. A CLI needs a contract The CLI accepts one or more files, or SQL through standard input: npx --yes sql-atlas@0.5.1 analyze query.sql echo "SELECT * FROM customers;" | npx --yes sql-atlas@0.5.1 analyze - It supports PostgreSQL, MySQL, Oracle, SQLite, SQL Server and a generic mode. Output can be text for a person, JSON for another program or Markdown for an issue or report. Exit codes are part of the interface: 0 means analysis completed and the configured policy passed. 1 means analysis completed but a severity or score threshold failed. 2 means the command or input was invalid. This distinction matters in CI. A policy failure is not the same as a broken invocation. Turning findings into pull request feedback The Action runs as a bundled Node 24 program and does not download dependencies at runtime. A minimal workflow looks like this: name : SQL review on : pull_request : paths : - " **/*.sql" permissions : contents : read jobs : sql-atlas : runs-on : ubuntu-latest steps : - uses : actions/checkout@v7 - uses : milekv/sql-atlas@v0.5.1 with : paths : | migrations/**/*.sql schema/**/*.sql dialect : postgresql fail-on : critical min-score : 60 Findin
AI 资讯
SQL Window Functions: How to Get the Top Row Per Group
By the end of this page you can answer the question that stops most people the first week they write SQL: which row is the best one in each category. You will know OVER and PARTITION BY , the three ranking functions and how each treats a tie, a running total, and LAG for comparing a row to the one before it. It is about twenty-five minutes. Here is what to actually do with it. The next time you write GROUP BY genre and get back a best rating without the name attached to it, stop rewriting the GROUP BY . Add ROW_NUMBER() OVER (PARTITION BY genre ORDER BY rating DESC) to the plain query instead, then keep the rows numbered 1. That is the whole move, and it replaces a query most people never get working. The short version: a window function adds a calculated column to each row while leaving every row in place. Grouping collapses rows. A window looks at them. One idea decides everything else on this page, so it gets the picture. Both halves do the same arithmetic over the same four rows, and only one of them still has four rows at the end. The original carries a diagram here. In words: Two panels side by side, each starting from the same stack of four identical row shapes. The left panel is labelled GROUP BY. Its four rows funnel down through a single arrow into one row at the bottom, and the four original rows are shown faded to indicate they are gone from the result. Only one row remains. The right panel is labelled OVER. Its four rows stay exactly where they are, at full strength, and each one gains a small badge on its right hand side holding a number: one, two, three, four. Nothing funnels and nothing is faded. The contrast is the whole idea: the left panel ends with a single summary row and no way to say which original row it came from, while the right panel ends with all four rows still present, each carrying its own calculated value. The worked example is real. Every number on this page comes from a published portfolio project: finding the genuinely overlooked g