func (cfs CFS) newDirNode() *Node {
	return &Node{
		cfs:  cfs,
		ID:   cfs.newUniqueID(),
		Mode: os.ModeDir | defaultPerms,
	}
}
newDirNode returns a new node struct corresponding to a directory.
package main
import (
	"context"
	"database/sql"
	"os"
	"syscall"
	"bazil.org/fuse"
	"bazil.org/fuse/fs"
	"github.com/cockroachdb/cockroach-go/crdb"
)
const rootNodeID = 1
const (
	fsSchema = `
CREATE DATABASE IF NOT EXISTS fs;
CREATE TABLE IF NOT EXISTS fs.namespace (
  parentID INT,
  name     STRING,
  id       INT,
  PRIMARY KEY (parentID, name)
);
CREATE TABLE IF NOT EXISTS fs.inode (
  id    INT PRIMARY KEY,
  inode STRING
);
CREATE TABLE IF NOT EXISTS fs.block (
  id    INT,
  block INT,
  data  BYTES,
  PRIMARY KEY (id, block)
);
`
)
var _ fs.FS = &CFS{}                
var _ fs.FSInodeGenerator = &CFS{}  
type CFS struct {
	db *sql.DB
}
func initSchema(db *sql.DB) error {
	_, err := db.Exec(fsSchema)
	return err
}
func (cfs CFS) create(ctx context.Context, parentID uint64, name string, node *Node) error {
	inode := node.toJSON()
	const insertNode = `INSERT INTO fs.inode VALUES ($1, $2)`
	const insertNamespace = `INSERT INTO fs.namespace VALUES ($1, $2, $3)`
	err := crdb.ExecuteTx(ctx, cfs.db, nil  , func(tx *sql.Tx) error {
		if _, err := tx.Exec(insertNode, node.ID, inode); err != nil {
			return err
		}
		if _, err := tx.Exec(insertNamespace, parentID, name, node.ID); err != nil {
			return err
		}
		return nil
	})
	return err
}
func (cfs CFS) remove(ctx context.Context, parentID uint64, name string, checkChildren bool) error {
	const lookupSQL = `SELECT id FROM fs.namespace WHERE (parentID, name) = ($1, $2)`
	const deleteNamespace = `DELETE FROM fs.namespace WHERE (parentID, name) = ($1, $2)`
	const deleteInode = `DELETE FROM fs.inode WHERE id = $1`
	const deleteBlock = `DELETE FROM fs.block WHERE id = $1`
	err := crdb.ExecuteTx(ctx, cfs.db, nil  , func(tx *sql.Tx) error {
		var id uint64
		if err := tx.QueryRow(lookupSQL, parentID, name).Scan(&id); err != nil {
			return err
		}
		if checkChildren {
			if err := checkIsEmpty(tx, id); err != nil {
				return err
			}
		}
		if _, err := tx.Exec(deleteNamespace, parentID, name); err != nil {
			return err
		}
		if _, err := tx.Exec(deleteInode, id); err != nil {
			return err
		}
		if _, err := tx.Exec(deleteBlock, id); err != nil {
			return err
		}
		return nil
	})
	return err
}
func (cfs CFS) lookup(parentID uint64, name string) (*Node, error) {
	return getInode(cfs.db, parentID, name)
}
func (cfs CFS) list(parentID uint64) ([]fuse.Dirent, error) {
	rows, err := cfs.db.Query(`SELECT name, id FROM fs.namespace WHERE parentID = $1`, parentID)
	if err != nil {
		return nil, err
	}
	var results []fuse.Dirent
	for rows.Next() {
		dirent := fuse.Dirent{Type: fuse.DT_Unknown}
		if err := rows.Scan(&dirent.Name, &dirent.Inode); err != nil {
			return nil, err
		}
		results = append(results, dirent)
	}
	if err := rows.Err(); err != nil {
		return nil, err
	}
	return results, nil
}
func validateRename(tx *sql.Tx, source, destination *Node) error {
	if destination == nil {
		return nil
	}
	if source.isDir() {
		if destination.isDir() {
			return checkIsEmpty(tx, destination.ID)
		}
		return fuse.Errno(syscall.ENOTDIR)
	}
	if destination.isDir() {
		return fuse.Errno(syscall.EISDIR)
	}
	return nil
}
func (cfs CFS) rename(
	ctx context.Context, oldParentID, newParentID uint64, oldName, newName string,
) error {
	if oldParentID == newParentID && oldName == newName {
		return nil
	}
	const deleteNamespace = `DELETE FROM fs.namespace WHERE (parentID, name) = ($1, $2)`
	const insertNamespace = `INSERT INTO fs.namespace VALUES ($1, $2, $3)`
	const updateNamespace = `UPDATE fs.namespace SET id = $1 WHERE (parentID, name) = ($2, $3)`
	const deleteInode = `DELETE FROM fs.inode WHERE id = $1`
	err := crdb.ExecuteTx(ctx, cfs.db, nil  , func(tx *sql.Tx) error {
		srcObject, err := getInode(tx, oldParentID, oldName)
		if err != nil {
			return err
		}
		destObject, err := getInode(tx, newParentID, newName)
		if err != nil && err != sql.ErrNoRows {
			return err
		}
		if err := validateRename(tx, srcObject, destObject); err != nil {
			return err
		}
		if destObject == nil {
			if _, err := tx.Exec(deleteNamespace, oldParentID, oldName); err != nil {
				return err
			}
			if _, err := tx.Exec(insertNamespace, newParentID, newName, srcObject.ID); err != nil {
				return err
			}
		} else {
			if _, err := tx.Exec(deleteNamespace, oldParentID, oldName); err != nil {
				return err
			}
			if _, err := tx.Exec(updateNamespace, srcObject.ID, newParentID, newName); err != nil {
				return err
			}
			if _, err := tx.Exec(deleteInode, destObject.ID); err != nil {
				return err
			}
		}
		return nil
	})
	return err
}
func (cfs CFS) Root() (fs.Node, error) {
	return &Node{cfs: cfs, ID: rootNodeID, Mode: os.ModeDir | defaultPerms}, nil
}
func (cfs CFS) GenerateInode(parentInode uint64, name string) uint64 {
	return cfs.newUniqueID()
}
func (cfs CFS) newUniqueID() (id uint64) {
	if err := cfs.db.QueryRow(`SELECT unique_rowid()`).Scan(&id); err != nil {
		panic(err)
	}
	return
}
func (cfs CFS) newFileNode() *Node {
	return &Node{
		cfs:  cfs,
		ID:   cfs.newUniqueID(),
		Mode: defaultPerms,
	}
}